网上对于网络同步的说法排雷
之前一的时候,要实现帧同步,需要一个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);
}
}