[从零开始的Unity网络同步] 4.如何实现确定性的网络同步
在上一篇文章中,总结得出确定性网络同步的必要性,那么接下来就考虑如何在Unity中实现确定性了.
1.服务端与客户端相同频率模拟(Simulate)
在Unity中,有三个更新方法Update
, LateUpdate
,FixedUpdate
.Update
和LateUpdate
属于渲染帧,它们每帧间隔的时间会受到渲染物体的时间影响(LateUpdate
是在所有的Update
方法执行完后再执行),打个比方说:相同的游戏,在性能好的机器上可以跑60帧每秒,但是在差的机器上,可能只能跑30帧每秒.两者相差了1倍,甚至更多.FixedUpdate
是固定频率更新,常常用来处理Unity中物理相关的东西,它不受渲染效率的影响,以固定的时间间隔调用,
所以为了保证服务端和客户端的模拟频率一致,那么在Unity中,就选用FixedUpdate
方法.在Unity中可以在Edit->Project Setting->time中找到Fixed timestep进行修改,也可以在代码中设置Time.fixedDeltaTime
的值.
public void SetFixedDeltaTimeForServer ()
{
Time.fixedDeltaTime = 1f/60; //当服务器成功启动,设置FixedUpdate更新间隔为每秒60次
}
public void SetFixedDeltaTimeForClient()
{
Time.fixedDeltaTime = 1f/60; //与服务端保持一致
}
这样,服务器和客户端的FixedUpdate
方法都会按照相同的频率调用,然后把操作的模拟(Simulate)放在里面执行.
2.相同的状态 + 相同的操作指令 = 相同的新状态
为了让服务端和客户端模拟的结果相同,首先必须保证服务端和客户端的模拟逻辑代码一致,尽量减少使用默认的物理模拟(PS:引擎的物理模拟有些会带有随机数,一旦服务器和客户端的随机数不一致,会导致结果不一致),先来定义操作指令类(Command)
public class Command
{
public uint sequence; //指令序号
public CommandInput input; //操作指令的输入
public CommandResult result; //操作指令执行后得到的结果
}
Simulate方法需要做的应该就是收集操作指令CommandInput,然后执行,得到CommandResult
public void FixedUpdate()
{
Simulate();
}
public void Simulate()
{
OnSimulateBefore();
if(isServer && isOwner) //如果是服务器的物体,获取指令,直接执行指令即可
{
Command cmd = new Command ();
cmd.input = CollectCommandInput(); // 获取指令
ExecuteCommand(cmd); // 执行指令
}
OnSimulateAfter();
}
public override void ExecuteCommand(Command command)
{
float movingSpeed = 4;
Vector3 movingDir = Vector3.zero;
if (input.forward ^ input.backward)
movingDir.z = input.forward ? +1 : -1;
if (input.left ^ input.right)
movingDir.x = input.right ? +1 : -1;
Vector3 velocity = movingDir * movingSpeed; //通过输入计算出速度
transform.position = transform.position + velocity * Time.fixedDeltaTime; //立即计算出结果
command.result.position = transform.position; //将结果保存到CommandResult中
}
CollectCommandInput
和ExecuteCommand
方法中,客户端和服务端的代码应该是一致的.
服务器和客户端,执行完Command以后,填充result需要的数据.这样,一个Command就完成了,经过网络同步以后,利用sequence(指令序号)来对比操作的结果是否一致.
操作结果如果:
3.小结
有了这个基本的Command的结构和相同频率的Simulate,后续就要考虑服务端和客户端如何去同步这些Command.