通过上一篇的研究,我们已经了解到玩家飞机和怪物是怎么加载出来的(根据配置id读取配置文件,创建实体)。
我们来回忆一下,玩家飞机是怎么创建的:GameEntry.Entity.ShowMyAircraft
现在,为了知道玩家飞机的逻辑是在哪里处理,我跟进了ShowMyAircraft函数,又发现了框架作者的秘密。
1.GameEntry.Entity来源
ShowMyAircraft函数是通过GameEntry.Entity调用的,那我们自然要先知道这里的Entity是什么东西。
如果大家还记得最开始的文章的话,应该对GameEntry不陌生——它是游戏初始化入口。
在GameEntry的InitBuiltinComponents函数里,对Enitity属性进行了赋值:
Entity = UnityGameFramework.Runtime.GameEntry.GetComponent<EntityComponent>();
我们现在知道了,Entity是一个EntityComponet类型的对象。
至于EntityComponent,它是游戏组件,继承了GameFrameworkComponent,它在初始化的时候会调用GameEntry.RegisterComponent(this)注册自身:
必须是先进行了注册的组件,UnityGameFramework.Runtime.GameEntry.GetComponent才能获取到。
不过,现在不理解也没关系,我们只要知道,GameEntry.Entity是什么就好了。
注意,UnityGameFramework.Runtime.GameEntry和StarForce.GameEntry不是同一个对象,只是类名相同而已。
2.调用顺序
ShowMyAircraft函数进行了很多层的封装,不得不吐槽一下,一个demo做得这么复杂,我对框架的推广有点担忧…当然,并不是说这样不好,只是觉得针对demo级别,有点繁琐而已。
首先调用的是EntityExtension里的ShowMyAircraft函数,这里主要是为了从配置文件中加载飞机实体的配置数据(上一篇讲解过了)。
接下来才是调用EntityComponent的ShowEntity函数:
EntityComponent的ShowEntity函数又调用了IEntityManager的ShowEntity函数,留意最后一个参数(ShowEntityInfo),这个参数最终会通过实体对象的生命周期函数传回来。
这里的IEntityManager是什么?我又得给大家解释一下了:
3.IEntityManager
EntityComponent有一个类型为IEntityManager的属性,m_entityManager。
IEntityManager是一个接口,在EntityComponent的Awake里进行了初始化:
m_EntityManager = GameFrameworkEntry.GetModule<IEntityManager>();
具体GetModule是做了什么事情,我们暂时不深入了解,只要知道,它是用于获取游戏框架模块的,这里返回的对象是EntityManager(实体管理器)。
4.EntityManager的ShowEnity函数
于是,我们又回到ShowEntity函数,EntityManager的ShowEntity函数主要做了下面几件事情:
a.根据配置数据,创建实体(从预制体创建)
b.调用实体对象的OnInit、OnShow生命周期函数,这里会把第2步提到的最后一个参数(new ShowEntityInfo(entityLogicType, userData))传递回来
c.还做了一些其他操作,我们暂时忽略
5.DefaultEntityHepler
等等,我们说了这么久,好像还没说到本篇的主题——飞机逻辑处理类
是的,为了知道逻辑处理类是如何绑定到实体上的,我们必须先了解实体是怎么创建的。
现在我们已经知道实体如何创建了,接下来,是最后一步,逻辑处理类是怎么和创建的实体对象关联起来的?
在EntityComponent类的Awake函数中,我们创建了EntityManager对象:
在Start函数里,还绑定了一个EntityHelper对象,这个EntityHelper对象就是实体管理器具体创建实体时要利用的工具类。代码比较多,我只截取其中一部分:
其中m_EntityHelperTypeName是这个Helper类的类型名字:
所以,我们知道了,EntityManage绑定的EntityHelper对象是DefaultEntityHelper。
DefaultEntityHelper是自定义的一个类,继承了EntityHelperBase。
如果以上你都没有看懂,那么,全部忽略吧(旁白:那我到底是为了什么要看你的文章啊喂!)
我们只要知道,最终EntityManager创建实体的时候会调用DefaultEntityHelper的CreateEntity函数即可。
但是,到此为止还是不能找到逻辑处理类在哪里绑定的,我们还要继续研究。(旁白:说好的最后一步呢?!)
6.最终的DefaultEntityHelper的CreateEntity函数
经过重重难关,我们终于找到了逻辑处理类是如何与实体对象绑定的,那就是DefaultEntityHelper的CreateEntity函数:
entityInstance即为实体对象,但这个对象是由框架底层创建,这个不是重点。
重点是最后一行代码,就是这一行代码,把Entity对象添加到了实体对象身上。
你以为这样就结束了吗?不,还有一步。(旁白:大家别拦着我!)
7.最终终极真的是最后一个关键地方——Entity
我们先别激动,虽然我们已经知道了Entity会绑定到创建的实体对象(GameObject)上(旁白:不,我有点懵,我不知道,实体对象是什么?Entity又是什么?!)。
如果大家不是很明白实体对象和Entity的关系,那我举个简单的例子:在Unity的IDE里创建一个空的GameObject对象,然后把脚本Entity拖到这个对象身上。
这就是我所说的实体对象和Entity的关系了。
好,我们再回忆一下,EntityManager的ShowEntity函数做了哪些事情:
a.根据配置数据,创建实体(从预制体创建)
b.调用实体对象的OnInit、OnShow生命周期函数,这里会把第2步提到的最后一个参数(new ShowEntityInfo(entityLogicType, userData))传递回来
各位,对不起,其实之前说的第b步,是我瞎掰的,实际上并不是调用实体对象生命周期函数,而是调用实体对象所绑定的脚本(Entity)的生命周期函数。
EnityManager的ShowEntity函数,会执行下面的代码:
首先是调用了m_EntityHelper(在这里就是DefaultEntityHelper类)的CreateEntity函数,这个函数返回的并不是一个GameObject,而是一个IEntity类型,具体到DefaultEntityHelper的CreateEntity函数,就是返回Entity对象。
所以,准确的说法是,在EntityManage的ShowEntity执行的过程中,会调用Entity的生命周期函数。
好,这个是重点,也是我们这篇文章要做的第一步(旁白:我觉得我第一步要做的就是关掉这篇文章)。
接下来就是要看看Entity的OnInit函数做了什么事情了:
为了更清晰地看逻辑,我删掉了很多代码,留下了三个关键的地方。
Entity的OnInit函数基本上就做一件事情——把逻辑处理类绑定到实体对象身上。
至于逻辑处理类的类型,是在一开始就通过参数传递的(EntityExtension的ShowMyAircraft函数):
8.结束
至于MyAircraft做了什么事情,那就是我们自己的事情了,它就是处理逻辑的,想怎么处理是我们自己定的。
这个Demo里无非就是控制移动、发射子弹,只是做的封装比较多。
时间关系,我就不继续介绍了。
至此,Game Framework的Demo项目StarForce的介绍,到此为止。
希望这系列的文章能稍微让大家了解了Game Framework的基础思路。
可能Demo中还有很多框架的使用细节没有说到,但我个人也是没有实际使用过这个框架,所以不想太过细致地去研究这个Demo,我希望未来在使用的过程中再去了解更多细节。
有机会的话,我会用尽量少的封装写一个Demo,这样学习起来会更加方便。
嗯,有机会的话……(旁白:所以为什么要用省略号,感觉完全没有机会的样子了!)