Unity中炮弹抛物线运动

发表于2017-11-30
评论0 9.5k浏览
比如迫击炮发射的子弹是抛物线运行的,并且在垂直方向上子弹做自由落体运动如果垂直方向上不做自由落体(仅仅是一个匀速的抛物线)有很多简便的方法可以实现比如设置一个起始点一个最高点一个目标点让物体按照这三个点移动就可以稍微复杂点的用dotweenitween设置个路径点按照路径点移动,下面就和大家介绍下开发过程中的炮弹抛物线运动。

下面开始逻辑:迫击炮抛物线击中目标单位需要的参数是:1.目标单位; 2.炮弹的水平速度。

按照初中的物理知识抛物线运动在水平方向是匀速的垂直方向上是v=a*t(v是速度,a是加速度,t是时间)。
也就是说只要得到垂直方向初始化速度让水平方向和垂直方向各自运行就可以了。如果知道目标(距离)和水平速度就能得到飞行的时间.time=distance/speed;在time这段时间内炮弹用1/2的时间上升1/2的时间下降.炮弹发出时在垂直方向上的速度是多少呢?我们可以反过来看在最顶点时炮弹速度是0经过1/2的时间下落到平面,根据v=a*t(也就是speed=重力加速度*1/2*时间),这样就得到了垂直方向的初始化速度。 然后用逻辑控制垂直方向和水平方向各自运行就可以了。
public class Test : MonoBehaviour  
{  
    public const float g = 9.8f;  
    public GameObject target;  
    public float speed = 10;  
    private float verticalSpeed;  
    void Start()  
    {  
        float tmepDistance = Vector3.Distance(transform.position, target.transform.position);  
        float tempTime = tmepDistance / speed;  
        float riseTime, downTime;  
        riseTime = downTime = tempTime / 2;  
        verticalSpeed = g * riseTime;  
        transform.LookAt(target.transform.position);  
    }  
    private float time;  
    void Update()  
    {  
        if (transform.position.y < target.transform.position.y)  
        {  
            //finish  
            return;  
        }  
        time += Time.deltaTime;  
        float test = verticalSpeed - g*time;  
        transform.Translate(transform.forward * speed * Time.deltaTime, Space.World);  
        transform.Translate(transform.up * test * Time.deltaTime, Space.World);  
    }  
} 

实现的效果如下: 

从上面的逻辑中看出炮弹只有水平和垂直方向的位移没有旋转:现实生活中炮弹发出时朝向天空在最高点时炮弹旋转是水平的在下落过程中炮弹朝向要轰炸的单位。下面为炮弹添加旋转逻辑: 首先根据上文水平方向速度和垂直方向的速度能得到tan值,然后计算出调用系统math.atan的到弧度然后弧度转换为角度。这个角度就是炮弹发出时与地面(水平方向)的夹角.然后在各角度在time/2的时间里变为0(最顶点角度为0)然后在下落的过程中角度在继续增大。

最终逻辑如下:
public class Bullet : MonoBehaviour  
{  
    public const float g = 9.8f;  
    public GameObject target;  
    public float speed = 10;  
    private float verticalSpeed;  
    private Vector3 moveDirection;  
    private float angleSpeed;  
    private float angle;  
    void Start()  
    {  
       float tmepDistance = Vector3.Distance(transform.position, target.transform.position);  
        float tempTime = tmepDistance / speed;  
        float riseTime, downTime;  
        riseTime = downTime = tempTime / 2;  
         verticalSpeed = g * riseTime;  
        transform.LookAt(target.transform.position);  
        float tempTan = verticalSpeed / speed;  
        double hu = Math.Atan(tempTan);  
        angle = (float)(180 / Math.PI * hu);  
        transform.eulerAngles = new Vector3(-angle, transform.eulerAngles.y, transform.eulerAngles.z);  
        angleSpeed = angle / riseTime;  
        moveDirection = target.transform.position - transform.position;  
    }  
    private float time;  
    void Update()  
    {  
        if (transform.position.y < target.transform.position.y)  
        {  
            //finish  
            return;  
        }  
        time += Time.deltaTime;  
        float test = verticalSpeed - g * time;  
        transform.Translate(moveDirection.normalized * speed * Time.deltaTime, Space.World);  
        transform.Translate(Vector3.up * test * Time.deltaTime,Space.World);  
        float testAngle = -angle + angleSpeed * time;  
        transform.eulerAngles = new Vector3(testAngle, transform.eulerAngles.y, transform.eulerAngles.z);  
    }  
}  

把上面的代码挂到子弹身上,配置一个目标对象,一个水平速度就可以运行了。
效果如下所示:

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

标签: