Lua框架
1、C#层可以实现解压、更新、资源管理、网络等模块,这里主要实现Lua层框架。启动流程一般为:检查解压、检查更新、初始化资源、加载Lua虚拟机,Lua框架初始化。Lua层使用MVC架构,入口为Main.lua。
2、这里使用插件middleclass.lua模拟类。
3、用到了一些注解,这些注解与lua语法没有任何关系,主要是为了更好的使用EmmyLua插件进行调试,具体含义可参考EmmyLua注解功能
local middleclass = require "3rd.middleclass"
--定义类--
function _G.class(name, super)
return middleclass(name, super)
end
入口
_G.Main={}
_G.MgrCenter = nil
require "Common/define"
require "Common/functions"
require "Common/protocol"
_G.LuaUtil=nil;
---@type ManagerCenter
local ManagerCenter=require("Common.ManagerCenter")
---@type NetworkManager
local netMgr=nil;
---@type CtrlManager
local ctrlMgr=nil;
---初始化框架
function Main.Initalize()
Main.InitManager();
log("lua init finish");
end
function Main.InitManager()
MgrCenter=ManagerCenter:new();
MgrCenter:Initialize();
LuaUtil=require("Common.LuaUtil")
netMgr=MgrCenter:GetManager(ManagerNames.Network);
ctrlMgr=MgrCenter:GetManager(ManagerNames.Ctrl);
ctrlMgr:GetCtrl(UINames.Setting):InitSetting(); --基本设置加载
end
function Main.OnDispose()
MgrCenter:OnDispose();
MgrCenter=nil;
netMgr=nil;
ctrlMgr=nil;
end
---接收C#层发来的网络数据包
---@param proto string
---@param data table
function Main.OnReceived(proto,data)
log(proto);
netMgr:OnReceived(proto,data);
end
---@param uiCtrlName string
---@param active boolean
---@param onFinish function
function Main.ShowUI(uiCtrlName,active,onFinish)
local ctrl=ctrlMgr:GetCtrl(uiCtrlName);
if ctrl ==nil then
logError("show ctrl was nil")
return;
end
ctrl:ShowUI(active,onFinish);
end
--显示showUICtrlName前先关闭closeuiCtrlName
---@param showUICtrlName string
---@param closeuiCtrlName string
---@param onFinish function
function Main.ShowUIClose(showUICtrlName,closeuiCtrlName,onFinish)
local showCtrl=ctrlMgr:GetCtrl(showUICtrlName);
local closeCtrl=ctrlMgr:GetCtrl(closeuiCtrlName);
if showCtrl ==nil then
logError("show ctrl was nil")
return;
elseif closeCtrl ==nil then
logError("close ctrl was nil");
return;
end
showCtrl:ShowUI(true,function() --加载完毕后再卸载上一个UI
closeCtrl:ShowUI(false,onFinish);
end)
end
Main.Initalize();
Main.ShowUI(UINames.Login,true);
总管理器
---@type BaseManager
local BaseManager=require("Manager.BaseManager")
---@class ManagerCenter
local ManagerCenter = class("ManagerCenter",BaseManager)
function ManagerCenter:Initialize()
BaseManager.Initialize(self);
self.managers = {}
--C# Manager--
self:AddManager(ManagerNames.Resource, self:GetCSharpManager(ManagerNames.Resource))
self:AddManager(ManagerNames.Socket, self:GetCSharpManager("NetworkManager"))
self:AddManager(ManagerNames.Sound, self:GetCSharpManager(ManagerNames.Sound))
self:AddManager(ManagerNames.Shader, self:GetCSharpManager(ManagerNames.Shader))
--Lua Manager--
self:AddManager(ManagerNames.Network, require "Manager.NetworkManager", true)
self:AddManager(ManagerNames.Event, require "Manager.EventManager",true)
self:AddManager(ManagerNames.Ctrl, require "Manager.CtrlManager", true)
self:AddManager(ManagerNames.Module, require "Manager.ModuleManager", true)
self:AddManager(ManagerNames.Handler, require "Manager.HandlerManager", true)
self:AddManager(ManagerNames.Level, require "Manager.LevelManager", true)
self:AddManager(ManagerNames.UI, require "Manager.UIManager", true)
self:AddManager(ManagerNames.Panel, require "Manager.PanelManager", true)
log('ManagerCenter:InitializeOK...')
end
function ManagerCenter:OnDispose()
BaseManager.OnDispose(self);
--C# Manager
self:RemoveManager(ManagerNames.Resource)
self:RemoveManager(ManagerNames.Socket)
self:RemoveManager(ManagerNames.Sound)
self:RemoveManager(ManagerNames.Shader)
--C# Ext Manager--
--Lua Manager--
self:RemoveManager(ManagerNames.Network,true)
self:RemoveManager(ManagerNames.Event,true)
self:RemoveManager(ManagerNames.Ctrl,true)
self:RemoveManager(ManagerNames.Module,true)
self:RemoveManager(ManagerNames.Handler,true)
self:RemoveManager(ManagerNames.Level, true)
self:RemoveManager(ManagerNames.UI,true)
self:RemoveManager(ManagerNames.Panel,true)
log("ManagerCenter OnDispose...")
end
function ManagerCenter:AddManager(name, manager, isLuaMgr)
if name == nil or manager == nil then
logError('ManagerCenter:AddManager Error!! '..name..' was nil.')
return
end
self.managers[name] = manager
isLuaMgr = isLuaMgr or nil
if isLuaMgr == true then
if name == ManagerNames.Table then
manager.Initialize()
else
manager:Initialize()
end
end
end
function ManagerCenter:GetManager(name)
if name==nil then
logError("the name is nil when get managered");
return nil;
end
return self.managers[name]
end
function ManagerCenter:RemoveManager(name,isLuaMgr)
local manager=table.removeKey(self.managers, name)
if manager~=nil then
isLuaMgr = isLuaMgr or nil
if isLuaMgr==true then
manager:OnDispose();
end
manager=nil;
end
end
function ManagerCenter:GetCSharpManager(name)
return LuaHelper.GetManager(name)
end
function ManagerCenter:GetExtManager(name)
return LuaHelper.GetManager(name)
end
return ManagerCenter
UI管理
---@type BaseManager
local BaseManager=require("Manager.BaseManager")
---@class UIManager
local UIManager = class("UIManager",BaseManager)
function UIManager:Initialize() --层级管理
BaseManager.Initialize(self);
self.MainCanvas=findByTag("UICanvas").transform;
self.mLayers = {}
self:InitUILayers()
log('UIManager:InitializeOK...')
end
function UIManager:InitUILayers()
self:CreateLayer('MapAbout', UILayer.MapAbout)
self:CreateLayer('Fixed', UILayer.Fixed)
self:CreateLayer('Common', UILayer.Common)
self:CreateLayer('Movie', UILayer.Movie)
self:CreateLayer('Effect', UILayer.Effect)
self:CreateLayer('Top', UILayer.Top)
end
function UIManager:CreateLayer(name, layerType)
local layerName = name..'_Layer'
local layerObj = GameObject.New(layerName)
layerObj.layer = LayerMask.NameToLayer("UI")
layerObj.transform:SetParent(self.MainCanvas.transform,false)
layerObj.transform.localScale = Vector3.one
local rectType = typeof(RectTransform);
local rect = layerObj:AddComponent(rectType)
rect.anchorMin = Vector2.zero
rect.anchorMax = Vector2.one
rect.sizeDelta = Vector2.zero
rect.anchoredPosition3D = Vector3.zero
rect:SetSiblingIndex(layerType)
self.mLayers[layerType] = layerObj
end
function UIManager:GetLayer(layerType)
return self.mLayers[layerType]
end
return UIManager
---@type BaseManager
local BaseManager=require("Manager.BaseManager")
---@class PanelManager
local PanelManager = class("PanelManager",BaseManager)
UI资源管理
function PanelManager:Initialize()
BaseManager.Initialize(self);
self.mPanels = {}
self.mCtrls = {}
self.resMgr = MgrCenter:GetManager(ManagerNames.Resource)
---@type UIManager
self.uiMgr = MgrCenter:GetManager(ManagerNames.UI)
log('PanelManager:InitializeOK...')
end
function PanelManager:OnDispose()
BaseManager.OnDispose(self);
--删除所有ctrl
for abName,ctrl in pairs(self.mCtrls) do
self:DestroyPanel(abName);
self.mCtrls[abName]=nil;
end
self.mPanels=nil;
self.resMgr=nil;
self.uiMgr=nil;
end
---@param uiCtrlName string
---@return table
function PanelManager:GetPanelCtrl(uiCtrlName)
return self.mCtrls[uiCtrlName]
end
---@param ctrl table
---@param layer table
---@param abName string
---@param onAwake function
function PanelManager:CreatePanel(ctrl, layer, abName, onAwake)
local panelName = abName.."Panel";
local parent = self.uiMgr:GetLayer(layer).transform;
self.mCtrls[abName] = ctrl;
local abPath = "Prefabs/UI/"..abName.."/"..panelName; --兼容AssetDatabase
self.resMgr:LoadAssetAsync(abPath, { panelName }, typeof(GameObject), function(objs)
if objs ~= nil and objs[0] ~= nil then
self:CreatePanelInternal(ctrl, panelName, objs[0], parent, onAwake)
end
end)
log("CreatePanel::>>"..abName)
end
function PanelManager:CreatePanelInternal(ctrl, panelName, prefab, parent, onAwake)
local gameObj = newObject(prefab)
gameObj.name = panelName;
gameObj.layer = LayerMask.NameToLayer("UI");
gameObj.transform:SetParent(parent,false);
local behaviour = gameObj:AddComponent(typeof(LuaBehaviour))
ctrl:InitUI(behaviour)
if onAwake ~= nil then
onAwake(ctrl)
end
self.mPanels[panelName] = gameObj;
end
---销毁UI
---@param abName string
function PanelManager:DestroyPanel(abName)
local ctrl=self:ClosePanel(abName);
local panelName = abName.."Panel";
local removeGameObj = table.removeKey(self.mPanels, panelName)
if removeGameObj ~= nil then
if ctrl~=nil then
ctrl:OnDestroy();
end
destroy(removeGameObj);
end
end
---关闭UI
---@param abName string
---@return any ctrl
function PanelManager:ClosePanel(abName)
local ctrl = self.mCtrls[abName];
if ctrl then
ctrl:ShowUI(false);
end
return ctrl;
end
---关闭所有UI
function PanelManager:CloseAllPanel()
for abName,ctrl in pairs(self.mCtrls) do
ctrl:ShowUI(false);
end
end
return PanelManager
UI控制层父类
---@class UIBaseCtrl
local UIBaseCtrl = class("UIBaseCtrl")
UIBaseCtrl.gameObject = nil
UIBaseCtrl.isUsing=false;
---@param onAwake function InitUI之后调用
function UIBaseCtrl:Awake(onAwake)
logError("not found ui contrller")
end
function UIBaseCtrl:Start() --初始化资源后调用一次
end
---PanelManager生成时调用
---@param behaviour table UI初始化
function UIBaseCtrl:InitUI(behaviour)
self.behaviour = behaviour
self.gameObject = behaviour.gameObject
self.transform=behaviour.transform;
self:InitUIBinder()
end
---显示或隐藏UI面板
---@param isShow boolean
---@param onFinish function
function UIBaseCtrl:ShowUI(isShow,onFinish)
if isShow == nil or isShow == true then
if isnil(self.gameObject) then --未加载Panel
self:Awake(function()
self:Start();
self:OnOpen();
if onFinish then
onFinish();
end
end)
else
self.gameObject:SetActive(true) --已加载过
self:OnOpen();
if onFinish then
onFinish();
end
end
else
if not isnil(self.gameObject) then
self.gameObject:SetActive(false)
self:OnClose();
if onFinish then
onFinish();
end
else
logWarn("the ui gameObject is nil when show ui false")
end
end
end
function UIBaseCtrl:InitUIBinder() --自动加载组件
if isnil(self.gameObject) then
return
end
self.mPrefabVars = {}
local prefabVar = self.gameObject:GetComponent('CPrefabVar')
if not isnil(prefabVar) then
local varData = prefabVar:GetVarArray()
local iter = varData:GetEnumerator()
while iter:MoveNext() do
local varObj = iter.Current
if not isnil(varObj) then
table.insert(self.mPrefabVars, varObj.name)
--print(self.gameObject.name, varObj.name, varObj.type)
if varObj.type == VarType.GameObject then
self[varObj.name] = varObj.objValue
elseif varObj.type == VarType.Transform then
self[varObj.name] = varObj.tranValue
elseif varObj.type == VarType.Image then
self[varObj.name] = varObj.imgValue
elseif varObj.type == VarType.Text then
self[varObj.name] = varObj.txtValue
elseif varObj.type == VarType.Button then
self[varObj.name] = varObj.btnValue
elseif varObj.type == VarType.TMP_InputField then
self[varObj.name] = varObj.inputValue
elseif varObj.type == VarType.Toggle then
self[varObj.name] = varObj.toggleValue
elseif varObj.type == VarType.Slider then
self[varObj.name] = varObj.sliderValue
elseif varObj.type == VarType.CMultiProgressBar then
self[varObj.name] = varObj.multiProgreValue
end
end
end
end
end
function UIBaseCtrl:ClearUIBinder()
if self.mPrefabVars ~= nil then
for _, value in ipairs(self.mPrefabVars) do
self[value] = nil
end
self.mPrefabVars = nil
end
end
function UIBaseCtrl:OnDestroy()
self:ClearUIBinder()
self.behaviour=nil;
self.gameObject=nil;
self.transform=nil;
end
function UIBaseCtrl:OnOpen()
self.isUsing=true;
log(self.gameObject.name.." on open");
end
function UIBaseCtrl:OnClose()
self.isUsing=false;
log(self.gameObject.name.." on close");
end
return UIBaseCtrl
登录页面控制
---@type UIBaseCtrl
local UIBaseCtrl = require "UIController/UIBaseCtrl"
---@class UILoginCtrl
local UILoginCtrl=class("UILoginCtrl",UIBaseCtrl)
---@param onAwake function
function UILoginCtrl:Awake(onAwake)
---@type PanelManager
self.panelMgr=MgrCenter:GetManager(ManagerNames.Panel)
---@type UserModule
self.userModule=MgrCenter:GetManager(ManagerNames.Module):GetModule(ModuleNames.User);
self.panelMgr:CreatePanel(self, UILayer.Fixed, UINames.Login, function()
onAwake();
self:InitUserSetting();
if self["toggle_autoLogin"].isOn==true and self["toggle_rememberPsd"].isOn==true then --自动登录
self:RequestLogin();
end
end)
log("UILoginCtrl.Awake--->>")
end
function UILoginCtrl:OnDestroy()
UIBaseCtrl.OnDestroy(self);
self.panelMgr=nil;
self.userModule=nil;
end
function UILoginCtrl:OnOpen()
UIBaseCtrl.OnOpen(self);
self:InitUserSetting();
self.behaviour:AddClick(self["btn_login"],self,self.RequestLogin)
self.behaviour:AddClick(self["btn_register"],self,function()
Main.ShowUIClose(UINames.Register,UINames.Login)
end)
end
function UILoginCtrl:OnClose()
UIBaseCtrl.OnClose(self);
self.behaviour:RemoveClick(self.btn_login);
self:SavaUserSettings();
end
function UILoginCtrl:RequestLogin()
local txt_account=self["input_user"].text;
local txt_password=self["input_password"].text;
self.userModule:ReqLogin(txt_account,txt_password);
end
function UILoginCtrl:ResponseLogin(respLogin)
if respLogin.resultCode==ResultCode.Success then
Main.ShowUIClose(UINames.Lobby,UINames.Login);
NativeIDList.userId=respLogin.userId;
else
LuaUtil.LoadHint("登录失败!",HintType.Warning);
logWarn("login faild");
end
end
function UILoginCtrl:InitUserSetting()
local account=PlayerPrefs.GetString("account");--存在记录,自动填入账号
if account~=nil then
self["input_user"].text=account;
self["input_password"].text=PlayerPrefs.GetString("password");
end
local autoLogin=PlayerPrefs.GetInt("autoLogin"); --自动登录设置显示
if autoLogin==nil or autoLogin==0 then
self["toggle_autoLogin"].isOn=false;
else
self["toggle_autoLogin"].isOn=true;
end
local remeberPsd=PlayerPrefs.GetInt("remeberPsd"); --记住密码设置显示
if remeberPsd==nil or remeberPsd==0 then
self["toggle_rememberPsd"].isOn=false;
else
self["toggle_rememberPsd"].isOn=true;
end
end
function UILoginCtrl:SavaUserSettings()
PlayerPrefs.SetString("account",self["input_user"].text); --保存账号
if self["toggle_autoLogin"].isOn then
PlayerPrefs.SetInt("autoLogin",1); --自动登录设置
else
PlayerPrefs.SetInt("autoLogin",0);
end
if self["toggle_rememberPsd"].isOn then
PlayerPrefs.SetInt("remeberPsd",1); --保存密码设置
PlayerPrefs.SetString("password",self["input_password"].text);
else
PlayerPrefs.SetInt("remeberPsd",0);
PlayerPrefs.SetString("password","");
end
end
return UILoginCtrl