天天看點

物體加速旋轉再減速

private float rotSpeed = 1000;      //旋轉速度
    private float rotState = -1;     //旋轉狀态 -1 停止 0 開始 1 結束
    private float endAngle = 0;      //結束角度
    private readonly float AcceleateTime = 1f; //加速度持續時間
    private  float rotTime = 0f;    //旋轉持續時間
    private float rotFactor = 0f;    //旋轉速度變化因子
    private float minTime = 3f;     //旋轉最小持續時間
    private float _tmpAngle = 0f;    //開始減速物體的角度

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        RotMath();
    }

    /// <summary>
    /// 旋轉方法 再update裡面更新
    /// </summary>
    public void RotMath()
    {
        if(rotState == -1)
        {
            return;
        }

        rotTime += Time.deltaTime; //記錄時間

        if (rotState == 0)
        {
            //開始旋轉 先加速計算速度
            rotFactor = rotTime / AcceleateTime;
            rotFactor = rotFactor > 1 ? 1 : rotFactor;
            transform.Rotate(Vector3.back, -rotFactor * rotSpeed * Time.deltaTime, Space.Self);
        }
        else
        {
            //減速旋轉一段時間再慢慢變停止

            //通過內插補點運算實作精準地旋轉到指定角度(球型插值無法實作大于360°的計算)
            float k = 1f;  //如果嫌減速太慢,可以加個系數修正一下
            _tmpAngle = Mathf.Lerp(_tmpAngle, endAngle, Time.deltaTime * k);

            //這裡隻存在一個方向的旋轉,是以不存在歐拉角萬向節的問題,是以使用歐拉角和四元數直接指派都是可以的
            transform.rotation = Quaternion.Euler(0, 0, -_tmpAngle);
            //node.eulerAngles = new Vector3(0, 0, _tmpAngle);

            if (1 >= Mathf.Abs(_tmpAngle - endAngle))
            {
                //重新設定狀态 資料 顯示獎勵等
                rotState = -1;
                endAngle = 0;
                rotTime = 0;


            }
        }
        
        //修改旋轉狀态
        if(rotState == 0 && rotTime > minTime && endAngle !=0 )
        {
            rotState = 1;
            // 将目前指針的歐拉角轉換成順時針統計角度
            //由于讀取到的值是[0, 180] U [-180, 0],左邊由0至180遞增,右邊由180轉變成-180,然後遞增至0,是以需要轉相應的轉換
            _tmpAngle = (1) * (360 - transform.eulerAngles.z) % 360;
        }
    }

    public void OnStartRot()
    {
        rotState = 0;
        rotTime = 0;
        endAngle = UnityEngine.Random.Range(0f, 360f);
        endAngle = Mathf.Abs(endAngle);
        print("End Angle: " + endAngle);
        endAngle = endAngle % 360;    //将角度限定在[0, 360]這個區間
        endAngle = -endAngle - 360 * 4;   //多N圈并取反,圈數能使減速階段變得更長,顯示更自然,逼真
    }
           

繼續閱讀