真Unity3d_分享一個ECS源碼(二)+ 幀同步

之前一的時候,要實現幀同步,需要一個ECS框架(非必須)

然後除了ECS,還缺平滑移動,(就算有了幀同步框架)

網上說的平滑移動很不準確,還有某大神的“同步框架”,“開源項目‘,居然有這樣的代碼

o.transform.position = Vector3.Lerp(o.transform.position, o.transform.position + dir.normalized, 0.33f * _speed);

如此做法,連在Unity或者任何一個遊戲引擎裏,“好好”移動都做不到,只是紙上談兵

網上狠多人也說,要用Lerp,要用Vector3.Lerp還是Mathf.Lerp??

然後又會扯出一大堆,lerp的理論,。。。。。 1+1==2 確實需要研究其理論的,這我同意

但其實要在Unity下實現平滑移動,

其實Lerp和Time.deltaTime應該是要配合使用的

(和官方的gravity, setVelocity等很不同,但有興趣的同學可以深挖一下其原理)

官方的很多封裝的方法都很“好用”

transform.Translate(0, 0, speed*Time.deltaTime);

又例如:

navAgent.velocity = v.normalized*MoveSpeed;

感覺UNITY公司內部人員都是牛人,但是他們好像也不願意分享其中原理,或者他們很多知識點覺得理所當然吧

也導致很多Unity新手自創很多方法。。。。99%是雷

下面這個代碼好像對,但有極其雷

(很多時候你做的遊戲看上去還好,只是因爲你一直沒發佈到不同的手機,一個小小的適配改變就各種顯示異常,類似地,網絡同步更加容易異常)

currentCornerMoved += MoveSpeed * Time.deltaTime;

transform.position = Vector3.Lerp(currentPathCorners[currentPathCornerIndex], currentPathCorners[currentPathCornerIndex + 1], currentCornerMoved / currentCornerDist);
transform.forward = Vector3.RotateTowards(transform.forward, currentPathCorners[currentPathCornerIndex + 1] - currentPathCorners[currentPathCornerIndex], 15.0f * Time.deltaTime, 0);

所以,這裏分享一個測試代碼,隨便一個空場景,掛腳本,填寫預製體,增加一個Plane(要在0點)做點擊觸發,即可使用

操作方法:

鼠標右鍵,新增GameObject

鍵盤X鍵,移動GameObject

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 一個平滑移動例子
/// </summary>
public class TouchAndMove : MonoBehaviour
{
    List<GameObject> objs = new List<GameObject>();
    public GameObject _prefab;
    Vector3 _destination;
    Vector3 _frm;
    public float _speed = 5;
    // Start is called before the first frame update
    Vector3 _deftinationDef = Vector3.zero;
    void Start()
    {
        //操作方法:鼠標右鍵,新增GameObject; 鍵盤X鍵,移動GameObject
    }

    // Update is called once per frame
    void Update()
    {
        if(UnityEngine.Input.GetMouseButtonUp(1))
        {
            objs.Add(GameObject.Instantiate(_prefab));
        }

        if (UnityEngine.Input.GetKeyUp(KeyCode.X))
        {
            Vector2 vec2 = GetWorldPos(UnityEngine.Input.mousePosition);
            _destination = new Vector3(vec2.x, 0, vec2.y);
            if (objs.Count > 0)
            {
                _frm = objs[0].transform.position;
            }
        }
        //可調用方法還有,OnDestinationDef(),OnDestination()等,請看說明,不一定”好用“
        //使用前,需要配置_prefab
        ///當然,可以通過調整_speed,觀察移動效果。。。
        OnDestination3(); 
    }
    /// <summary>
    /// 彈簧式步進
    /// </summary>
    void OnDestinationDef()
    {
        foreach (var o in objs)
        {
            if ((o.transform.position - _destination).magnitude > 1)
            {
                o.transform.position = Vector3.Lerp(o.transform.position, _destination, Time.deltaTime * _speed);
            }
            else
            {
                _frm = objs[0].transform.position;
                //_destination = _deftinationDef;
            }
        }
    }
    /// <summary>
    /// 只移動一小段
    /// </summary>
    void OnDestination()
    {
        if (_destination == null) return;
        foreach (var o in objs)
        {
            if ((o.transform.position - _destination).magnitude > 1)
            {
                o.transform.position = Vector3.Lerp(_frm, _destination, Time.deltaTime * _speed);
            }
            else
            {
                _frm = objs[0].transform.position;
                //_destination = _deftinationDef;
            }
        }
    }
    /// <summary>
    /// 特喵了,根本無法正常移動
    /// </summary>
    void OnDestination2()
    {
        if (_destination == null) return;
        foreach (var o in objs)
        {
            if ((o.transform.position - _destination).magnitude > 1)
            {
                Vector3 dir = _destination - _frm;
                o.transform.position = Vector3.Lerp(o.transform.position, dir.normalized, Time.deltaTime * _speed);
            }
            else
            {
                _frm = objs[0].transform.position;
                //_destination = _deftinationDef;
            }
        }
    }
    /// <summary>
    /// 看上去,這個是真正的完全移動了,但如果把速度調快,則也是有明顯”卡幀“,所以高速運動還是有跳幀現象
    /// </summary>
    void OnDestination3()
    {
        if (_destination == null) return;
        foreach (var o in objs)
        {
            if ((o.transform.position - _destination).magnitude > 1)
            {
                Vector3 dir = _destination - _frm;
                o.transform.position = Vector3.Lerp(o.transform.position, o.transform.position +dir.normalized, Time.deltaTime * _speed);
            }
            else
            {
                _frm = objs[0].transform.position;
                //_destination = _deftinationDef;
            }
        }
    }
    /// <summary>
    /// 不平滑移動
    /// </summary>
    void OnDestination4() {
        if (_destination == null) return;
        foreach (var o in objs)
        {
            if ((o.transform.position - _destination).magnitude > 1)
            {
                Vector3 dir = _destination - _frm;
                o.transform.position = Vector3.Lerp(o.transform.position, o.transform.position + dir.normalized, 0.33f * _speed);
            }
            else
            {
                _frm = objs[0].transform.position;
                //_destination = _deftinationDef;
            }
        }
    }

    Vector2 GetWorldPos(Vector2 screenPos)
    {
        var ray = Camera.main.ScreenPointToRay(screenPos);
        if (Physics.Raycast(ray, out var hit))
        {

            return new Vector2(hit.point.x, hit.point.z);

        }

        var hitPoint = ray.origin - ray.direction * (ray.origin.y / ray.direction.y);
        return new Vector2(hitPoint.x, hitPoint.z);
    }
}

 

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