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

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

首先,当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
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值