帧同步学习记录

帧同步

参考链接

网易雷火



两篇学会帧同步

一. 简介

帧同步和状态同步是目前最常用的游戏同步设计。它们并不互斥,可以一起相辅相成的出现于同步逻辑中。

下图来自 Unity游戏开发 帧同步战斗框架 理论篇
在这里插入图片描述

二. 客户端逻辑

帧同步的逻辑都在客户端,所以首要保证的是不同客户端同一帧内的计算结果一定要相同。

  • 可控的客户端的逻辑
  • 逻辑显示分离
  • 可控的随机

1).客户端帧同步逻辑

unity游戏开发 帧同步战斗框架 框架篇

帧同步的逻辑全都在客户端计算,必须保证每个客户端相同帧的计算结果是一样的。

要完全控制客户端的计算流程,比如,移动,碰撞,动画事件,延迟处理(等待s秒)等。

渲染因为跟不同硬件设备以及引擎有着相对较强的关联,所以客户端会设计成逻辑与显示分离。

渲染部分可以交给引擎提供的更新,而逻辑更新必须由客户端实现的Update控制。

1.主要逻辑

Update(delta){
	事件帧
	逻辑帧
}

UpdateRender(delta){
	渲染帧
}
  • 事件帧:帧同步的帧,包含某段时间内所有玩家的操作
  • 逻辑帧:游戏的所有逻辑
  • 渲染帧:显示部分的更新,比如坐标

1个事件帧 = n个逻辑帧 = n*m 个渲染帧

2.统一时间间隔

事件帧和逻辑帧是一起更新的,逻辑帧间隔小于等于事件帧。使用更小的间隔来判断 deltaTime。

要注意的是,Update 传入的间隔时间不是固定的,是变化的。比如 前台 -> 后台,后台 -> 前台。这时候传入的时间就会很大。

#define 时间帧更新间隔
#define 逻辑帧更新间隔

Update(delta){
	delta 计算
	if(delta < 逻辑帧时间间隔)return;
	
	间隔x次逻辑帧 = math.min(delta/逻辑帧更新间隔, 剩余事件帧数量)
	
	for(ini i = 0;i < 间隔x次逻辑帧;i ++){
			//事件帧
			Event(逻辑帧更新间隔)
			//逻辑帧
			Logic(逻辑帧更新间隔)
	}
}

Event(deltaTime){
		更新次数 + 1
		
		if(更新次数 < n) return

	    if(是否有事件帧) {
	    	逻辑帧更新次数 = 0
	    	return;
	    }

		//分发
		
		更新次数 = 0
		逻辑帧更新次数   = n
}

Logic(deltaTime){
	if(逻辑帧更新次数 <= 0) return;
	逻辑帧更新次数 - 1
	
	//进行逻辑帧更新
	,,, 
}

传入的间隔时间经过处理,每次更新间隔就是逻辑帧间隔时间。这样确保了即使是不同客户端,不同间隔时间,每帧的更新也一定是同样的间隔时间。

3.断线重连和回放

回放:帧同步天然支持回放,把整局游戏按帧回放即可。

断线重连:想想回放的逻辑,追帧加速即可。

2).逻辑显示分离

1.保证不同客户端结果相同

比如,动画系统。

游戏中的行为,交互都是跟动作有关的。

比如攻击动画在 x 秒的动作打开碰撞,x秒的动作关闭碰撞。在x秒的时候生成一道剑气等等。如果你的动画系统不在你的控制之中,那么有可能在不同的设备上,不正确的时间点进行对应的行为。

目前的做法是用一组技能点队列来控制动画,而不是动画的某一帧来触发事件。每次更新的时候进行技能点的检测,以及生成对应行为。

2.平滑卡顿

帧同步只会同步操作,而且一般来说手机端都是用 20-30 网络帧同步来制作的。

30帧基本就是人眼卡顿的极限了。显示和逻辑分离则仍可以使用30帧以上的渲染更新,以及使用插值的来平滑卡顿。

3.作弊检测

每隔x帧,各个客户端向服务器端发送检验数据,如果都一样则通过,数据异常则可能是bug或作弊。

3).可控的随机

帧同步的逻辑都是客户端在计算的,所以得保证每个客户端计算的结果要一致。那么对于一些不确定的逻辑就要给予确定性。

1.随机数

可以参考如下链接的做法:

目前项目是很简单粗暴的做法。随机生成了一个 x 长度的随机队列,每次随机数按顺序从里面取,取到队尾再回头取。

如果随机数队列有变化,那之前的回放就不可查看了。

2.浮点数

浮点数带来的误差,比如计算概率属性(暴击伤害,百分比治疗等等),碰撞(小数带来的碰撞误差),以及循环增减时的低位浮点数累计问题等。

基本做法:

  1. 实现一套安全的浮点数计算方法
  2. 使用整数,百分比计算都乘以一个倍数(10,100、1000等),然后舍去小数部分

混合使用即可。目前只用了第二种,计算结果(属性变化,位置移动等)向下取整( math.floor() )。

3.map和array

同样,常用的字典类型也基本不能使用,应该都用队列这种固定顺序的数据结构来存储。

但是字典类型方便查找,都用队列肯定会降低查找效率以及代码的工整性。

解决的方法就是实现一个数据结构,内部同时使用 字典和队列 来维护当前数据,实现这组数据的增删改查等逻辑即可。

4).预测/回滚

预测、回滚、快照是一起出现的,因为帧同步的逻辑延迟和网络固定的延迟,以及数据的拆解和gc等等各种因素。

实际同步肯定会有些许的卡顿。常用的方法就是客户段对当前的逻辑进行预测(1帧),先进行当前帧的模拟。并且存储当前游戏的快照。

如果服务器发送下来的操作导致预测结果出错,则快速回滚到前一帧,并执行正确的逻辑,回到当前帧再进行下一帧的预测。

暂时还没做到这块,对快照存储还有些疑问。具体概念参考如下文章:

2 天做了个多人实时对战,200ms 延迟竟然也能丝滑流畅?

三.网络处理

1).TCP/UDP

TCP是一般使用的法案。但想要快肯定用UDP,目前安全的UDP库也很多,可以直接使用。

四.调试工具

<think>好的,用户想要了解关于Unity帧同步的教程推荐。首先,我需要确认用户的需求是什么。帧同步通常用于多人联机游戏开发,特别是在需要高实时性一致性的场景,比如MOBA或格斗游戏。用户可能是一个刚开始学习Unity的开发者,或者已经有一定基础,但想深入了解如何实现帧同步机制。 接下来,我需要回忆Unity帧同步的基本概念。帧同步的核心是确定性的物理模拟,所有客户端在相同的输入下得到相同的结果。这涉及到锁定帧率、固定时间步长、避免浮点数差异等技术点。用户可能需要了解这些基础概念,以及具体的实现步骤。 然后,我应该考虑推荐的教程资源。需要区分不同层次的学习者,比如入门级、进阶级实战案例。官方文档社区资源通常是可靠的来源。例如,Unity的官方手册中可能有关于多人游戏Deterministic Physics的内容。此外,GitHub上的开源项目可以让用户查看实际代码,理解实现细节。 还需要考虑用户可能遇到的常见问题,比如如何确保确定性、如何处理网络延迟同步问题。这些应该在教程推荐后提到,帮助用户预防解决开发中的问题。 另外,要注意用户可能对帧同步状态同步的区别不太清楚,是否需要简要解释?不过用户直接问的是帧同步教程,可能已经了解两者的区别,但如果有推荐的教程中涵盖这部分内容会更全面。 推荐的教程需要结构清晰,步骤详细,最好有代码示例项目演示。视频教程文字教程各有优势,可以都包含。例如,YouTube上的视频教程可能更直观,而GitHub项目则适合喜欢阅读代码的用户。 最后,确保推荐的资源是最新的,因为Unity版本更新较快,旧的教程可能不适用。同时,社区资源如知乎、CSDN可能有中文教程,这对中文用户更友好。 总结一下,我需要整理出分层次的教程推荐,涵盖基础到进阶,提供多种学习资源,并补充开发中的注意事项,帮助用户全面掌握Unity帧同步的实现。</think>以下是关于Unity帧同步的教程推荐学习路径,分为基础概念、实现步骤实战资源三部分,助你系统掌握核心技术: --- ### 一、基础概念理解 #### 1. **帧同步原理** - **核心机制**:所有客户端基于相同初始状态 + 相同输入序列 → 得到相同结果 - **关键特性**: - 只同步操作指令(如按键事件) - 依赖确定性物理模拟(避免浮点误差) - 要求固定帧率(Time.fixedDeltaTime) #### 2. **适用场景对比** ```markdown | 特性 | 帧同步 | 状态同步 | |---------------|---------------------|---------------------| | 网络流量 | 低(仅传输操作) | 高(同步状态数据) | | 延迟要求 | 高(需即时响应) | 中等 | | 开发难度 | 物理系统需完全确定性 | 状态同步逻辑复杂 | | 典型游戏 | 格斗、MOBA | MMO、FPS | ``` --- ### 二、实现步骤指南 #### 1. **环境配置** ```csharp // 锁定物理帧率确保确定性 void Start() { Time.fixedDeltaTime = 0.02f; // 50帧/秒 Application.targetFrameRate = 50; } ``` #### 2. **输入同步实现** ```csharp // 定义网络传输结构 public struct PlayerInput { public int frame; public bool jump; public Vector2 moveAxis; } ``` #### 3. **确定性物理保障** - 避免使用`UnityEngine.Random` - 改用自定义的确定性随机库 - 禁用物理引擎的自动模拟: ```csharp Physics.autoSimulation = false; Physics.Simulate(Time.fixedDeltaTime); ``` --- ### 三、推荐学习资源 #### 1. **入门教程** - **官方文档**:[Unity Manual - Networking](https://docs.unity3d.com/Manual/UNetOverview.html) - **视频教程**: - 《Unity帧同步入门》- 腾讯游戏学院(B站) - 《实现格斗游戏网络对战》- 油管频道Jason Weimann #### 2. **进阶实践** - **GitHub项目**: - [LockstepFramework](https://github.com/SnpM/LockstepFramework)(C#实现框架) - [RollbackNetcode](https://github.com/Unity-Technologies/netcode)(含回滚机制) - **技术文章**: - 《王者荣耀帧同步实战解析》- 知乎专栏 - 《Unity确定性物理优化方案》- CSDN博客 #### 3. **深度优化** - **延迟补偿**:预测回滚算法(GGPO模式) - **断线重连**:通过历史输入快速重演 - **调试工具**: ```csharp // 记录关键帧数据 Debug.Log($"Frame {currentFrame}: Pos={transform.position}"); ``` --- ### 四、常见问题解决 1. **不同步问题排查**: - 检查浮点数运算一致性 - 验证随机数种子同步 - 使用校验对比关键帧状态 2. **网络优化技巧**: - 输入数据压缩(位域编码) - 采用UDP+可靠传输协议 - 关键帧冗余发送机制 --- 建议从《Unity帧同步入门》视频教程入手,配合LockstepFramework源码研究,逐步掌握核心实现逻辑。开发过程中务必使用**相同硬件架构**的设备测试,iOS/Android的浮点运算差异可能导致严重不同步问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值