關於貝塞爾曲線運動

遊戲中我們有時候會碰到計算物體的曲線運動,貝塞爾曲線就變得比較常用。

以下貼出主要代碼:

BezierData.cs

using UnityEngine;
using System.Collections;

public struct BezierData
{
    private Vector3 p0;
    private Vector3 p1;
    private Vector3 p2;

    public void SetData(Vector3 startPos, Vector3 controlPos, Vector3 endPos)
    {
        this.p0 = startPos;
        this.p1 = controlPos;
        this.p2 = endPos;
        //		Debug.Log(this.p0 + "  " + this.p1 + "  " + this.p2);
    }

    public Vector3 Lerp(float t)
    {
        t = Mathf.Clamp01(t);
        if (Mathf.Approximately(t,1))
        {
            return this.p2;
        }

        Vector3 pos0 = this.p0;
        Vector3 pos1 = this.p1;
        Vector3 pos2 = this.p2;

        float x = pos0.x + t * (2 * (1 - t) * (pos1.x - pos0.x) + t * (pos2.x - pos0.x));
        float y = pos0.y + t * (2 * (1 - t) * (pos1.y - pos0.y) + t * (pos2.y - pos0.y));
        float z = pos0.z + t * (2 * (1 - t) * (pos1.z - pos0.z) + t * (pos2.z - pos0.z));
        return new Vector3(x, y, z);
    }
}

BulletThing.cs

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

public class BulletThing : MonoBehaviour 
{

    public static Dictionary<BulletThing, bool> liveBullet = new Dictionary<BulletThing, bool>();

    public BulletInfo info;
    public EffectThing effect;
    public Vector3 targetPos;
    private float moveSpeed;
    private float curMoveTime;
    private float totalMoveTime;
    //private 
    private BezierData bezierData;

    public bool isPause;

    //public bool isPau

    private void OnEnable()
    {
        liveBullet[this] = true;
    }


    private void OnDisable()
    {
        liveBullet.Remove(this);
    }


    private void OnDestroy()
    {
        OnDisable();
    }

    public static BulletThing Create(BulletInfo info, IBaseThing owner)
    {
        //EffectManager
        BindInfo bindInfo = new BindInfo();
        bindInfo.position = new Vector3(info.posX, info.posY, info.posZ);
        bindInfo.eulerAngle = new Vector3(info.angleX, info.angleY, info.angleZ);
        bindInfo.scale = new Vector3(info.scaleX, info.scaleY, info.scaleZ);
        if (bindInfo.scale == Vector3.zero)
            bindInfo.scale = Vector3.one;
        EffectThing effectThing = EffectManager.ins.AddEffectSceneWithBone(info.imgId, owner, bindInfo);
        BulletThing bullet = UITools.GetOrCreateComponent<BulletThing>(effectThing.gameObject);
        bullet.info = info;
        bullet.effect = effectThing;
        effectThing.isLoop = true;
        //bullet.OnStart();
        return bullet;
    }

    public void Update()
    {
        if(!this.isPause)
           this.ManualUpdate(Time.deltaTime);
    }

    public virtual void ManualUpdate(float deltaTime)
    {
        if(info.flyType == BulletFlyType.LineMove)
        {
            HandlerLineMove(deltaTime);
        }else if(info.flyType == BulletFlyType.BezierMove)
        {
            HandlerBezierMove(deltaTime);
        }
    }


    private void MoveDone()
    {
        this.Clear();
        this.enabled = false;
        EffectManager.ins.RecoverEffect(this.effect);
    }

    public void HandlerLineMove(float deltaTime)
    {
        Vector3 curPos = this.transform.position;
        Vector3 vector3 = targetPos - curPos;
        float dis = vector3.magnitude;
        float moveDis = this.moveSpeed * deltaTime;
        if (moveDis >= dis)
        {
            this.transform.position = targetPos;
            this.MoveDone();
        }
        else
        {
            vector3 = vector3.normalized;
            this.transform.forward = vector3;
            this.transform.position = curPos + vector3.normalized * moveDis;
        }
    }

    private void InitBezierMove()
    {
        float height = this.info.centerHeight;
        totalMoveTime = this.info.flyDuration;
        //height = 20;
        Vector3 centerPos = Vector3.Lerp(this.transform.position, targetPos, 0.5f);
        centerPos.y = height;
        //Mathf.Lerp(this.tra)

        //targetPos - this.transform.position

        bezierData = new BezierData();
        bezierData.SetData(this.transform.position, centerPos, targetPos);
    }

  

    public void HandlerBezierMove(float deltaTime)
    {
        curMoveTime += deltaTime;
        Vector3 newpos = bezierData.Lerp(curMoveTime / this.totalMoveTime);
        Vector3 oldPos = this.transform.position;
        this.transform.position = newpos;
        if (curMoveTime >= totalMoveTime)
        {
            this.MoveDone();
        }
        else
        {
            Vector3 vecForward = (newpos - oldPos);
            if(vecForward.sqrMagnitude > 0)
            {
                this.transform.forward = vecForward.normalized;
            }
        }
    }

    public void OnStart()
    {
        this.enabled = true;
        this.curMoveTime = 0;
        this.targetPos.y += this.info.targetOffsetY;
        moveSpeed = this.info.moveSpeed;
        //moveSpeed = 20;
        if (this.info.flyType == BulletFlyType.BezierMove)
            InitBezierMove();
    }


    public void Clear()
    {

    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章