接上一篇文章的內容繼續:
在開始編碼之前,首先可能需要大家掌握幾個知識點
基於掌握以上基礎的前提,我們整理一下邏輯~關於Base的邏輯的生命周期,我思考了好久結合當前正在做的項目中的設計,得到了類似下圖的決定:
開始代碼的編寫:
-- @FileName UIBase -- @Create by mx -- @Create time 2019/05/26 22:08:38 -- @FileInfo 所有UI的基類
--全局申明UIBase基類 UIBase = Class("UIBase") --全局申明 UI資源載入方式 UILoadType = { Sync, --同步 ASync, --非同步 }
function UIBase:Ctor( ... ) --該UI是否已經初始化完成 self.m_isInited = false --實例化的Prefab self.m_uiObj = nil --實例化的TransForm信息 self.m_uiTrans = nil --是否處於激活狀態 self.m_isActive = false --UIName self.m_uiName = nil --UIPath self.m_uiFullPath = nil --是否在載入中 self.m_isLoading = false --資源載入方式 默認同步 self.m_resLoadType = UILoadType.Sync --存儲UI的數據信息 self.m_uiPanel = nil end
--資源載入 function UIBase:Load( callBack ) if self.m_isLoading then return end if self.m_uiObj then LogError("Already Loaded UIName :"..self.m_uiName) return end if self.m_uiFullPath == nil then self:SetUIFullPath() end local l_uiObj = nil if self.m_resLoadType == UILoadType.Sync then l_uiObj = MObjectManager:InstantiateGameObeject(self.m_uiFullPath) self:OnLoadFinish(l_uiObj,callBack) else l_uiObj = MObjectManager:InstantiateGameObejectAsync(self.m_uiFullPath,function (resPath,mResObjItem,parms) self:OnLoadFinish(l_uiObj,callBack) end,LoadResPriority.RES_LOAD_LEVEL_HEIGHT) end end
--資源載入完成 初始化信息的設置 function UIBase:OnLoadFinish(obj,callBack) if obj == nil then LogError("資源載入失敗~ Name:"..self.m_uiName) self.m_uiObj = nil return end obj.name = self.m_uiName self.m_uiObj = obj self.m_uiTrans = obj.transform self:Init() if callBack then callBack(self) end end
--資源釋放 function UIBase:UnLoad( ... ) --Todo 非同步載入對正在載入的非同步邏輯做取消判定 --資源載入缺少這個介面 需要補上 if self.m_isLoading then
end
if self.m_uiObj then MObjectManager:ReleaseObject(self.m_uiObj) self.m_uiObj = null self.m_uiTrans = null end end
--邏輯初始化 在資源載入完成後調用 function UIBase:Init() self.m_isInited = true end
--資源卸載後調用 function UIBase:Uninit() self:UnLoad() self.m_isInited = false self.m_uiPanel = false end
--打開UI function UIBase:Active() end
--關閉UI function UIBase:Deactive() end
--UI顯示時 function UIBase:OnActive() end
--UI關閉前 function UIBase:OnDeactive() end
--事件綁定 function UIBase:BindEvents() end
--事件解綁 function UIBase:UnBindEvents() end
--Update事件 function UIBase:Update() end
--觸摸事件 function UIBase:UpdateInPut(touchItem) end
--斷線重連 function UIBase:OnReconnected() end
--遊戲註銷 function UIBase:OnLogout() end
function UIBase:IsActive( ... ) return self.isActive end
function UIBase:IsInited( ... ) return self.IsInited end
--設置UI的全路徑 function UIBase:SetUIFullPath( ... ) if self.m_uiFullPath ~= nil then return end if self.m_uiName == nil then LogError("UIName is nil ~ Please Check it") end self.m_uiFullPath = MPathUtils.UI_MAINPATH.."/"..self.m_uiName..MPathUtils.UI_PREFAB_SUFFIX end
--UIBase Test --UIBase.m_uiName = "LoginPanel" --UIBase.Load(UIBase) return UIBase
以上為Base的基礎設計,後續的開發過程中在持續優化~
接下來就是幾個繼承UIBase的基礎類
UIBaseWind基本窗體類
UIBaseToggleWind依附於基本窗體的類
UIBaseSlot復用Object類
這裡我們在來理一下思路:
屬性
當前UI的顯示層級 m_uiLayer
當前UI的顯示類型 m_uiType
當前UI是否是Toggle的父類 如果是那麼保存繼承UIBaseToggle的UIToggleWind的引用 m_uiToggleWindTb = {}
保存當前UI下創建的所有繼承自UIBaseSlot的復用性組件 m_uIbaseSlotTb = {}
介面
支持創建UIbaseSlot
支持創建UIBaseToggle
當前ToggleWind的父節點
當前ToggleWind的名字
當前Slot的父節點
當前Slot的Id
考慮到Slot有可能用於ScrollView需要頻繁創建 需要一個當前Slot的SlotPool池管理
統一以上生命周期 做好釋放邏輯 以免內存泄露
以上就是幾個基礎類的設計了~ 代碼不貼了。接下來就是UIManager類似C#的設計Manager需要核心做以下的事情
1 管理UI的顯示 隱藏 銷毀
2 管理UI堆棧
3 統一一些生命周期的入口,比如說Update,OnReconnect,OnLogout等
然後就是提供一些常用的介面,比如獲取某一個UI的狀態啊,獲取某一個UI啊,堆棧清空啊,彈出一個棧頂的UI等等~
還有一點之前沒有講到,就是Lua邏輯基礎代碼的自動生成,其實定義好基類之後,業務層的開發會有一個統一的結構,從文本角度看基礎類無非就是UI的名字不一樣,那麼這個時候就需要做一個UI代碼的生成工具了。
其實這裡還有一點小東西當前項目做得很好,就是寫了一個腳本管理UI的所有類型,然後給每一個我們需要操作的節點掛上這個腳本,生成代碼的時候我們就可以直接生成這個掛腳本的節點的位置信息,不需要代碼裡面去做Transform.Find操作。
代碼生成是非常重要的一環,可以大大縮短開發時間,真的非常有必要。
UI框架這塊基本介紹完了。我們當前的遊戲框架中引入了Lua的熱重載,就是不需要重啟遊戲,直接就可以更新Lua虛擬機中的代碼,大大加快了開發的速度。後面我會把這個東西也集成到我們的遊戲框架中,給大家做一個簡單的講解。
共勉。