菜單欄相關: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異步返回后刪除界面
? ? ? ? //UILobbyComponentSystempublic static async ETTask EnterMap(this UILobbyComponent self){await EnterMapHelper.EnterMapAsync(self.ClientScene());await UIHelper.Remove(self.ClientScene(), UIType.UILobby);}
之后EnterMapHelper會向服務器發起進入Map的請求
? ? ? ? //EnterMapHelperpublic 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);} ? ? ??}
?