【UNET自学日志】Part5 解决延迟产生的画面不流畅问题

来源:互联网 发布:匈牙利 基督之盾 知乎 编辑:程序博客网 时间:2024/04/25 20:15

关于解决延迟这类问题,最简单粗暴的方法就是提高网络的质量,但是身为程序猿我们也应该做些力所能及的事情,关于网络的延迟导致的画面不流畅,可以采用以下介绍的方法:

首先,当Player1的位置发生变化时,会发送一个变化的位置给服务器,服务器将这个位置的点发送给其他客户端,此时,我们需要一个list去保存这些点;

下一步,计算客户端中Player1的位置和list中的第一个位置,如果两个位置相距的距离足够近的话,删除掉第一个点的位置;


通过这样的方法,可以使Player的位置移动更加的平滑,附上代码


using UnityEngine;using System.Collections;using System.Collections.Generic;using UnityEngine.Networking;using UnityEngine.UI;[NetworkSettings(channel=0,sendInterval=0.1f)]public class Player_SyncPosition : NetworkBehaviour {    [SyncVar(hook="SyncPositionValues")]private Vector3 syncPos;    [SerializeField]Transform myTransform;    private float lerpRate;    private float normalLerpRate = 16;    private float fasterLerpRate = 27;    private Vector3 lastPos;    private float threshold = 0.5f;    private NetworkClient nClient;    private int latency;    private Text latencyText;    private List<Vector3> syncPosList = new List<Vector3>();    [SerializeField]private bool useHistoricalLerping=false;    private float closeEnough = 0.11f;    void Start()    {        nClient = GameObject.Find("NetworkManager").GetComponent<NetworkManager>().client;        latencyText = GameObject.Find("Latency Text").GetComponent<Text>();        lerpRate = normalLerpRate;    }    void Update()    {        LerpPosition();        ShowLatency();    }    void FixedUpdate()    {        TransformPosition();    }    void LerpPosition()    {        if (!isLocalPlayer)        {            if (useHistoricalLerping)            {                HistoricalLerping();            }            else            {                OrdinaryLerping();            }        }    }    [Command]    void CmdProvidePositionToServer(Vector3 pos)    {        syncPos = pos;    }    [ClientCallback]    void TransformPosition()    {        if (isLocalPlayer&&Vector3.Distance(myTransform.position,lastPos)>threshold)        {            CmdProvidePositionToServer(myTransform.position);            lastPos = myTransform.position;        }    }    [Client]    void SyncPositionValues(Vector3 latestPos)    {        syncPos = latestPos;        syncPosList.Add(syncPos);    }    void ShowLatency()    {        if (isLocalPlayer)        {            latency = nClient.GetRTT();            latencyText.text = latency.ToString();        }    }    void OrdinaryLerping()       {        myTransform.position = Vector3.Lerp(myTransform.position, syncPos, Time.deltaTime * lerpRate);    }    void HistoricalLerping()    {        if (syncPosList.Count > 0)        {            myTransform.position = Vector3.Lerp(myTransform.position, syncPosList[0], Time.deltaTime * lerpRate);            if (Vector3.Distance(myTransform.position, syncPosList[0]) < closeEnough)            {                syncPosList.RemoveAt(0);            }            if (syncPosList.Count > 10)            {                lerpRate = fasterLerpRate;            }            else            {                lerpRate = normalLerpRate;            }        }    }}
上段代码中提供两种不同的同步运动的方式(OrdinaryLerping和HistoricalLerping),以供对比。

SyncVar(hook="SyncPositionValues")指的是当这个值发生变化的时候就调用SyncPositionValues函数。

至于normalLerpRate和fasterLerpRate的值各位读者可以自己衡量一个更为恰当的值。


另外附上一篇相关文章的链接http://www.gabrielgambetta.com/fpm1.html

上面所介绍的内容还是相当给力的~

0 0