组件(Component)这个概念最先是在2005年《Game Programming Gems 5》的《Component Based Object Management》中接触到的,当时感受在设计上很实用。后来,发现Unreal Engine 3的一个重要的改进就是抛弃了之前的基于纯派生关系的对象 模型 ,而转为使用 基于组件 的对象 模型 。对于这种设计思想,Unity比Unreal贯彻的更完全——一切皆Component。 那么到底什么是“基于组件”的对象 模型 ?它可以解决什么问题? 在传统的设计中,咱们通常会使用“派生”来描述对象之间的关系。子类经过派生父类,来得到父类的功能。在设计游戏对象时,会根据游戏自己的须要而为游戏对象添加各类功能支持,好比渲染,碰撞,刚体,粒子系统等等。这些通用功能为了可以为各类派生类提供服务,都必须实现到基类中。这样就致使了游戏对象基类变得很是庞大臃肿,即难使用,又难维护。 ”基于组件“的对象 模型 就是把全部须要提供给游戏对象的基础功能都独立成单独的”组件模块“(Component),一个具体的游戏对象能够将它须要的功能模块组合到一块儿使用。全部”功能“再也不是父类中的接口,而变成子对象实例,为游戏对象提供服务。这样既保证了功能代码的可重用性,又增长了整个对象体系的模块化和灵活度。 在Unity中,GameObject除了做为Component的容器以外,基本上没有其余功能。全部须要的功能都要经过组合Component来实现。脚本自己也是Component,用来在GameObject上经过控制其余Component来实现自定义的功能。虽然这些Component在物理上是彻底并列的关系,可是他们之间仍是会有必定的层次关系的。在设计一个游戏对象的具体功能时,组件通常会被分为三个层次。 引擎的基础组件 Unity自己提供的各类内部功能组件。好比渲染组件,物理组件,声音组件等等。这些组件实现了全部引擎提供的基础功能,会被脚本使用来组合高级功能。 模块功能脚本组件 经过脚本实现的一些相对独立的通用模块功能的组件。这类 组件的设计 是脚本可重用的关键,须要仔细分析游戏对象中哪些功能能够被独立出来成为一个可重用的功能模块组件,而且在实现上应该尽可能下降与其余组件的耦合性。好比在设计一个角色游戏对象时,须要为他设计换装功能。换装功能其实就是对显示子对象进行分组管理,切换显示状态。这个功能相对独立,与其将他实现到角色中,不如独立成一个功能模块组件。角色游戏对象和其余全部须要换装功能的游戏对象均可以经过包含这个模块组件来实现换装功能。 模块功能组件之间还可能有依赖关系,也就是一个功能模块组件可能依赖与另外一个功能模块组件,从而在这个组件层次上造成更多的子层次。 高层的胶水代码脚本 这些脚本用来真正将引擎基础组件和模块功能组件组合到一块儿实现最终游戏对象逻辑。用“胶水代码”来形容这些脚本很是的贴切,就是把全部这些子功能“粘”在一块儿。好比设计一个Player脚本,将全部须要的组件功能组合起来,实现一个玩家的具体游戏逻辑。由于这一层次表明的都是最高层的游戏行为控制对象,是具体的游戏逻辑的“胶水”代码,不会再为更上层提服务,因此自己的可重用性并不高。可是这些对象之间按照类型区分,每每会有一些功能上的重合,因此反而能够继续使用派生关系来实现功能的重用。好比在Character中实现全部的基础功能(这些功能又是经过组合基础组件来实现的),而Player和NPC都从Character派生,来继承全部Character的功能,并继续实现本身特殊的功能。一个功能到底应该用组件实现仍是用派生实现并无很是明确的界限,应该根据须要灵活运用。 在使用Unity的过程当中,若是要实现的是demo级别的小工程,并不须要考虑不少,直接用脚本实现功能就能够了。可是若是要有效地组织复杂的工程,提升代码的重用性,充分理解和合理的利用“基于组件”的对象 模型 设计思想仍是很重要的。