97人加入学习
(0人评价)
网络游戏同步算法

不同的游戏该选用何种同步机制?

价格 ¥ 9.90

打击优化算法

1.延迟补偿算法:

延迟补偿是游戏服务器端执行的一种策略,处理用户命令时客户端回退到客户端发送命令的准确时间。

利弊:

1.以牺牲真实性来弥补攻击行为的体验,本质上是一种折中选择。

2.对低延迟的玩家不公平,移动速度快,可能已经跑掉了,却又被打中了。

3.对高延迟的玩家有利,但对维护游戏世界的平衡还是有利的。

服务端功能:

1.保留信息多个帧的信息,如前20帧

2.必要时回溯

[展开全文]

帧同步:指令同步

状态->状态  客户端发送物体位置   服务端只是只转发

服务端转发,客户端运算,客户端有运算的话,一般是校准能力,判断是否作弊,也可以没有,但最好有

指令->状态  客户顿发送的是一个指令,比如:向前,向后等;服务端做位置运算,再把算出来的位置广播发给其他的客户端

服务端运算,客户端可以没有运算能力,客户端有运算的话,一般是先行表现,客户端优先先行一下,等服务端回消息后,做判断,如果差别不大,就以先行为主,如果大的话,就以服务端为主

,这样可以提高游戏体验

指令->指令 帧同步  :客户顿发送的是一个指令,比如:向前,向后等,服务端只是只转发,广播发给其他的客户端,客户端再去模拟向前向后的指令,逻辑运算都是在客户端运算的;

服务端转发指令,客户端接受指令后运算,服务端有运算的话,一般是校准能力,判断是否作弊,也可以没有,但最好有

 

[展开全文]

延迟的解决

1:移动优化算法

插值算法:收到同步协议后,客户端不直接将实体拉到目基地,二十让实体以一定的速度移动到目基地

时间为0时,T0=0+1/2RTT

时间为0.05时,T1=0.05+1/2RTT

时间为0.1时,T2=0.1+1/2RTT

时间为0.15时,T3=0.15+1/2RTT

时间为0.2时,T3=0.2+1/2RTT

1:发送端:

public Update(){

if(时间间隔){
sendMove();
}
}
class MsgMove(){

public float x=0;
public float y=0;
public float z=0;
public float ex=0;
public float ey=0;
public float ez=0;
}

2:接受端:

//last 上次的位置消息
Vector3 lastPos;
Vector3 lastEuler;
Vector3 targetPos;//接受实体的位置
Vector3 targetEuler;//接受实体的旋转
float lastTime;//上次接受的时间


public onMsgMove(MsgMove msg){
lastPos=transform.position;//当前实体的位置
lastEuler=transform.eulerAngles;//当前实体的旋转
targetPos=new Vector3(msg.x,msg.y,msg.z);//发过来实体的位置
targetEuler=new  Vector3(msg.ex,msg.ey,msg.ez)//发过来实体的旋转
lastTime=Time.time;//记录时间
}


public Update(){
float t=(Time.time-lastTime)/INTERVAL;
transform.position=Vector3.Lerp(lastPos,targetPos,t)
transform.rotation=Quaternion.Lerp(Quaternion.Euler(lastEuler),Quaternion.Euler(targetPos),t);
}

插值算法公式

1.瞬移

pos=pos0

2.匀速插值

pos=pos0+v(t-t0)

v=(pos1-pos0)/  1/2RTT

3.匀加速插值

pos1=pos0+v(t-t0)+1/2a(t-t0)^2

 

“point-to-point”方式

“linear”方式

”quadratic“方法

”三次参数“ 方法

2预算算法

在某些有规律可循的条件下,如匀速运动,或匀加速运动,能够预测坦克在接下来的位置,提前走到预测的位置去.

1.发送端

public Update(){

if(时间间隔){
sendMove();
}
}
class MsgMove(){

public float x=0;
public float y=0;
public float z=0;
public float ex=0;
public float ey=0;
public float ez=0;
}

 

2.发送端

//last 上次的位置消息
Vector3 lastPos;
Vector3 lastEuler;
Vector3 targetPos;//接受实体的位置
Vector3 targetEuler;//接受实体的旋转
float lastTime;//上次接受的时间


public onMsgMove(MsgMove msg){
lastPos=transform.position;//当前实体的位置
lastEuler=transform.eulerAngles;//当前实体的旋转
Vector3 msgPos=new Vector3(msg.x,msg.y,msg.z);
Vector3 msgEuler=new Vector3(msg.ex,msg.ey,msg.ez);
targetPos=lastPos+(msgPos-lastPos)*2;//移动2倍的距离
targetEuler=lastEuler+(msgEuler-lastEuler)*2;
lastTime=Time.time;//记录时间
}


public Update(){
float t=(Time.time-lastTime)/INTERVAL;
transform.position=Vector3.Lerp(lastPos,targetPos,t)
transform.rotation=Quaternion.Lerp(Quaternion.Euler(lastEuler),Quaternion.Euler(targetPos),t);
}

匀速,匀加速下可预测

缓存队列

将消息缓存,逐一播放

代码,多级缓存

Queue<MsgMove>moveQueue;
public onMsgMove(MsgMove msg){
moveQueue.Enqueue(msg)
}
public Update(){
//直接忽略消息
while(moveQueue.Count>5){//0.2*5=1s
moveQueue.dequeue();
}
//加速执行
if(moveQueue.Count>3){
msg=moveQueue.dequeue();
设置目标点;
调整INTERVAL加速;
return;
}
//正常速度
if(moveQueue.Count>1){
msg=moveQueue.dequeue();
设置目标点;
return;
}
}

 

[展开全文]