首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >弱网多人联机表现优化

弱网多人联机表现优化

作者头像
keyle
发布2024-11-01 12:10:03
发布2024-11-01 12:10:03
21100
代码可运行
举报
文章被收录于专栏:礼拜八不工作礼拜八不工作
运行总次数:0
代码可运行

上篇讲到客户端的同步策略,也就是Client to Server的发包策略。那么这篇说一下Server to Client的网络抖动情况下优化本地表现。 延迟实际并不会造成客户端表现障碍,但是网络抖动会,我们优化的点在于不要让用户看到模型坐标拉扯,让表现过度自然。处理的过程中尽量追平服务器计算的实时位置。

视频

这里讲一下我的思路,玩家每次收到的Pack结构如下:position是此刻当前物体处在位置,angle为运动方向,speed为0则物体进入idle。

代码语言:javascript
代码运行次数:0
运行
复制
public class PlayerStatePack
{
    public float speed;
    public Vector3 position;
    public int angle_deg;
}

下面是模拟服务端延迟的实现,fluctuation用来模拟网络抖动:

currentTime = Time.time + Ping / 1000f * 2 + Random.Range(-fluctuation * 2/1000f , fluctuation * 2/1000f );

代码语言:javascript
代码运行次数:0
运行
复制
void Update()
{
    for (int i = 0; i < packLst.Count; i++)
    {
        if (packLst[i].BeSend)
            continue;
        
        if (packLst[i].currentTime <= Time.time)
        {
            packLst[i].BeSend = true;
            ReceivePack?.Invoke(packLst[i]);
        }
    }
}

客户端接收消息实现如下:通过ReceivePack函数订阅模拟服务器下发的Pack, 在该函数内做一个向量的减法,获取当前客户端所处与服务器同步过来的位置之间的误差, 有了此向量,那后面就可以通过插值逐渐修正到一个趋近正确的位置,一定程度上抹平网络波动引起的误差。 在 ApplyPoint 函数我做了一个当前误差的差值与角度差值,这样效果会好一些。

代码语言:javascript
代码运行次数:0
运行
复制
public void OnMove(float passTime,float step,Vector3 pos,float angle)
{
    ...
}


private void ReceivePack(PlayerStatePack item)
{
    Debug.Log("其他玩家收到同步包");

    modifyOffset = item.position - transform.position;
    localPositon = transform.position;
    localAnlge = transform.eulerAngles.y;
    ...
}

public float timeTakenDuringLerp = .2f;

private void Update()
{
    ....
    var passTime = Time.time - currentPack.CurrentTime;

    OnMove(passTime,step,pos,angle);

    ApplyPoint(passTime);
}

private void ApplyPoint(float passTime)
{
    float percentageComplete = passTime / timeTakenDuringLerp;
    
    if(percentageComplete >= 1.0f)
    {
        transform.position = RuntimePos + modifyOffset;
        return;
    }

    var offset = Vector3.Lerp(Vector3.zero, modifyOffset,percentageComplete); 
    transform.position = RuntimePos + offset;

    if(percentageComplete*2 >= 1.0f)
    {
        return;
    }
    var yoffset = Mathf.LerpAngle(localAnlge, currentPack.angle_deg,percentageComplete*2);
    transform.eulerAngles = new Vector3(transform.transform.eulerAngles.x,yoffset,transform.transform.eulerAngles.z);
}

结语

还有其他方式优化表现,下面贴了条链接其中有讲到 立方样条插值,这种方式常见于各种导航软件比较复杂。如果是赛车游戏我倒是非常推荐用这种预测模式降低网络抖动造成的拉扯现象

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-03-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 礼拜八不工作 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档