在业务开发中很常用的思想就是高内聚,低耦合,也即我们希望各个部件之间相互独立,功能容易扩展和修改
如何在某个Actor或Widget触发某个事件后,其他事件收到通信?你可能会想到事件分发器,其优点在于只要绑定事件分发器,向全局播报即可,不必获得通信方的引用。但优点同样是缺点,当我们需要知道收信方或者需要限制收信方时,就不再适用于事件分发器
想象一下你打开一个项目发现全是事件分发器时内心有多崩溃
为什么不使用cast to节点?
Cast to的缺点:当通信对象足够多时,不断地cast to会看的让你想把脑袋塞进马桶里
使用蓝图接口就像传入一个空指针,指向通信对象,可以使用引用查看器来查看有哪些通信对象实现了我们要求的功能。接口内置函数,在发信方使用抽象函数(注意使用message版本,右上角有信封标志),在收信方中具体实现事件(在此还可以扩展一个概念就是中介者模式,可自行了解)
在大项目中,组合一般优于继承
例如有这样一个场景,你做好了一个Actor_A,功能都内置在Actor中,运行良好,非常棒,完美符合你的当前需求。但是天有不测风云,这时又有了新的需求,需要增加一个类似功能的Actor,大部分功能需要保持不变,但是需要修改一些操作,同时还可能需要增加一些功能
这时候你可能会很自然的想到,那么我新加一个Actor_B,让它继承Actor_A,再重写函数不就可以实现这个需求了吗?确实,这套方法确实能够很好的实现目前的需求。但是问题是这是在需求并不复杂的前提下,倘若这种需求继续增加,那么Actor_A就与其他的Actor产生了依赖,如果作为结构基地的Actor_A需要变动,那么整个结构都会需要修改甚至逻辑混乱,这会带来灾难式的维护成本
因此在这种思想下,我们认为组合优于继承(大部分情况)
我们将功能从Actor_A中独立出来成为单独的组件,安装在Actor_A上,之后的Actor也遵循同样的约定,这样Actor之间就保持了独立,可以各自风景独好,非常好,实现了我们需要的效果。甚至我们还可以将其应用在其他项目上,完成代码复用,大大提升工作效率
当然,在需求并不复杂的情况下(例如我们只需要增加一个额外的需求),使用继承也不失为好的方法
纵观上述思想,我们发现产生问题的原因在于我们在项目初期并不知道项目的全貌,因此无法对结构形成一个整体的认知,我们误认为我们作为基底的情况是通用,但是随着需求的不断增加,“特例”开始越来越多,出现了越来越多超出框架的东西需要维护,这时候我们就需要考虑解耦,来优化我们的结构。因此不要过早的优化你的代码,在项目初期快速实现需求才是第一位
顺带一提,事件分发器同样会造成污染,因为我们只需要接收到通知,并不需要知道所有发信方的引用,因此可以结合事件分发器和蓝图接口,(也可以建立一个事件分发器管理者),只需要知道一个引用即可
一些小的点:
Ⅰ,避免在Event Tick事件中使用Cast To节点,可以在Event Begin Play事件中进行Cast To,之后保存起来
Ⅱ,接口函数和GameState一样,可以全局访问,但是接口函数只能在实现之后使用,否则不进行任何操作
Ⅲ,养成使用Is Valid节点的习惯,优于Begin Play框架,为防止出现某些Actor尚未初始化的问题,可以使用