unity3d:网络同步,状态同步,源码,C#服务器demo

news2025/1/10 1:45:25

协议数据单元

网络同步包最小单元PDU

// 预测的基础数据类型
public class PDU
{
public uint UID;            //玩家的唯一id
public PDUType type;		//PDU类型
public Vector3 position;	// 位置
public Vector3 forward;		// 朝向
public float speed;			// 速度: 速度为0表示静止
public float time;			// PDU发出的时间
public string anim;			// 当前的动作
}

需要发送PDU的情况,即是状态改变时情况

public enum PDUType
{
None			= 0, 	// 没有产生任何改动
OutOrbit 		= 1,	// 超出轨道
OverThreshold 	= 2,	// 和本地模拟超过一定的阈值
SpeedChange 	= 4,	// 速度发生改变
ActChange 		= 8,	// 动作发生改变
All 			= OutOrbit | OverThreshold | SpeedChange | ActChange,
};

超出轨道

a背后有个观察者b,b对着a运动的方向,发射一个带有宽度的轨道。a超过了轨道即发送PDU,好处是在玩家速度,方向不变时,只需要发送一次PDU,而不需要每时每刻都发送
图下两条绿线即为轨道
在这里插入图片描述

当a相对b的本地坐标.x超过了轨道轨道宽度的一半,即触发了超过轨道

// 检查是否还在轨道内,每帧调用
bool inOrbitJudge()
{
Vector3 currentPos = gameObject.transform.position;
Quaternion rot = transform.localRotation;

Vector3 vct = m_PDUCreater.transform.InverseTransformPoint(currentPos);
if ( Mathf.Abs(vct.x) > orbitWidth/2.0)
{
return false;
}

return true;
}

同时更新b的位置与朝向

Vector3 dir = transform.position - lastPosition;
m_PDUCreater.transform.position = transform.position;
m_PDUCreater.transform.LookAt(transform.position + dir.normalized * 5);

本地模拟超过一定的阈值

本地模拟出的位置b(根据发出的pdu的朝向,速度每帧计算出),与发送者的位置a偏差超过阈值。这么做的原因是玩家原地转向也能识别到,一般手游都是摇杆,还是比较难做到原地转向

localSimulatedPosition += currentPDU.forward * currentPDU.speed * Time.deltaTime;

if ((localSimulatedPosition - transform.position).magnitude > DistanceTolerance)// 如果和本地模拟超过一定的阈值也要发送PDU
{
iPDUType |= PDUType.OverThreshold;
}

客户端同步服务器时间

每个客户端每隔1s同步服务器时间,得到时间s后,会在本地进行update模拟累加
发送时会记录发送时间戳

//向服务器发送请求服务器时间
void SendSyncTime()
{
sendSyncTime = Time.time;
GameSocket.Instance.SendMsgProtoVoid(MsgIdDefine.ReqHeartBeat);
}

接收时,记录接收时间戳,假设一次传输的时间延迟发送,接收各占一半,此时服务器时间为

void OnRspHeartBeat(PtLong data)
{
float reciveNetTimeDiff = Time.time - sendSyncTime;
float serverTime = (float)data.value + reciveNetTimeDiff * 0.5f;
TimeManager.self.currentTime = serverTime;
}

远程玩家

远程玩家是个镜像,当有新PDU传入时,做插值运动到预测的位置
没有时,按照上一次的PDU状态运动,例如上一次有速度时,按照速度*朝向移动;上一次是没速度时,持续禁止状态

新PDU传入

远程的位置应该为 PDU传输过来的位置 + 朝向 * 速度 * (插值时间 + 消息延迟)

//当新PDU传入时改变远程玩家位置,朝向,动画,速度
if(newPDUComing)
{
//DeterminStateByAnimation(realPDU.anim);
//float curTime = pvpWJY.ServerTime.currentTime;
float curTime = TimeManager.self.currentTime;
float oldTime = realPDU.time;

// 消息延迟时间
float timeDiffer = curTime - oldTime;
if(timeDiffer < 0 || timeDiffer > 2)
Debug.LogError("server time error : " + timeDiffer);

timeDiffer = Mathf.Clamp(timeDiffer, 0, 2);

smoothTime = realSmoothTime;

// 公式:插值的目标位置 = PDU传输过来的位置 + 朝向 * 速度 * (插值时间 + 消息延迟)
targetPosition = realPDU.position + realPDU.forward * realPDU.speed * timeDiffer;
targetForward = realPDU.forward;
startLerpPosition = transform.position;
startLerpForward = transform.forward;
newPDUComing = false;

transform.position = targetPosition;
}

//当还剩下平滑插值时间,继续插值
if (smoothTime > 0)
{
smoothTime -= Time.deltaTime;
transform.position = Vector3.Lerp(targetPosition, startLerpPosition, smoothTime / realSmoothTime);
transform.forward = Vector3.Slerp(targetForward, startLerpForward, smoothTime / realSmoothTime);

}
else
{
if (realPDU != null)
{
transform.position += realPDU.forward * realPDU.speed * Time.deltaTime;
}
}

Demo演示

白色是玩家,发送数据给服务器
黑色是远程镜像,接收到服务器PDU包进行模拟运动
type为PDU改变的类型
在均速直线运动阶段,产生的网络包较少
在这里插入图片描述

源码

https://github.com/luoyikun/UnityForTest
先启动服务器
UnityForTest\Server\MultiServer.sln运行
在这里插入图片描述
在这里插入图片描述

在局域网下,服务器会定时向局域网UDP广播TCP服务器的端口号
客户端接到了TCP的端口号,连接服务器
客户端场景
UnityForTest\Assets\NetSync\gdePvp\GdeNetSync.unity
点击运行,等待连接上服务器即可
在这里插入图片描述

按ws前进后退,ad转向

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/417676.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【STL十一】无序容器(哈希容器)—— unordered_map、unordered_set

【STL十一】无序容器&#xff08;哈希容器&#xff09;—— unordered_map、unordered_set一、简介1、关联容器和无序容器不同2、无序容器特点二、头文件三、模板类四、无序容器的内部结构1、管理桶2、内部结构五、unordered_map成员函数1、迭代器2、元素访问3、容量4、修改操作…

CV大模型应用:Grounded-Segment-Anything实现目标分割、检测与风格迁移

Grounded-Segment-Anything实现目标分割、检测与风格迁移 文章目录Grounded-Segment-Anything实现目标分割、检测与风格迁移一、Segment-Anything介绍二、Grounded-Segment-Anything1、简介2、测试一、Segment-Anything介绍 代码链接&#xff1a;https://github.com/facebookr…

Direct3D 12——混合——雾

实现雾化效果的流程如下&#xff1a;如图所示&#xff0c;首先指明雾的颜色、由摄像机到雾气的最近距离以及雾 的分散范围(即从雾到摄像机的最近距离至雾能完全覆盖物体的这段范围)&#xff0c;接下来再将网格三角形上点 的颜色置为原色与雾色的加权平均值&#xff1a; foggedC…

Python爬虫之多线程加快爬取速度

之前我们学习了动态翻页我们实现了网页的动态的分页&#xff0c;此时我们可以爬取所有的公开信息了&#xff0c;经过几十个小时的不懈努力&#xff0c;一共获取了 16万 条数据&#xff0c;但是软件的效率实在是有点低了&#xff0c;看了下获取 10 万条数据的时间超过了 56 个小…

【技巧】Word“只读方式”的设置与取消

如果你担心在阅读Word文档的时候&#xff0c;不小心修改并保存了内容&#xff0c;那就给文档设置“只读方式”吧&#xff0c;这样就算不小心做了修改也不能随意保存。 Word文档的“只读方式”有两种模式&#xff0c;对此不清楚的小伙伴&#xff0c;来看看如何设置和取消吧。 模…

第一次作业

作业内容&#xff1a;1&#xff0c;atd和crond的区别 2&#xff0c;指定在2023/08/26 09&#xff1a;00将时间写入testmail.txt文件中 3&#xff0c;指定在每天凌晨4&#xff1a;00将该时间点之前的系统日志信息备份到个目录下&#xff08;/var/log/messages &#xff09;&…

华为手表开发:WATCH 3 Pro(17)传感器订阅指南针

华为手表开发&#xff1a;WATCH 3 Pro&#xff08;17&#xff09;传感器订阅指南针初环境与设备指南针传感器介绍与说明鸿蒙开发文件夹&#xff1a;文件新增展示的文本标记index.hmlindex.cssindex.js初 希望能写一些简单的教程和案例分享给需要的人 鸿蒙可穿戴开发 环境与设…

二 、Locust自定义用户(场景)

二 、自定义用户&#xff08;场景&#xff09; 一个用户类代表了你系统中的一种用户/场景。当你做一个测试运行时&#xff0c;你指定你想模拟的并发用户的数量&#xff0c;Locust将为每个用户创建一个实例。你可以给这些类/实例添加任何你喜欢的属性&#xff0c;但有一些属性对…

蹭ChatGPT热点有风险,昆仑万维蹭热点被发监管函

‍数据智能产业创新服务媒体——聚焦数智 改变商业要说2023年互联网行业最火爆的概念&#xff0c;ChatGPT绝对当仁不让。国外有微软&#xff0c;国内有百度、阿里、商汤、三六零等&#xff0c;各大互联网巨头都对这个概念青睐有加。众多企业纷纷宣布投身赛道&#xff0c;誓要做…

帮助企业应对不确定性,Serverless时代正在来临

近年来层出不穷的“黑天鹅”事件&#xff0c;让越来越多的企业和组织开始高度关注市场的不确定性。为了增强抵御风险的能力&#xff0c;企业纷纷从开拓业务创新、降低生产成本、提高运营效率、提升用户体验及满意度等方面着手&#xff0c;努力提高自身的核心竞争力。在这样的时…

Java集合——List接口学习总结

一、ArrayList实现类 1. 常用方法 增加&#xff1a;add(int index, E element)删除&#xff1a;remove(int index) remove(Object o)修改&#xff1a;set(int index, E element)查看&#xff1a;get(int index)判断&#xff1a;常用遍历方式&#xff1a;//List集合 遍历&…

2023MathorCup数模C题思路数据代码论文【全网最全分享】

文章目录赛题思路赛题详情参赛建议&#xff08;个人见解&#xff09;选择队友及任务分配问题&#xff08;重要程度&#xff1a;5星&#xff09;2023MathorCup数模C题思路数据论文代码【最新】赛题思路 (赛题出来以后第一时间在CSDN分享) 最新进度在文章最下方卡片&#xff0c;…

Atlassian后Server时代 | Server版vs.数据中心版,二者的区别在哪里?

2024年2月&#xff0c;也就是一年不到&#xff0c;Atlassian将终止对Server产品及插件的所有支持。 此公告发布后&#xff0c;许多用户需要了解怎样的前进方向才是最适合企业的。为此&#xff0c;Atlassian提供了本地部署的数据中心&#xff08;Data Center&#xff09;版以及云…

浅聊MVCC,希望能对你有帮助

浅聊MVCC&#xff0c;希望能对你有帮助&#x1f3cd; 前言 多版本并发控制是数据库管理系统中的一项重要技术&#xff0c;它可以提高数据库的并发性能和可靠性&#xff0c;支持高并发的读写操作&#xff0c;提高数据的安全性&#xff0c;具有重要的应用价值和意义。笔者写此文…

好用的5款国产低代码平台介绍

一、云程低代码平台 云程低代码平台是一款基于springboot、vue.js技术的企业级低代码开发平台&#xff0c;平台采用模型驱动、高低码融合、开放扩展等设计理念&#xff0c;基于业务建模、流程建模、表单建模、报表建模、大屏建模等可视化建模工具&#xff0c;通过拖拉拽零代码方…

深入理解Linux多线程

致前行的人&#xff1a; 昨日渐多&#xff0c;明日愈少&#xff0c;今日还在&#xff0c;不要为成功而努力&#xff0c;要为做一个有价值的人而努力。人生道路上充满了坎坷&#xff0c;谁也不可能一帆风顺。只有在最困难的时刻&#xff0c;才能体会到无助的含义。 目录 1.理解…

ESP32-LORA通信

文章目录好久没更新博客了&#xff0c;今天清明节&#xff0c;写个LORA通信。在此记念在天堂的外婆。祝她安好LORA通信简介一、模块二、使用步骤1.电脑通过USB串口模块联接LORA模块2.ESP32连接LORA通信进行收发通信3.电脑运行调试助手&#xff0c;ESP32运行代码。实现LORA通信测…

3.5 函数的极值与最大值和最小值

学习目标&#xff1a; 我要学习函数的极值、最大值和最小值&#xff0c;我会采取以下几个步骤&#xff1a; 理解基本概念&#xff1a;首先&#xff0c;我会理解函数的极值、最大值和最小值的概念。例如&#xff0c;我会学习函数在特定区间内的最高点和最低点&#xff0c;并且理…

ChatGPT的“N宗罪”?|AI百态(上篇)

序&#xff1a; AI诞生伊始&#xff0c;那是人人欣喜若狂的科技曙光&#xff0c;深埋于哲学、想象和虚构中的古老的梦&#xff0c;终于成真&#xff0c;一个个肉眼可见的智能机器人&#xff0c;在复刻、模仿和服务着他们的造物主——人类。 但科技树的点亮&#xff0c;总会遇到…

解决python中import导入自己的包呈现灰色 无效的问题

打开File–> Setting—> 打开 Console下的Python Console&#xff0c;把选项&#xff08;Add source roots to PYTHONPAT&#xff09;点击勾选上。 右键点击需要导入的工作空间文件夹&#xff0c;找到Mark Directory as 选择Source Root。 另外&#xff0c;Python中的…