假设同一平面中有AB两点,A点向B点水平射击,很容易想象子弹会沿由A指向B的向量方向前进,经过时间t后到达B点,若此时A点不再水平射击,改为以抛物线的方式向B点投射,同样需要在时间t后击中B点,那么如何确定被修正后的初速度呢。(这时就不得不提那万恶的游戏平衡性了Orz)
想想也不难,只要保证初速度在A指向B方向的速度分量与加速度分量与之前水平射击时一致即可。进一步简化问题则为,额外计算重力加速度g值产生的y轴方向的初速度。
匀变速运动中的一些与加速度相关公式:
1. Vt-V0=at;
2.Vt2-V02=2as;
3.s=V0t 0.5*at2
实际上以上三个公式就可以解决所有这类问题,至于抛物线的一些额外公式都非常容易通过这三个公式推导,就不再列举了。
代码语言:javascript复制 1 using UnityEngine;
2
3 public class ParabolaBullet : Bullet
4 {
5 //高度
6 public float height = 3.0f;
7
8 private Vector3 Vyt;
9 private Vector3 Vxt;
10 private Vector3 For;
11 private float Gy;
12 private float Vyo;
13 private float Vxo;
14
15 public override void Init()
16 {
17 TargetPos = Target != null ? Target.transform.position : TargetPos;
18
19 //平面向量
20 var of = TargetPos.FixV3ToFloor() - transform.position.FixV3ToFloor();
21 //平面距离
22 var Sx = of.magnitude;
23 //平面末速度
24 var Vxt = Mathf.Sqrt(Mathf.Abs(2 * Acceleration * Sx Velocity * Velocity));
25 //平面运动时间
26 var Tx = Acceleration == 0 ? Sx / Velocity : (Vxt - Velocity) / Acceleration;
27 //到达最高点时间为平面运动时间的一半
28 var Ty = 0.5f * Tx;
29 //重力加速度
30 Gy = 2 * height / (Ty * Ty);
31 //高度初速度
32 Vyo = Mathf.Sqrt(2 * Gy * height);
33
34 Vxo = Velocity;
35 For = transform.forward;
36 dTime = 0;
37 }
38
39 private float dTime = 0;
40 private void FixedUpdate()
41 {
42 var dt = Time.fixedDeltaTime;
43 dTime = dt;
44 //vt=vo at 两个方向(竖直方向与原始运动方向) 注意重力G为与初速度方向相反,取负
45 Vyt.y = Vyo - Gy * dTime;
46 Vxt = (Vxo Acceleration * dTime) * For.FixV3ToFloor().normalized;
47
48 //分别在两个方向上进行运动,注意为世界空间
49 transform.Translate(Vxt * dt, Space.World);
50 transform.Translate(Vyt * dt, Space.World);
51
52 //子弹的前向指向两个速度单位向量的和单位向量
53 transform.forward = (Vxt Vyt).normalized;
54 }
55 }
上面的脚本采用了固定高度的方式动态计算加速度常量的值,当然感兴趣的读者也可通过固定加速度常量来计算,这样更为简单。