Unity 拋物線彈道和轉向

在三維空間中,利用拋物線公式計算彈道,獲得一個發射初速度,讓導彈打擊到指定地點
效果:
彈道效果工具

腳本屬性
腳本使用:只需指定目標點便可
能夠經過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;
    }

}
相關文章
相關標籤/搜索