Unity中炮弹抛物线运动

比如迫击炮发射的子弹是抛物线运行的,并且在垂直方向上子弹做自由落体运动,如果垂直方向上不做自由落体(仅仅是一个匀速的抛物线),有很多简便的方法可以实现,比如设置一个起始点,一个最高点,一个目标点,让物体按照这三个点移动就可以,稍微复杂点的用dotween,itween设置个路径点,按照路径点移动.
下面开始逻辑:
迫击炮抛物线击中目标单位,需要的参数是: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);
    }
}
把上面的代码挂到子弹身上,配置一个目标对象,一个水平速度就可以运行了.效果如下所示:

support: hiramtan@live.com
qq群: 83596104

  • 35
    点赞
  • 90
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是Unity实现物体按抛物线运动的代码示例: ```csharp public class ParabolicMotion : MonoBehaviour { // 起始点、终止点和高度 public Transform startPoint; public Transform endPoint; public float height; // 运动时间 public float timeToReachTarget = 1f; private bool isMoving = false; private float timer = 0f; private Vector3 startPosition; private Vector3 endPosition; void Start() { // 获取起始点和终止点的位置 startPosition = startPoint.position; endPosition = endPoint.position; } void Update() { if (isMoving) { // 计算当前时间与总时间的比例 float t = timer / timeToReachTarget; // 计算当前位置 Vector3 currentPos = ParabolicInterpolation(startPosition, endPosition, height, t); // 更新物体位置 transform.position = currentPos; // 更新计时器 timer += Time.deltaTime; // 判断是否到达终点 if (timer >= timeToReachTarget) { isMoving = false; timer = 0f; } } } public void StartMotion() { isMoving = true; } // 抛物线插值函数 private Vector3 ParabolicInterpolation(Vector3 start, Vector3 end, float height, float t) { Vector3 result = Vector3.zero; // 计算抛物线顶点位置 Vector3 vertex = new Vector3((start.x + end.x) / 2f, height, (start.z + end.z) / 2f); // 计算当前位置 result.x = Mathf.Lerp(start.x, end.x, t); result.y = Mathf.Lerp(start.y, end.y, t) + Mathf.Sin(t * Mathf.PI) * height; result.z = Mathf.Lerp(start.z, end.z, t); return result; } } ``` 在这个示例,我们定义了起始点、终止点和高度等参数,然后在Update函数计算当前位置,利用抛物线插值函数实现物体按抛物线运动。我们还通过StartMotion函数来启动运动,可以通过其他事件来触发该函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值