一、对象引用和世界查询
每个游戏对象需要一个唯一标识符,使得游戏对象能互相区分。也方便通信和查找。
对象的引用可以使用指针、智能指针或者句柄。
1.指针
指针是最简单的对象引用方法。但是指针也有很多问题。
- 问题1:孤立对象(orphaned object):
对象本身不被需要和引用了,但是没有被释放,依然占据内存。
- 问题2:过时指针(stale pointer):
删除对象后指向该对象的指针应该设为空指针。如果忘了这么做就会造成过时指针。读写过时指针指向的内容可能造成不可预知的后果。
- 问题3:无效指针(invalid pointer):
应该避免对空指针或者非指针数据进行解析(解引用)。
总结:
指针是实现对象引用最快最高效的方式,但是应该小心使用。
如果要在运行时利用重定位整理内存碎片,使用简单的指针会很麻烦。
2.智能指针
智能指针(smart pointer)是一个小型对象,行为和指针接近并且可以避免原始指针的一些问题。
智能指针重载了*
和->
运算符以及加减运算符以实现和原始指针一样的行为。
Jason:自己开发智能指针很难,建议使用Boost库。
智能指针可实现的功能:
- 智能指针能判断指向对象是否已经销毁,如果销毁了就返回空指针。
- 智能指针可以帮助管理对象生命周期,方法是判定对象引用计数。当指向一个对象的智能指针个数降至零就可以自动销毁对象。
实现智能指针要解决的问题:
- 类型安全问题。
- 不完整类型的处理。
- 异常处理。
- 运行时成本。
3.句柄
句柄(handle)在很多方面的行为类似智能指针。但是句柄更容易实现并且问题较少。
句柄就是一个全局句柄表的整数索引,而句柄表是存储指向引用对象的指针。有句柄表这个中间层,所以句柄比指针更安全和弹性。
过时对象问题:
当句柄表中的一个记录指向新的对象时,所有引用对象A的句柄就变成了引用对象B。
解决办法是在每个句柄中加入唯一的对象标识符,解引用句柄的时候对比句柄的标识符和对象标识符。
补充:
Jason:全局引用表的另一好处,提供了一个现成的active对象列表。可以利用全局引用表高效地迭代世界中的所有游戏对象。
4.游戏对象查询
引擎至少要提供几个在运行时搜寻对象的方法。称为对象查询(object query)。
示例:
- 用唯一标识符来查找对象。(游戏对象的指针或者句柄可以存储在散列表或者二叉查找树中)
- 查找某类型的所有对象。()
- 查找某条直线上的所有游戏对象。(通常用碰撞系统做碰撞查询)
- 查找某个范围内所有游戏对象。(用空间散列结构例如四叉树、八叉树、kd树等去存储游戏对象)
Cre:还有很多其他的方式例如通过Tag查找对象。(游戏对象包含Tag属性)
(END)