(框架文件夹ToLuaGameFramework,拖入到你的工程里即可。但是熟悉本框架之前建议整个Demo工程全部下载,业务层开发都在LuaDev里)
基于toLua扩展的Unity热跟新实用框架,继承MonoBehaviour常用的生命周期,方便管理组件逻辑。
使用UI栈自动管理层级,支持消息机制唤起UI,高度解耦,代码简单高效。
集成DOTween并做了一些少量扩展。
LuaDev目录下常用功能界面已形成,接着往下开发即可,开箱即用,方便快捷。
更多功能不断完善中......
本框架推荐C#只用来简单的加载Lua资源和启动Lua框架,游戏逻辑全部在Lua里开发。
C#的开始:
修改LuaConfig.cs中的LuaDevPath定义您的开发目录。
开发目录内创建Lua目录和Prefabs目录,建议两个文件夹名称不要修改。UI图集、模型、音效等素材可放在开发目录外。以保证开发目录干净整洁
注册好各种事件,然后直接调用 LuaMain.Instance.StartFramework() 即可
MessageCenter.Add(MsgEnum.ABLoadingBegin, (BaseMsg msg) =>
{
text.text = "正在更新资源";
slider.value = 0;
});
MessageCenter.Add(MsgEnum.ABLoadingError, (BaseMsg msg) =>
{
text.text = msg.args[0].ToString();
});
MessageCenter.Add(MsgEnum.ABLoadingProgress, (BaseMsg msg) =>
{
float progress = float.Parse(msg.args[0].ToString());
text.text = Mathf.FloorToInt(progress * 100) + "%";
slider.value = progress;
});
MessageCenter.Add(MsgEnum.ABLoadingFinish, (BaseMsg msg) =>
{
Debug.Log("更新完成");
});
MessageCenter.Add(MsgEnum.RunLuaMain, (BaseMsg msg) =>
{
Debug.Log("开始执行Lua的Main脚本");
Destroy(text.gameObject);
Destroy(slider.gameObject);
MessageCenter.Remove(MsgEnum.ABLoadingBegin);
MessageCenter.Remove(MsgEnum.ABLoadingError);
MessageCenter.Remove(MsgEnum.ABLoadingProgress);
MessageCenter.Remove(MsgEnum.ABLoadingFinish);
MessageCenter.Remove(MsgEnum.RunLuaMain);
});
//启动框架
LuaMain.Instance.StartFramework();
//执行该命令,会自动检测下载 LuaConfig.cs里的ExportRes_For_Startup字典里的资源,完成后执行Main.lua
//而LuaConfig.cs里的ExportRes_For_Delay字典里的资源不会下载,开发者可在Lua代码内部使用前下载,方法见下文第11点。
Prefabs内放好预设体。建议Lua目录内创建结构一样的子目录结构,目录内创建对应的UI控制Lua脚本。如果是UI,继承BaseUI,否则继承LuaBahaviour。方式如下:
Login.lua继承BaseUI:
local BaseUI = require "Core.BaseUI"
local Login = Class("Login", BaseUI)
return Login
Ball.lua继承LuaBehaviour:
local LuaBehaviour = require "Core.LuaBehaviour"
local Ball = Class("Ball", LuaBehaviour)
return Ball
local BaseUI = require "Core.BaseUI"
local Login = Class("Login", BaseUI)
function Login:PrefabPath()
return "Prefabs/Battle/Actors/Ball"
end
return Login
function DailyReward_Content_1:IsUIStack()
return false
end
local BaseUI = require "Core.BaseUI"
local Login = Class("Login", BaseUI)
function Login:PrefabPath()
"Prefabs/Battle/Actors/Ball"
end
function Login:Awake()
self.super.Awake(self)
--按钮的绑定
self.btnClose = self.transform:Find("BtnClose")
self.btnClose:OnClick(function()
Destroy(self.gameObect)
end)
end
function Login:OnEnable()
self.super.OnEnable(self)
end
function Login:Start()
--DOTween使用(本框架扩展了DOTween的整界面同时透明动画的方法,支持重载以忽略某些参数,详见DOTweenExtend.cs)
--self.transform:DOAlpha(初始透明度,目标透明度,动画时长,缓动方式,是否包含所有子节点)
self.transform:DOAlpha(0, 1, 1.5, Ease.OutExpo, true):OnComplete(function()
Log("透明淡入完成")
end)
end
function Login:Update()
--这里每帧执行一次
end
function Login:FixedUpdate()
--这里每帧执行一次
end
function Login:LateUpdate()
--这里每帧执行一次
end
function Login:OnDisable()
self.super.onDisable(self)
end
function Login:OnDestroy()
self.super.onDestroy(self)
end
return Login
local coinsTrans = self.transform:Find("CoinsBar")
--绑定
local luaCom = AddLuaComponent(coinsTrans, require("Common.CoinsBarCtrl"))
--移除(第二参数支持传入实例化后的类也支持传入未实例化的Require对象)
RemoveLuaComponent(coinsTrans, luaCom)
或
RemoveLuaComponent(coinsTrans, require("Common.CoinsBarCtrl"))
local PreloadUI = require "Modules.ResPreload.ResPreload"
PreloadUI:New()
或
local parent = GameObject.Find("MainCanvas").transform
PreloadUI:New(parent)
分模块开发,在各自模块里管理对应UI集合,通过发送命令展示:(高度解耦,数据隔离,大项目推荐)
第1步:创建模块类(如Demo中的LoginMgr),并在Ctor()添加好该模块各个UI类
第2步:Enum文件里创建一个模块ID,并注册到Modules
第3步:发送一个命令,即可展示UI
注:模块管理器与UI之间的相互访问,可参考Login.lua和LoginMgr.lua
模块类基础内容:
local BaseMgr = require "Core.BaseMgr"
local LobbyMainMgr = Class("LobbyMainMgr", BaseMgr)
function LobbyMainMgr:Ctor()
self.super.Ctor(self)
self:AddUI("LobbyMain", require "Modules.Lobby.LobbyMain.LobbyMain")
end
return LobbyMainMgr
触发打开
CommandManager.Execute(CommandID.OpenUI, "LobbyMainMgr", "LobbyMain",父级(可选))
--发送命令适合跨模块使用,不想用命令也可以调用方法实现打开UI(适合模块内使用,或需要得到UI对象进行进一步赋值时使用)
local alert = Modules.Common:OpenUI("Alert")
alert:setContent("Hello Lua")
local go = ResManager.SpawnPrefab(预设体在Resources目录下的路径,父级(可选))
for i = 1,10 do
local btn = self.transform:Find("Btn_"..i)
btn:OnClick(function()
--这里完全可以直接引用循环中的“i”值做计算
Log(i)
end)
end
function MyClass:Awake()
for i = 1,10 do
local btn = self.transform:Find("Btn_"..i)
btn:OnClick(self.OnBtnClick, self, i)
end
end
function MyClass:OnBtnClick(index)
Log(index)
end
local PreloadUI = require "Modules.ResPreload.ResPreload"
PreloadUI:New(parent)
CommandManager.execute(CommandID.OpenUI, "模块类名", 模块管理类里的UI索引(可选),父级(可选))
function BaseMgr:DefaultParent()
--TODO:请根据项目实际情况修改
local parent = GameObject.Find("MainCanvas").transform
return parent
end
local btnDailyReward = self.transform:Find("BtnDailyReward")
btnDailyReward:OnClick(
function()
if ResManager.instance:IsABLoaded("Prefabs/Activities/DailyReward") and
ResManager.instance:IsABLoaded("Prefabs/Activities/DailyTask") then
Modules.DailyReward:OpenUI("DailyReward")
else
local abs = {"Prefabs/Activities/DailyReward", "Prefabs/Activities/DailyTask"}
ResManager.instance:UpdateABsByNames(abs, function(name, progress, allCompleted)
Log(progress, name .. "progress")
if allCompleted then
Modules.DailyReward:OpenUI("DailyReward")
end
end)
end
end
)
继承BaseUI后,UI自动受UI栈管理。即每生成一个UI界面都会自动压入UI栈,Destroy后自动出栈,默认情况下除栈顶之外的其他UI自动隐藏,只需发送命令打开新UI即可,前一个UI无需多加代码关闭。栈顶的UI被Destroy出栈后,新的栈顶UI会自动显示,无需多写代码激活。如果不希望关闭UI后自动显示前一个UI,可在打开新UI命令前,先将当前UI进行Destroy即可
当某些UI因特殊情况需要自己添加Canvas并且指定独立的Camera的情况,本UI栈会将其生成在场景根目录,指定的父级无效,并且会与无Canvas的普通UI合理排序,无需自行处理(例如:工程内的预设体BattleUI)
所以:当打开一个UI后,想跳回原来的UI,有两种方法:方法1:直接Destroy自己,无需再发送命令打开前UI。方法2:直接用命令或者模块方法打开前UI,无需多写代码关掉自己
继承BaseUI后,通过发送命令打开新UI时,UI将被当成一个单例使用。系统先从栈内查找,如果找到则直接移到栈顶显示,不会重复创建新UI
function FirstUI:KeepActive()
return true
end
function FirstUI:IsFloat()
return true
end
--有特效添加的先调用该方法再刷新
UIManager.RefreshSortObjects(self.transform)
--否则只调用该方法即可
UIManager:RefreshStack()
第1步:导出前配置好Config.cs里的4个目录:OutputPath,RemoteUrl,ExportLuaPaths,ExportResPath
第2步:菜单执行ToLuaUIFramework->Build XXX AssetBundle
第3步:Config.cs里将UseAssetBundle设置为true, 将开发Resources目录改名以免资源被打入母包中,开始出包
如需预加载本地AssetBundle资源,可仿照Game目录下的的ResPreload.lua执行预加载,预加载的目录可自行配进paths数组里
local paths = {
"Prefabs/LobbyUI"
}
ResManager:PreloadLocalAssetBundles(
paths,
function(progress)
self.slider.value = progress
if progress == 1 then
--预加载完成
end
end
)
function LuaBehaviour:DestroyABAfterSpawn()
return true
end
function LuaBehaviour:DestroyABAfterAllSpawnDestroy()
return true
end
ResManager:UnloadAllAssetBundles(false)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。