|
最近在学习 B站某不知名大佬:奥飒姆_Awesome 的视频,发现自己的一些知识缺漏,本文对一些困惑的点进行学习和总结。
附上主页:奥飒姆_Awesome的个人空间_哔哩哔哩_Bilibili
项目链接: https://github.com/RedFF0000/TopDownShooter
(十分惋惜的是,Awesome大佬已经停更一年了,可能在忙其他的吧,还是很感谢他的分享,讲的很好。)
Transform.right的妙用
问题:让枪械转向鼠标所在位置
方法:Transform.right = mousePos
分析:在unity3d中,我们经常用LookAt()函数来改变物体的朝向。在2d游戏中是否有更好的办法呢?
参考API的解释(Transform-right - Unity 脚本 API),Transform.right/up/forward代表的是物体的 右、上、前方向对应世界坐标的向量,对其赋值会使得物体发生旋转。
我们假设枪口指向的位置是物体的 “右”方向,则直接使用 Transform.right = mousePos,即可完成朝向。
真的是非常的简便。
参考:https://its201.com/article/qq_19895789/83149394
火箭弹的设计思路
1. 火箭弹初始化
核心代码:
IEnumerator DelayFire(float delay)
{
yield return new WaitForSeconds(delay);
int median = rocketNum / 2;
for (int i = 0; i < rocketNum; i++)
{
GameObject bullet = ObjectPool.Instance.GetObject(bulletPrefab);
bullet.transform.position = muzzlePos.position;
if (rocketNum % 2 == 1)
{
bullet.transform.right = Quaternion.AngleAxis(rocketAngle * (i - median), Vector3.forward) * direction;
}
else
{
bullet.transform.right = Quaternion.AngleAxis(rocketAngle * (i - median) + rocketAngle / 2, Vector3.forward) * direction;
}
bullet.GetComponent<Rocket>().SetTarget(mousePos);
}
}
Quaternion-AngleAxis - Unity 脚本 API
创建一个围绕axis旋转angle度的旋转。
问题1:第二个参数为什么是 Vector3.forward
// 参考api
//
// 摘要:
// Shorthand for writing Vector3(1, 0, 0).
public static Vector3 right { get; }
//
// 摘要:
// Shorthand for writing Vector3(-1, 0, 0).
public static Vector3 left { get; }
//
// 摘要:
// Shorthand for writing Vector3(0, 1, 0).
public static Vector3 up { get; }
//
// 摘要:
// Shorthand for writing Vector3(0, 0, -1).
public static Vector3 back { get; }
//
// 摘要:
// Shorthand for writing Vector3(0, 0, 1).
public static Vector3 forward { get; }
Vector3.forward代表的是unity中的Z轴方向
因为教程是2d游戏教程,因此以z轴作为参考轴,就能够实现2d视角下的子弹偏移(白色箭头为子弹轨迹)
将子弹轨迹分两种情况,第一种是奇数个火箭弹(rocketNum %2==1)。
if (rocketNum % 2 == 1)
{
bullet.transform.right = Quaternion.AngleAxis(rocketAngle * (i - median), Vector3.forward) * direction;
}
第二种是偶数个火箭弹
else
{
bullet.transform.right = Quaternion.AngleAxis(rocketAngle * (i - median) + rocketAngle / 2, Vector3.forward) * direction;
}
2. 每个火箭弹的逻辑
核心逻辑:每个子弹的转向和移动 private void FixedUpdate()
{
direction = (targetPos - transform.position).normalized;
if (!arrived)
{
transform.right = Vector3.Slerp(transform.right, direction, lerp / Vector2.Distance(transform.position, targetPos));
rigidbody.velocity = transform.right * speed;
}
if (Vector2.Distance(transform.position, targetPos) < 1f && !arrived)
{
arrived = true;
}
}
transform.right = Vector3.Slerp(transform.right, direction, lerp / Vector2.Distance(transform.position, targetPos));
rigidbody.velocity = transform.right * speed;Vector3.Slerp:在两个向量之间进行球面插值
官网API:Vector3-Slerp - Unity 脚本 API
public staticVector3Slerp(Vector3a,Vector3b, floatt);
其中:a代表起始方向,b代表目标方向, t的范围是[0, 1],t为0.5即代表a和b方向的中间方向,以此类推。
这里的起始方向是:子弹的朝向,终止方向是:目标方向,这两个都很好理解。
t为什么是:lerp / Vector2.Distance(transform.position, targetPos) ?
如果使用固定值 lerp ,在FixUpdate每帧调用,会导致子弹到达目标点的转向不可控,可能导致距离较远时转向过头,或者距离不到时转向过小。
Vector2.Distance(transform.position, targetPos) 代表距离目标点的距离,除以这个距离,可以保证:
距离目标点较远时转向较小,距离目标点较近时转向较大。
这里有个疑惑:Vector2.Distance(transform.position, targetPos) 不会等于0吗?
有大佬了解的话可以解答下,我猜测是因为C#的float计算基本不会有相等的情况,但是不会有万一吗? 最终效果:可以看上面的链接视频
激光枪设计思路
1. debug版激光枪
核心代码:
protected override void Fire()
{
RaycastHit2D hit2D = Physics2D.Raycast(muzzlePos.position, direction, 30);
// 只能在debug模式的时候看到
Debug.DrawLine(muzzlePos.position, hit2D.point);
}
Physics2D.Raycast:向场景中的碰撞体投射射线,RaycastHit2D返回的投射数量。
Physics2D-Raycast - Unity 脚本 API
2. LineRender组件
关键参数如下:
游戏中的效果:
关键代码:
protected override void Fire()
{
RaycastHit2D hit2D = Physics2D.Raycast(muzzlePos.position, direction, 30);
// Debug.DrawLine(muzzlePos.position, hit2D.point);
laser.SetPosition(0, muzzlePos.position);
laser.SetPosition(1, hit2D.point);
其中laser.SetPosition是设置激光的起始位置。
再加上一点点粒子特效,最终游戏中的效果如下:
3. 使用URP进行激光后处理
这部分我还没消化,后面学习了会补充上笔记。 最终效果:
高速枪械(仅看得到轨迹)
基本原理和激光枪设计类似,只是修改了LineRender的颜色 看下最终效果:
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|