在三維空間中,利用拋物線公式計算彈道,獲得一個發射初速度,讓導彈打擊到指定地點
效果:
工具
腳本使用:只需指定目標點便可
能夠經過Hight調整導彈的飛行高度
能夠經過Gravity調整導彈的飛行速度測試
經過如下兩個腳本實現。工具腳本計算彈道,Missile腳本每幀更新導彈位置spa
PhysicsUtil.cscode
using UnityEngine; /// <summary> 物理計算工具 /// <para>ZhangYu 2018-05-10</para> /// </summary> public static class PhysicsUtil { /// <summary> 獲取拋物線初始速度 </summary> /// <param name="start">起點</param> /// <param name="end">終點</param> /// <param name="heightOff">高度偏移(相對於兩個點的最高位置 高出多少)</param> /// <param name="gravity">重力加速度(負數)</param> /// <returns></returns> public static Vector3 GetParabolaInitVelocity(Vector3 start, Vector3 end, float heightOff = 10, float gravity = -9.8f) { float topY = Mathf.Max(start.y, end.y) + heightOff; float d1 = topY - start.y; float d2 = topY - end.y; float g2 = 2 / -gravity; float t1 = Mathf.Sqrt(g2 * d1); float t2 = Mathf.Sqrt(g2 * d2); float t = t1 + t2; float vX = (end.x - start.x) / t; float vZ = (end.z - start.z) / t; float vY = -gravity * t1; Vector3 v0 = new Vector3(vX, vY, vZ); return v0; } /// <summary> 計算拋物線物體在下一幀的位置 </summary> /// <param name="position">初始位置</param> /// <param name="velocity">移動速度</param> /// <param name="gravity">重力加速度</param> /// <param name="time">飛行時間</param> /// <returns></returns> public static Vector3 GetParabolaNextPosition(Vector3 position, Vector3 velocity, float gravity, float time) { float dY = 0.5f * gravity * time * time; return position + velocity * time + new Vector3(0, dY, 0); } }
MissileTest.csorm
using UnityEngine; /// <summary> /// 拋物線導彈測試 /// <para>計算彈道和轉向</para> /// <para>ZhangYu 2019-02-27</para> /// </summary> public class MissileTest : MonoBehaviour { public Transform target; // 目標 public float hight = 16f; // 拋物線高度 public float gravity = -9.8f; // 重力加速度 private Vector3 end; // 目標位置 private Vector3 position; // 個人位置 private Vector3 velocity; // 運動速度 private void Start() { end = target.position; position = transform.position; velocity = PhysicsUtil.GetParabolaInitVelocity(position, end, hight, gravity); transform.LookAt(PhysicsUtil.GetParabolaNextPosition(position, velocity, gravity, Time.deltaTime)); } private void Update() { // 計算位移 float deltaTime = Time.deltaTime; position = PhysicsUtil.GetParabolaNextPosition(position, velocity, gravity, deltaTime); transform.position = position; velocity.y += gravity * deltaTime; // 計算轉向 transform.LookAt(PhysicsUtil.GetParabolaNextPosition(position, velocity, gravity, deltaTime)); // 簡單模擬一下碰撞檢測 if (position.y <= end.y) enabled = false; } }