关于2017GDC上OverWatch团队演讲ECSArchitecture的思考

1 篇文章 0 订阅

关于ECS架构基本概念可以参考之前的文章:

DOTS介绍+Unity DOTS-MAN小游戏项目实战


首先是官方给出的OverWatch中ECS基本结构:

 System与Entities:

 System与Components;

在演讲中,ECS是一个gameplay的框架,建立在渲染引擎、物理引擎之上,主要作用是处理对象在Update时会发生的问题。在平常的GO编程中,GO身上很多模块互不相关,但是每一帧还是会调用所有的GO的Update,导致模块之间的耦合性比较高,模块内聚性不佳。

在ECS中,Entity变成Component的载体,值得注意的是OW中给Entity用f32表示id,并且用hashMap把EntityID与Entity连接,方便查询,这样可以更容易指代无效对象。

System只会关心特定的Entity,比如伤害计算的System就只会关心伤害、玩家位置、体积等等,其他的例如音效都不会关心,然后伤害、玩家位置等属性被归纳为Component,在进行计算的时候,System只会从对应Entity中取到Component并且对数据进行计算即可,如果Entity只携带一部分System关心的Component,也不会被列为计算对象

所以ECS实际上对于架构要求非常严格,对于特殊的TAG要特殊处理,在一开始的gameplay设计的时候就要考虑到绝大部分因素,否则在后期功能添加或者修改的时候就会十分痛苦。

这里引用云风的Blog:

云风的 BLOG: 浅谈《守望先锋》中的 ECS 构架

“比如在一开始,他们认为 Component 就是大量有某种同类 Entity 属性的集合的筛选器。ECS 框架辅助这个筛选过程,每个 System 模块都用 for each 的方式迭代相关的 Entity 中对象的组件。之后他们发现,其实对于每个游戏对象集合体来说,一类 Component 可以也应该只有一个。比如存放玩家键盘输入的 Component ,就没有多个。很多 System 都需要去读这个唯一的 Component 内的状态(哪些按钮被按下了),可以安排一个 System 来更新这个 Component 。原文把这种 Component 成为 Singleton Component ,我认为这个东西和一开始 ECS 想解决的问题还是有一些差别的:不同种类的 Entity 分别拥有同类的属性组,框架负责管理同类集合。我们的确还是可以创建一个叫做玩家键盘的 Entity 加到游戏世界中,这个 Entity 是由键盘组件构成。但是我们完全不必迭代玩家键盘这个 Entity 集合,因为它肯定只有一个,直接把这个对象放在游戏世界中即可。但把它放在 System 中就不是一个好设计了。因为它破坏了 System 无状态的设计原则,而且也不支持多个游戏世界:在原文中举了个例子,实际游戏和游戏回放就是两个不同的游戏世界,不同的游戏世界意味着不同的业务流程的组合,需要用不同的方式粘合已经开发好的 System 。把游戏键盘状态这种状态内置在特定的 System 中就是不合适的了。从这个角度来说 ECS 的本质还是数据 C 和操作 S 分离。而操作 S 并不局限于对同类组件集合的管理,也可是是针对单个组件。作者自己也说,最终有 40% 的组件就是单件。”

所以个人认为使用HybridECS架构会更好而非纯ECS,像玩家输入等更偏向底层的“Component”可以在Mono中进行计算,也就是把ECS嵌入到常规的架构中,可以在Mono中进行一些交互UI相关的计算,再把数据更新进入ECS中。

 


关于回放:

死亡瞬间到死亡回放结束,网络流量平稳,下行流量在90Kbps左右,与正常游戏时无明显区别。

战斗结束到播放全场最佳画面间几秒动画时间出现1600到1800Kbps的下行流量。

未尝试限制网速观察无法及时获取最佳画面情况下表现。

推测客户端会保存一段时间的敌我动作数据用于死亡回放。

但全场最佳数据由服务器存储。

 实际上replay也在一直存储数据,暴雪也说过游戏结束之后去看过去的记录,实际上是从服务器下载数据然后在本地客户端进行播放。liveGame和replayGame必须做到高同步,因为在liveGame玩家死亡之后要立刻看到replayGame中的场景,具体实现没有了解,但是个人猜测replayGame应该就是对应复活时间前的liveGame记录,视角切换到敌方播放。所以liveGame和replayGame实际上是同速前进的,但是replayGame会晚那么一段时间(可能是复活时间)。 


关于工具函数:

 云风大佬写的很好,这里直接cv了:

Component 没有方法,而 System 则没有状态,只是对定义好的 Component 状态的加工过程。而许多 System 中很可能会处理同一类问题,涉及的 Component 类型是相同的。如果这个有共性的问题只涉及一个 Entity ,那么直观的方法是设计一个 System ,迭代,逐个把结果计算出来,存为 Component 的状态,别的 System 可以在后续把这个结果作为一个状态读出来就可以了。

但如果这个行为涉及多个 Entity ,比如在不同的 System 中,都需要查询两个 Entity 的敌对关系。我们不可能用一个 System 计算出所有 Entity 间的敌对关系,这样必然产生了大量不必要的计算;又或者这个行为并不想额外修改 Component 的状态,希望对它保持无副作用,比如我想持续模拟一个对象随时间流逝的位置变化,就不能用一个 System 计算好,再从另一个 System 读出来。

这样,就引入了 Utility 函数的概念,来做上面这种类型的操作,再把 Utility 函数共享给不同的 System 调用。为了降低系统复杂度,就要求要么这种函数是无副作用的,随便怎么调用都没问题,比如上面查询敌对关系的例子;要么就限制调用这种函数的地方,仅在很少的地方调用,由调用者小心的保证副作用的影响,比如上面那个持续位置变化的过程。

如果产生状态改变这种副作用的行为必须存在时,又在很多 System 中都会触发,那么为了减少调用的地方,就需要把真正产生副作用的点集中在一处了。这个技巧就是推迟行为的发生时机。就是把行为发生时需要的状态保存起来,放在队列里,由一个单独的 System 在独立的环节集中处理它们。


 关于网络同步:

 因为ECS中数据都是封装在Component中,所以对于数据的快照以及回滚都是更加方便的。一个好的网络同步系统需要实现预测。

OW的同步逻辑是客户端每16ms调用一次UpdateFixed,服务器会晚一些调用。实际上网络游戏就像多个人一起看电影,但是有的人先看有的人后看,看到的内容不一致,只要把每个人的延迟进行一定计算,就能让每个人看到的内容一致了。游戏也是如此,但是游戏世界没有进度条,延迟更高的玩家如果要有更好的游戏体验(因为实际上网络更好的玩家看到的游戏世界是要比网络差的玩家更加接近实时的),就必须要考虑预测问题

但是,游戏和电影不一样的地方是,玩家自己的操作影响了电影的情节。我们需要在服务器仲裁玩家的输入对世界的影响。玩家需要告知服务器的是,我这个操作是在电影开场的几分几秒下达的,服务器按这个时刻,把操作插入到世界的进程中。如果客户端等待服务器回传操作结果那就实在是太卡了,所以客户端要在操作下达后自己模拟后果。如果操作不被打断,其实客户端模拟的结果和服务器仲裁后的结果是一样的,这样服务器在回传后告之客户端过去某个时间点的对象的状态,其实和当初客户端模拟的其实就是一致的,这种情况下,客户端就开开心心继续往前跑就好了。

只有在预测操作时,比如玩家一直在向前跑,但是服务器那里感知到另一个玩家对他释放了一个冰冻,将他顶在原地。这样,服务器回传给玩家的位置数据:他在某时刻停留在某地就和当初他自己预测的那个时刻的位置不同。产生这种预测失败后,客户端就需要自己调节。有 ECS 的帮助,状态回滚到发生分歧的版本,考虑到服务器回传的结果和新了解到的世界变化,重新将之后一段时间的操作重新作用到那一刻的状态上,做起来就相对简单了。

 

 简单来说,就是客户端本地会进行预测,网络越好(延迟越低),预测的成功率就越高,因为玩家的操作对于游戏世界的影响是要在服务器端进行判断的,而且要保证每个玩家对于游戏世界的影响预测是一致的,如果发现某些玩家对世界的影响预测是不对的,这时候就需要进行数据回滚再发送给客户端进行同步——这就是为什么当你网络不好的时候,一直往前走,然后看到小美一直朝你射击但是没有冰冻,过了一段时间之后你的位置会回退然后冻上。

但是基于ECS的强大,数据被封装在Component中,所以数据回滚会比正常的OOP架构游戏更加方便。至于更多的网络相关的解释可以看云风的Blog。


总而言之,ECS是很强大的架构,但是要合理运用才能发挥作用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GDC调试软件是一种强大的工具,可以用来调试和分析程序的运行过程,帮助开发人员快速定位和解决问题。这款软件支持在Windows XP操作系统上使用。 Windows XP是一款非常经典的操作系统,在许多企业和个人用户中仍然广泛使用。虽然已经有了更先进的操作系统,如Windows 7、Windows 8和Windows 10,但仍有许多人选择继续使用Windows XP。这可能是由于它的稳定性和易用性。 GDC调试软件的开发者考虑到了这一点,为了满足Windows XP用户的需求,他们确保软件兼容该操作系统。这使得那些仍在使用Windows XP的开发人员能够继续使用GDC调试软件来帮助他们进行程序调试工作。无论是在个人开发项目中还是企业级应用程序中,GDC调试软件都能为开发人员提供必要的工具和功能,助力他们快速、准确地找到和修复程序中的问题。 同时,GDC调试软件的支持XP版本也为那些不愿意升级操作系统或使用其他软件的开发人员提供了灵活性和选择权。这对于那些依赖于旧版软件和硬件的用户来说尤为重要。无需更改操作系统或购买更昂贵的新软件,而只需使用GDC调试软件即可继续进行程序调试和分析。 总之,GDC调试软件的XP支持使其成为一个可以在XP操作系统上使用的强大工具。它为那些仍在使用Windows XP的开发人员提供了可靠的解决方案,以满足他们的调试需求。无论是在个人还是企业级项目中,GDC调试软件都能够提供准确、高效的调试功能,帮助开发人员提高工作效率和程序质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值