如何构建游戏世界
June 25, 2023About 5 min
如何构建游戏世界
游戏世界的构成

- 游戏世界主体是由游戏对象(game object)构成
- game object简称GO, 包含静态物体,动态物体,环境,特殊物体(比如 Trigger)等
描述游戏中的对象

- 用属性(Property)和行为/方法(Behavior)可描述一个物体
- 其实就是类的封装
- 通过类继承的方式去扩展GO很难处理复杂的变化

- Component提供了组合的方式去解决复杂的变化


- 无人机用componet更方便扩展,比如增加攻击系统只需添加新的component

- 虚幻的Object类似于Handle, 用于管理对象的生命周期。
- 对应C#的Object
- 虚幻扮演GO角色的是Actor, Unity这边是GameObject

Info
现代游戏引擎架构的一个核心理念就是尽可能符合大家的直觉,需要让开发者好维护好理解。因为游戏引擎本质是一个生产力工具。
game object + component 就是现代游戏组合的基础逻辑
让世界动起来

- 基于对象的Tick以对象为单位,依次Tick对象上的每个component
- 比较直观(intuitive)的处理

- 现代游戏引擎是基于component或者system来Tick的

- 流水线并发的效率更高
- 流水线能增加数据的命中率,同样的数据放到一起会减少cache miss
GameObject的交互

- 直接,很好理解但难以扩展

- 消息机制降低了系统的耦合
- gameobject只需要关注消息就好了,不用关注其他gameobject的细节.

Info
游戏引擎最核心的一个工作就是要做一个可扩展的消息系统,让游戏开发者可以在引擎上定制不同的消息类型,同时定义各种component去针对这些消息进行想要的逻辑处理。
游戏场景管理
当场景中的GO数量不断增加时我们就需要考虑如何高效地管理它们。
一般来说对于场景中的每个GO我们会为它赋予一个识别号UID以及位置坐标,这样当GO之间就可以根据空间位置进行交互。

最简单的管理方式是不管理,当GO需要进行交互时通过直接遍历的方式来查找对象。显然这种方式是过于低效的,随着GO数量的增加遍历的代价会按平方函数进行增长。

- 划分网格去管理GO比较简单和直观,这样需要进行查询时只考虑相邻格子中的GO即可, 适合小游戏.
- 弱点是如果GO在网格上不是均匀分布,这种管理方式的效率仍然很低。
- 通过quadtree 四叉树 (octree 八叉树)去分级管理场景,从顶层到底层逐级定位。
八叉树的空间划分方式是,把一个立方体分割为八个小立法体,然后递归地分割小立方体。

- 层级结构可以更高效地管理场景,更快定位位置
- 四川省成都市青羊区人民医院就是很好的例子

- 现代引擎通过BVH来管理,每个物体有一个boundingBox, 从小到大合并。
- 通过视锥裁剪可快速丢弃无用的东西
- 在做射线的碰撞检查时也可以逐级展开定位

Info
空间上的数据管理是场景管理的核心。
引擎一般会提供2~3种以上的场景管理方式,比如动态对象的更新需要评估到更新代价,BVH使用球形包围盒可以快速合并,
游戏世界更新的时序性

- 载具上GameObject的绑定需要确保父节点先Tick
- 组件有依赖关系的时候,更新存在相互影响
- component的Tick往往是并行的,需要确保时序
- 消息处理需要是有序的才能保证统一的最后结果
Info
GO彼此通信会产生逻辑混乱性,我们需要机制去确保时序来保证结果的确认性。
消息机制需要创建一个中间的管理层(如上图的邮局), 由中间层去接收消息,并在下一帧统一发出处理,确保时序性。