Unity 定点投射固定高度抛物线
假设同一平面中有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
实际上以上三个公式就可以解决所有这类问题,至于抛物线的一些额外公式都非常容易通过这三个公式推导,就不再列举了。
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 }
上面的脚本采用了固定高度的方式动态计算加速度常量的值,当然感兴趣的读者也可通过固定加速度常量来计算,这样更为简单。