对于旋转的同步,其主要的思路和运动的同步是一样的,设置一个List,每次角度变化的时候将这个变化的数值存入List当中,当物体旋转的角度和List的第一个数值足够接近的时候,删除List中的第一个数值。值得一提的是,此方法只是改善画面的流畅性,并不能消除延迟所带来的同步问题。
下面是Player_SyncRotation的代码
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;
public class Player_SyncRotation : NetworkBehaviour {
[SyncVar(hook="OnPlayerRotSynced")]private float syncPlayerRotation;
[SyncVar(hook = "OnCamRotSynced")]private float syncCamRotation;
[SerializeField]private Transform playerTransform;
[SerializeField]private Transform camTransform;
private float lerpRate=20;
private float lastPlayerRot;
private float lastCamRot;
private float threshold = 1;
private List<float>syncPlayerRotList=new List<float>();
private List<float>syncCamRotList=new List<float>();
private float closeEnough = 0.4f;
[SerializeField]private bool useHistoricalInterpolation;
void Update()
{
LerpRotations();
}
void FixedUpdate ()
{
TransmitRotations();
}
void LerpRotations()
{
if (!isLocalPlayer)
{
if (useHistoricalInterpolation)
{
HistoricalLerping();
}
else
{
OrdinaryLerping();
}
}
}
void OrdinaryLerping()
{
LerpPlayerRot(syncPlayerRotation);
LerpCamRot(syncCamRotation);
}
void LerpPlayerRot(float rotAngle)
{
Vector3 playerNewRot = new Vector3(0, rotAngle, 0);
playerTransform.rotation = Quaternion.Lerp(playerTransform.rotation, Quaternion.Euler(playerNewRot), lerpRate * Time.deltaTime);
}
void LerpCamRot(float rotAngle)
{
Vector3 camNewRot = new Vector3(rotAngle, 0, 0);
camTransform.localRotation = Quaternion.Lerp(camTransform.localRotation, Quaternion.Euler(camNewRot), lerpRate * Time.deltaTime);
}
void HistoricalLerping()
{
if (syncPlayerRotList.Count > 0)
{
LerpPlayerRot(syncPlayerRotList[0]);
if (Mathf.Abs(playerTransform.localEulerAngles.y - syncPlayerRotList[0]) < closeEnough)
{
syncPlayerRotList.RemoveAt(0);
}
Debug.Log(syncPlayerRotList.Count.ToString() + " syncPlayerRotList Count");
}
if (syncCamRotList.Count > 0)
{
LerpCamRot(syncCamRotList[0]);
if (Mathf.Abs(camTransform.localEulerAngles.x - syncCamRotList[0]) < closeEnough)
{
syncCamRotList.RemoveAt(0);
}
Debug.Log(syncCamRotList.Count.ToString() + " syncCamRotList Count");
}
}
[Command]
void CmdProvideRotationToServer(float playerRot, float camRot)
{
syncPlayerRotation = playerRot;
syncCamRotation = camRot;
}
[Client]
void TransmitRotations()
{
if (isLocalPlayer)
{
//if(Quaternion.Angle(playerTransform.rotation,lastPlayerRot)>threshold||Quaternion.Angle(camTransform.rotation,lastCamRot)>threshold)
if(CheckIfBeyondThreshold(playerTransform.localEulerAngles.y,lastPlayerRot)||CheckIfBeyondThreshold(camTransform.localEulerAngles.x,lastCamRot))
{
lastPlayerRot = playerTransform.localEulerAngles.y;
lastCamRot = camTransform.localEulerAngles.x;
CmdProvideRotationToServer(lastPlayerRot,lastCamRot);
}
}
}
bool CheckIfBeyondThreshold(float rot1,float rot2)
{
if (Mathf.Abs(rot1 - rot2) > threshold)
{
return true;
}
else
{
return false;
}
}
[Client]
void OnPlayerRotSynced(float latestPlayerRot)
{
syncPlayerRotation = latestPlayerRot;
syncPlayerRotList.Add(syncPlayerRotation);
}
[Client]
void OnCamRotSynced(float latestCamRot)
{
syncCamRotation = lastCamRot;
syncCamRotList.Add(syncCamRotation);
}
}
List中保存的是一个Float,当Player旋转的时候,在父物体中只是改变其Y轴,在子物体中只是改变其X轴,故可以用float来记录。