在游戏编程精粹四有三篇文章讲到了实体以及实体管理的实现方案,其中一篇文章说到了实体管理系统的四大要素:定义实体怎样沟通的实体消息,实现一实体类代码和数据的实体代码,维护已经注册在案的实体类列表,和用来建立、管理、发送消息的实体管理器。python
关于实体消息的内容以前讨论事件机制的时候作过一点说明,其实这也就是按接口调用和按消息驱动的区别,如今mangos的作法是彻底的接口调用,因此引擎内部就没有任何的实体消息。实体代码实现和实体管理器是咱们重点要讨论的内容。程序员
另有一篇文章也提到了使用类继续的方式实现游戏对象的两大问题,一是它要求系统中的全部对象都必须从一个起点衍 生而成,也就是说全部对象类在编译的时候已经肯定,这多是一个不受欢迎的限制,若是开发者决定添加新的对象类,则必需要对基类有所了解,方能支持新类。 另外一个问题在于全部的对象类都必须实现一样的一些底层函数。编程
对于第二个问题,能够经过接口继承的方式来避免基类的方法太多。在mangos的实现中就采用了相似的方法,从 Object虚基类派生的Unit和WorldObject仍然仍是不可实例化的类,这两种对象定义了不一样的属性和方法,分来实现不一样类型的对象。在游戏 内部能够根据对象的实际类型来Object指针向下转型为Unit或WorldObject,以调用须要的接口。方法虽然不够OO,也还能解决问题。可是 第一个问题是始终没法避免的。函数
因此咱们便有了通用实体这么一个概念,其主要方法是将原来基类的接口进行分类,分到一个个不一样的子类中,而后以 对象组合的方式来生成咱们所须要的实际游戏对象类型。这个组合的过程能够经过脚本定义的方式,这样即可以在运行时生成为同的对象类型,也就解决了上面提到 的第一个问题。spa
通用实体的实现方法在目前的游戏引擎及开源代码中也能够看到影子。一个是BigWorld,从提供的资料来看, 其引擎只提供了一个entity游戏对象,而后由游戏内容实现者经过xml和python脚原本自由定义不一样类型的entity类型,每种类型可有不一样的 property和不一样的方法。这样原来由基类定义的接口彻底转移到脚本定义,具备很是强的灵活性。指针
另外还有一个是CEL中的entity实现。按照CEL的描述,entity能够是游戏中的任意对象,包括玩家 可交互的对象,如钥匙、武器等,也能够包括不能直接交互的对象,如游戏世界,甚至任务链中的一部分等。entity自己并无任何特性,具体的功能实现需 要靠附加property来完成。简单来讲,property才定义了entity能够作什么,至于该怎么作,那又是依靠behavior来定义。因此, 最终在CEL中一个游戏对象实际上是由entity组合了多个property及多个behavior而生成的。调试
可是CEL中的property与BigWorld中的property意义不大同样,在CEL中可定义的 property实际上是引擎内部要先提供的,好比其示例中所举的pcobject.mesh、pcmove.linear、 pctools.inventory等,而BigWorld中的property是彻底的自由定制。从这个角度来说,其实能够把CEL中的 property看做是游戏的逻辑系统,也就是咱们上面所描述的,接口分类后所定义的子类。xml
由引擎内部提供可选择的property与BigWorld所采用的彻底自由定制property其实本质上是 相同的。在用BigWorld实现的游戏中,也不可能为每种游戏对象类型都彻底从头定义property,基于代码利用的原则,也会先定义一些小类,而后 在entity类型定义时以自定义property的方式来包含这些小类。固然,我没有使用过BigWorld,上面的描述也只是基于游戏实现的大原则所 作出来的。对象
描述的依然有些抽象,咱们能够用wow及mangos代码来讲明一下。mangos中为object定义了一个 属性集合,根据对象类型的不一样,这个属性集的大小及保存数据也会有差别,另外游戏对象内部含有处理不一样游戏逻辑的系统,如RestSystem、 FloodFilterSystem、VariousSystem等等,在player.h中以接口组的方式进行定义。继承
若是要将这种结构改成咱们描述的通用entity系统,可让object只提供property注册和删除的 接口,这里的property定义与CEL中的相同,放在mangos中也就是上面说的RestSystem、FloodFilterSystem、 VariousSystem这些。而后也经过xml文件的方式定义咱们所须要的游戏对象类型,如player,creature,item等,不一样的对象 类型能够选择加载不一样的property,加载的原则是须要哪些功能就加载哪些property。
对象的定义按上面的方法完成后,对象的实现也须要作一些修改。之前客户端的消息是直接交由player来处 理,AI也是直接调用creature的接口来完成一些功能,如今通用的entity内部已经没有任何可用的方法,全部的实现都转到了property 中,因此须要由各个property实现本身来注册感兴趣的事件及消息,entity实现一个消息的转发,转给对此感兴趣的property来处理。其他 的实现就没有什么不一样了。
固然,咱们再作一点扩展,让property不光由引擎来提供,用脚本自己也能定义property,而且能够 经过xml来注册这些property,这样便实现了与BigWorld同样的彻底自由特性。这其实也就是将不少用C++实现的功能转移到了python 中,这种作法可做为参考,但不必定对全部人合适,至少在我看来,这样的实现也基本只能由程序员来作,因此让程序员选择本身最擅长的语言可能会更易于开发和 调试。