【ET8】2.ET8入门-ET框架解析
菜单栏相关:ENABLE_DLL选项
ET->ChangeDefine->ADD_ENABLE_DLL/REMOVE_ENABLE_DLL
一般在开发阶段使用Editor时需要关闭ENABLE_DLL选项。该选项关闭时,修改脚本之后,会直接重新编译所有的代码,Editor在运行时会直接使用最新的程序集。如果ENABLE_DLL选项是开启的,框架启动后会加载之前生成的程序集文件(这个文件需要在ET->BuildTool界面生成),导致每次需要应用修改,都要重新生成程序集文件。
框架解析
框架入口解析
启动流程如下
入口文件为Init,之后调用CodeLoader对代码进行加载
如果不是EnableDll模式则直接加载程序集。否则通过AB加载文件,之后调用LoadHotfix函数
LoadHotfix会加载程序集,并且调用EventSystem,根据特性注册对应事件的监听。
之后调用ET.Entry的Start方法。
ET.Entry.Start 进行初始化之后,调用FiberManager.Instance.Create调用FiberInit事件,推送对应的EntryEvent事件
推送EntryEvent3,EntryEvent3_InitClient接收后推送AppStartInitFinish
AppStartInitFinish_CreateLoginUI接收该事件后,创建UI场景
UI系统
UI界面的生成流程
ET是通过异步方式创建UI,如下方例子,调用UIHelper.Create方法,指定创建UI的场景,UI类型和对应的层级
? ? ? ? protected override async ETTask Run(Scene scene, EventType.AppStartInitFinish args)
? ? ? ? {
? ? ? ? ? ? await UIHelper.Create(scene, UIType.UILogin, UILayer.Mid);
? ? ? ? }
调用scene挂载的UIComponent组件,处理Create事件
? ? ? ? public static async ETTask<UI> Create(Scene scene, string uiType, UILayer uiLayer)
? ? ? ? {
? ? ? ? ? ? return await scene.GetComponent<UIComponent>().Create(uiType, uiLayer);
? ? ? ? }
之后会标记有对应UIEvent特性的类,处理该事件,开始加载资源并生成对应的GameObject
[UIEvent(UIType.UILogin)]
public class UILoginEvent: AUIEvent
{
public override async ETTask<UI> OnCreate(UIComponent uiComponent, UILayer uiLayer)
{
await uiComponent.DomainScene().GetComponent<ResourcesLoaderComponent>().LoadAsync(UIType.UILogin.StringToAB());
GameObject bundleGameObject = (GameObject) ResourcesComponent.Instance.GetAsset(UIType.UILogin.StringToAB(), UIType.UILogin);
GameObject gameObject = UnityEngine.Object.Instantiate(bundleGameObject, UIEventComponent.Instance.GetLayer((int)uiLayer));
UI ui = uiComponent.AddChild<UI, string, GameObject>(UIType.UILogin, gameObject);
ui.AddComponent<UILoginComponent>();
return ui;
}
public override void OnRemove(UIComponent uiComponent)
{
ResourcesComponent.Instance.UnloadBundle(UIType.UILogin.StringToAB());
}
}
UI组件解析
以UILogin为例子,对应的Prefab实际上只挂载了ReferenceCollector,ReferenceCollector负责将结点进行绑定
生成该GameObject之后,调用AddComponent
[UIEvent(UIType.UILogin)]
public class UILoginEvent: AUIEvent
{
public override async ETTask<UI> OnCreate(UIComponent uiComponent, UILayer uiLayer)
{
string assetsName = $"Assets/Bundles/UI/Demo/{UIType.UILogin}.prefab";
GameObject bundleGameObject = await uiComponent.Scene().GetComponent<ResourcesLoaderComponent>().LoadAssetAsync<GameObject>(assetsName);
GameObject gameObject = UnityEngine.Object.Instantiate(bundleGameObject, uiComponent.UIGlobalComponent.GetLayer((int)uiLayer));
UI ui = uiComponent.AddChild<UI, string, GameObject>(UIType.UILogin, gameObject);
ui.AddComponent<UILoginComponent>();
return ui;
}
public override void OnRemove(UIComponent uiComponent)
{
}
}
其中UILoginComponent负责显示对应成员
[ComponentOf(typeof(UI))]
public class UILoginComponent: Entity, IAwake
{
? ? public GameObject account;
? ? public GameObject password;
? ? public GameObject loginBtn;
}
AddComponent之后,会调用对应的System,这里UILoginComponentSystem就是对应的System,在Awake阶段通过ReferenceCollector对UILoginComponent进行了绑定,以及实现了对应的UI逻辑
[ObjectSystem]
public class UILoginComponentAwakeSystem : AwakeSystem<UILoginComponent>
{
? ? protected override void Awake(UILoginComponent self)
? ? {
? ? ? ? ReferenceCollector rc = self.GetParent<UI>().GameObject.GetComponent<ReferenceCollector>();
? ? ? ? self.loginBtn = rc.Get<GameObject>("LoginBtn");
? ? ? ? self.loginBtn.GetComponent<Button>().onClick.AddListener(()=> { self.OnLogin(); });
? ? ? ? self.account = rc.Get<GameObject>("Account");
? ? ? ? self.password = rc.Get<GameObject>("Password");
? ? ?}
}
场景切换
关于ET的场景切换相关逻辑可以查看
UILobbyComponentSystem处理进入Map的操作,先是调用EnterMap异步函数,等待EnterMapHelper异步返回后删除界面
? ? ? ? //UILobbyComponentSystem
? ? ? ? public static async ETTask EnterMap(this UILobbyComponent self)
? ? ? ? {
? ? ? ? ? ? await EnterMapHelper.EnterMapAsync(self.ClientScene());
? ? ? ? ? ? await UIHelper.Remove(self.ClientScene(), UIType.UILobby);
? ? ? ? }
之后EnterMapHelper会向服务器发起进入Map的请求
? ? ? ? //EnterMapHelper
? ? ? ? public static async ETTask EnterMapAsync(Scene clientScene)
? ? ? ? {
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? G2C_EnterMap g2CEnterMap = await clientScene.GetComponent<SessionComponent>().Session.Call(new C2G_EnterMap()) as G2C_EnterMap;
? ? ? ? ? ? ? ? clientScene.GetComponent<PlayerComponent>().MyId = g2CEnterMap.MyId;
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? // 等待场景切换完成
? ? ? ? ? ? ? ? await clientScene.GetComponent<ObjectWait>().Wait<Wait_SceneChangeFinish>();
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? EventSystem.Instance.Publish(clientScene, new EventType.EnterMapFinish());
? ? ? ? ? ? }
? ? ? ? ? ? catch (Exception e)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Log.Error(e);
? ? ? ? ? ? } ? ? ??
? ? ? ? }
?
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!