在三维空间中,利用抛物线公式计算弹道,得到一个发射初速度,让导弹打击到指定地点
效果:脚本使用:只需指定目标点即可可以通过Hight调整导弹的飞行高度可以通过Gravity调整导弹的飞行速度
通过以下两个脚本实现。工具脚本计算弹道,Missile脚本每帧更新导弹位置
PhysicsUtil.cs
using UnityEngine;///物理计算工具/// public static class PhysicsUtil { /**findInitialVelocity * Finds the initial velocity of a projectile given the initial positions and some offsets * @param Vector3 startPosition - the starting position of the projectile * @param Vector3 finalPosition - the position that we want to hit * @param float maxHeightOffset (default=0.6f) - the amount we want to add to the height for short range shots. We need enough clearance so the * ball will be able to get over the rim before dropping into the target position * @param float rangeOffset (default=0.11f) - the amount to add to the range to increase the chances that the ball will go through the rim * @return Vector3 - the initial velocity of the ball to make it hit the target under the current gravity force. * * Vector3 tt = findInitialVelocity (gameObject.transform.position, target.transform.position); Rigidbody rigidbody = gameObject.GetComponentZhangYu 2018-05-10 ///(); Debug.Log (tt); rigidbody.AddForce(tt*rigidbody.mass,ForceMode.Impulse); */ public static Vector3 GetParabolaInitVelocity(Vector3 from, Vector3 to, float gravity = 9.8f, float heightOff = 0.0f, float rangeOff = 0.11f) { // get our return value ready. Default to (0f, 0f, 0f) Vector3 newVel = new Vector3(); // Find the direction vector without the y-component /// /找到未经y分量的方向矢量// Vector3 direction = new Vector3(to.x, 0f, to.z) - new Vector3(from.x, 0f, from.z); // Find the distance between the two points (without the y-component) //发现这两个点之间的距离(不y分量)// float range = direction.magnitude; // Add a little bit to the range so that the ball is aiming at hitting the back of the rim. // Back of the rim shots have a better chance of going in. // This accounts for any rounding errors that might make a shot miss (when we don't want it to). range += rangeOff; // Find unit direction of motion without the y component Vector3 unitDirection = direction.normalized; // Find the max height // Start at a reasonable height above the hoop, so short range shots will have enough clearance to go in the basket // without hitting the front of the rim on the way up or down. float maxYPos = to.y + heightOff; // check if the range is far enough away where the shot may have flattened out enough to hit the front of the rim // if it has, switch the height to match a 45 degree launch angle //if (range / 2f > maxYPos) // maxYPos = range / 2f; if (maxYPos < from.y) maxYPos = from.y; // find the initial velocity in y direction /// /发现在y方向上的初始速度// float ft; ft = -2.0f * gravity * (maxYPos - from.y); if (ft < 0) ft = 0f; newVel.y = Mathf.Sqrt(ft); // find the total time by adding up the parts of the trajectory // time to reach the max //发现的总时间加起来的轨迹的各部分// //时间达到最大// ft = -2.0f * (maxYPos - from.y) / gravity; if (ft < 0) ft = 0f; float timeToMax = Mathf.Sqrt(ft); // time to return to y-target //时间返回到y轴的目标// ft = -2.0f * (maxYPos - to.y) / gravity; if (ft < 0) ft = 0f; float timeToTargetY = Mathf.Sqrt(ft); // add them up to find the total flight time //把它们加起来找到的总飞行时间// float totalFlightTime; totalFlightTime = timeToMax + timeToTargetY; // find the magnitude of the initial velocity in the xz direction /// /查找的初始速度的大小在xz方向// float horizontalVelocityMagnitude = range / totalFlightTime; // use the unit direction to find the x and z components of initial velocity //使用该单元的方向寻找初始速度的x和z分量// newVel.x = horizontalVelocityMagnitude * unitDirection.x; newVel.z = horizontalVelocityMagnitude * unitDirection.z; return newVel; } /// 计算抛物线物体在下一帧的位置 /// 初始位置 /// 移动速度 /// 重力加速度 /// 飞行时间 ///public static Vector3 GetParabolaNextPosition(Vector3 position, Vector3 velocity, float gravity, float time) { velocity.y += gravity * time; return position + velocity * time; }}
Missile.cs
using UnityEngine;////// 抛物线导弹/// public class Missile : MonoBehaviour { public Transform target; // 目标 public float hight = 16f; // 抛物线高度 public float gravity = -9.8f; // 重力加速度 private Vector3 position; // 我的位置 private Vector3 dest; // 目标位置 private Vector3 velocity; // 运动速度 private float time = 0; // 运动时间 private void Start() { dest = target.position; position = transform.position; velocity = PhysicsUtil.GetParabolaInitVelocity(position, dest, gravity, hight, 0); 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; time += deltaTime; velocity.y += gravity * deltaTime; // 计算转向 transform.LookAt(PhysicsUtil.GetParabolaNextPosition(position, velocity, gravity, deltaTime)); // 简单模拟一下碰撞检测 if (position.y <= dest.y) enabled = false; }}计算弹道和转向 ///ZhangYu 2019-02-27 ///