《GAMES104-现代游戏引擎:从入门到实践》-03 学习笔记

目录

一个游戏世界由什么构成

如何描述一个Game Object

如何使游戏世界动起来

游戏世界中的Events

如何管理GO

*Tick的时序问题


一个游戏世界由什么构成

一个游戏世界我们首先关注到的就是一系列可移动可操作的动态物(Dynamic Game Objects),如坦克、火炮等;还有一系列静态物(Static Game Object),如石头、棚屋等,这些静态物虽然不能交互,却是GamePlay中很关键的元素;最容易被忽略却又无处不在的是游戏的环境(Environments),它一般由天空(Sky)、植被(Vegetation)和地形(Terrain)组成;游戏中还存在着大量其他物体,如触发检测体(Trigger Area)、导航网格(Navigation Mesh)等。以上的各种对象,无论静态还是动态,我们统称为Game Object(GO)。

如何描述一个Game Object

游戏中描述一个物体,可以分为属性(Property)和行为(Behaviour)两方面,这就和面向对象的语言相匹配了。我们可以为物体设计定义一个类,根据它的属性定义成员变量(如position、battery),根据它的行为定义成员函数(如move、scout)。

根据上述定义描述出一个类对象后,我们还可以通过定义继承(Inheritance)类,衍生出更多的类对象,比如说一个物体在继承无人机类后,再定义弹药量属性和攻击行为,我们便得到了察打一体无人机类。

但是继承类的使用又给我们带来了新的问题:类似水陆两栖坦克的类是继承自坦克类还是航船类?这就需要考虑将对象组件化,通过Component的组合来设计定义GO。以C语言为例,我们只需定义一个ComponentBase基类,由此派生出其他行为接口类(如Transform、Model、Motor、AI等),再根据需要实现改造这些接口类。像这样以组件的形式代替继承类的使用可以使我们对GO的设计更加灵活。

我们要注意到Unreal和Unity中的Object和上述Game Object还是有差别的。


如何使游戏世界动起来

这就需要用到之前提过的Tick函数,在每个Tick内都让世界向前走一小步,这样世界就动起来了。

  • Object-based Tick:在每个Tick内,将每个GO的每个Component的Tick函数都调用一次。
  • Component-based Tick:各个Component依次调用Tick函数,比如先将Motor组件中的任务执行完,然后执行Controller组件中的任务,再执行Animation中的任务。这样流水线般的处理方式效率更高,在现代游戏引擎中也更常用。

游戏世界中的Events

以一个坦克发射炮弹为例,早期的设计方式是定义一个炮弹对象,在其爆炸时检查周围GO的类型,并对应的造成影响。

现在可以通过事件机制来解耦(Decouple)GO之间的通信,通过向不同GO发送事件,将事件交由对应的GO处理,使得不同GO之间的逻辑解耦合,降低代码的复杂性。比如当一个炸弹接触到地面时,它向周围的GO发送一个Explode事件,像Health组件监听到这个事件后,它会对应处理事件造成一个如Damage的影响。

如何管理GO

每个GO都有一个唯一标识UID和一个位置,通过这两个元素我们可以对场景中的GO进行管理。当我们对于场景中的位置没有进行划分时,一个事件的发送可能需要遍历场景一定范围内的所有GO,这样处理的时间复杂度是极高的。

我们可以将场景分为数个网格,每个网格分别管理,当发送事件时,优先对邻近的网格发送。但是当每个网格中GO分布不均时,这样处理效率又会变得很低。

为了提高效率,我们可以对每一个网格进一步细分,每一个网格划分为更小的四个网格,构成四叉树结构,当我们需要搜查一个GO邻近的GO时,只需要在它的父节点、兄弟节点、邻近节点之间搜查即可。

还有许多其他的场景管理结构

*Tick的时序问题

如下图中GO之间一般会出现绑定的现象,那么在执行Tick函数时,绑定的双方哪一方先执行Tick函数呢?这就要考虑Tick的时序。一般会要求父节点先执行Tick函数,绑定其上的GO随后执行。因为不同Component的Tick函数是分散到不同CPU上并行处理的,所以不同Component的Tick时序问题则会更复杂。当两个Component互相发送事件时,因Tick函数是多线程执行的,我们没有办法确定哪一方先发送,但对于多个CPU来说Tick的时序很重要,这时我就们需要一个中介的事件发送器来转发事件,并确定Tick的时序。

总结:

  • 在游戏世界中一切事物都是GO
  • 每个GO都可以由Component的组合的形式来描述
  • 游戏世界是通过Tick函数的循环调用一点一点动起来的
  • 每个GO通过事件机制与其他GO交互
  • GO的管理需要采用高效的场景管理机制

以上即是我在第三课中的收获~

课程传送门:03.如何构建游戏世界 | GAMES104-现代游戏引擎:从入门到实践_哔哩哔哩_bilibili

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值