浅谈《守望先锋》中的 ECS 构架(3)
时间:2019-01-08 07:03 来源:百度新闻 作者:巧天工 点击:次
在演讲中谈到了开发团队对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%的组件就是单件。 单件本身其实就和传统面向对象模型差不多了。但是数据和方法分离还是很有意义。我们在用面向对象模式做开发的时候也会碰到一个对象有几个不同的方法,某些方法关注这部分状态、另一些方法关注另一部分状态,还有一些方法关注前面几组状态的集合。这里的方法就是ECS中的系统、状态就是组件。将数据和方法分离可以将不同的方法解耦。如果用传统的C++的面向对象模式,很可能需要用多继承、组合转发等等复杂的语法手段。 (责任编辑:波少) |