Unity3D 通过初速度和加速度实现物体曲线运动

1. 本代码实现了3D环境中物体朝着任意方向曲线运动。本质是通过物体的初速度向量和加速度向量来控制物体的运动,lifetime控制物体的飞行时间,currentAngle 控制物体的旋转角度

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class sc_flying : MonoBehaviour
{

    public float speed_ratio_= 5f;

    //每个飞行道具的运动数据
    private Vector3 fly_velocity_; //速度
    private Vector3 fly_acc_velocity_; //加速度
    private float life_cycle_; //生命周期

    private float time_spent_; //已经过去的时间
    private Vector3 currentAngle_; //道具当前角度

    public void Reset(Vector3 start_pos,Vector3 speed,Vector3 speed_acc,float life_cycle)
    {
        //重置飞行数据
        transform.position = start_pos;
        fly_velocity_ = speed * speed_ratio_;
        fly_acc_velocity_ = speed_acc;
        life_cycle_ = life_cycle;

        currentAngle_ = Vector3.zero;
    }
    // Start is called before the first frame update
    void Start()
    {

    }
    
    // Update is called once per frame
    void FixedUpdate()
    {
        if (fly_velocity_ != Vector3.zero)
        {
            flying();
        }

        //飞行生命周期
        life_cycle_ -= Time.fixedDeltaTime;
        if (life_cycle_ <= 0f)
        {
            Destroy(gameObject);
        }

    }


    /// <summary>
    /// 控制飞行速度和位移
    /// </summary>
    private void flying()
    {

        //计算速度 V = v0 + at
        fly_velocity_ += fly_acc_velocity_ * (time_spent_ += Time.fixedDeltaTime);

        //位移轨迹
        transform.position += (fly_velocity_) * Time.fixedDeltaTime;

        //控制旋转
        rotateZaxis();
        rotateYaxis();
    }



    /// <summary>
    /// 旋转道具的Z角度
    /// </summary>
    private void rotateZaxis()
    {
        //该算法使用速度的y/x 的正切值来控制物体绕着Z轴旋转
        //因为除数不能为0,除数为0时使用 y/z 的正切值来控制
        if (fly_velocity_.x != 0)
        {
            currentAngle_.z = Mathf.Atan((fly_velocity_.y) / Mathf.Abs(fly_velocity_.x)) * Mathf.Rad2Deg;
        }
        else
        {
            currentAngle_.z = Mathf.Atan((fly_velocity_.y) / Mathf.Abs(fly_velocity_.z)) * Mathf.Rad2Deg;
        }
    }

    /// <summary>
    /// 旋转道具的Y角度
    /// </summary>
    private void rotateYaxis()
    {

        Vector3 Speed_hori = new Vector3(fly_velocity_.x, 0f, fly_velocity_.z);
        float angle = Vector3.Angle(Vector3.right, Speed_hori);

        Vector3 nordir = Vector3.Cross(Vector3.right, Speed_hori);
        
        //计算两个向量的点乘,点乘可得知两个向量夹角是否大于90度,cos(angle) < 0
        float dot = Vector3.Dot(nordir, Vector3.down);
        
        //将angle的范围从 0-180 转换成0-360
        if (dot < 0)
        {
            angle *= -1;
            angle += 360;
        }
    
        // angle和Unity中的旋转角度相反,因为unity使用的是左手坐标系
        currentAngle_.y = angle * -1;

        //Debug.Log("Y旋转角" + currentAngle.y);
        transform.eulerAngles = currentAngle_;
    }



    //如果碰到其他物体不再飞行
    /*
    private void OnTriggerEnter(Collider other) {
        if(other.gameObject)
        {
            fly_velocity = Vector3.zero;
        }
    }
    */
}

参考文章:unity抛物线_发射弓箭轨迹的实现_lizhenxiqnmlgb的博客-CSDN博客_unity 抛物线轨迹

猜你喜欢

转载自blog.csdn.net/weixin_45203752/article/details/123277215
今日推荐