游戏启示录 关于组件的那些事
组件的概念,只是在我们项目中的称呼。至于其他人怎么称呼这种模式,我则不是很清楚。如果这个名字不对的话,请告诉,我在文档中修复。免得影响其他人的认知。
其实我本无意写这篇文章。因为在项目中引入这个想法的人并不是我,所以我觉得整理其他人的想法,没有任何意义。不过。组件的后期改动我有相当程度的参与,并且Update的更新模式是我进行修改的,并且我已经写了一篇文章描述这个变化的过程,有人表示看不懂。所以,就补上一篇组件的说明。
常规的设计
一般情况下,内容的设计会把一个对象的内容完全封装到一个对象中(哈哈,当然如果是按照面向对象的方式来实现的)。让我们来畅想一下一般情况下一个对象都会有什么东西。位置的移动(基础、移动、减速、加速等)、伤害逻辑(爆炸、碰撞伤害)、对其他内容的影响逻辑(击退、斥力盾啥的)、位置的显示、附属组件的位置调整。一般情况下,这些功能会把公用部分放到合适的位置,比如说移动部分的代码基本上所有的东西都会有,所以这部分内容会添加最基础的组件比如说放置到最基础层面的Objectbase。算了上个插图。
为了实现功能就需要将核实的功能放到合适的位置去,比如说,位置移动的功能。基本上所有的对象都有,那么基本上这个功能就需要放到ObjectBase中。攻击范围的概念基本上只有怪物才会有,那么这部分功能就需要放到怪物层级上。弹幕上的功能则相对比较复杂。普通弹幕很简单,就是普通的东西。但是爆炸的弹幕则需要添加上爆炸的逻辑。追踪的弹幕则需要添加上追踪的逻辑。如果一个弹幕既有爆炸又有追踪。那么使用面向对象的方式来进行设计。这个地方就有两个个选择了,1 父类实现相关的内容,子类选择性的使用。但是因为子类的变动而影响到了父类,这违反了开闭原则对吧。或许,你觉得违反原则,这个并不重要。但是父类频繁的变更,会给子类带来莫名其妙的BUG这个时间长了,你就会有体会了。;2 子类实现自己的东西。如果选择其中第二种方式。那么相同的功能则需要抽离出来,想使用这块功能的单独使用这块功能对吧但是这个违反了面向对象的思想对吧。
组件设计
好,既然面向对象解决这个问题存在困难。那么我们就换个思路,就是刚才我们刚才提到的第二种解决方式。如果所有的功能我们都进行抽离出来,你想用的时候直接挂在上这部分功能。那么,我们不使用继承。也可以实现功能的复用。如果你觉得某一部分功能不够用。完全可以做一个功能类似的组件替换掉原来的组件。封装,将功能形成一个整体;继承,继承也可以看成子类使用父类的组件;多态,功能的替换,这不就是多态吗。其实组件的设计或许跟继承使用了不同的做法。但是基础的封装、继承、多态。我们都可以提供。其实呢,这是另一种继承。哈哈。有点意思。
组件的好处
可以更加完美的实现继承的设计思想,只是这一点其实已经足够吸引人了。其实我们最开始使用这种设计也正是基于这种想法。不过实现完了之后。我发现,其实因为使用了组件,所以我们把一个实体拆分成了很多个小的组件。引用一下昨天的图。
竖着看。这是一个个的实体。但是从侧面看,那跟实体就没什么关系了。每一个组件都是一个单独的个体。在这一帧中,只要所有的组件都调用了Update函数就OK了。那么去调整组件Update更新顺序也就可以实现了。让相同类型的组件靠近更新这种想法也可以。至于组件的更新顺序嘛。不要按照添加的顺序嘛。可以给他们一个排序字段嘛。按照你设定的排序进行就可以。简单的很。代码我就不贴了。因为可能有人看不懂。算了。