Unity3D热更新之LuaFramework篇[03]--prefab加载和Button事件
在上一篇文章 Unity3D热更新之LuaFramework篇[02]--用Lua创建自己的面板 中,我介绍了LuaFramework加载面板的方法,但这个方法并不适用于其它Prefab资源,在这套框架中非面板型资源的加载方法另有套路。
1、如何加载非面板预制体
1、创建一个预制体
打开上次使用的工程,打开Main场景,创建一个名为ImgOrc的Image,图片就选例子用的兽人头像。在Assets/LuaFramework/CustomPrj目录下新建一个Prefabs目录,然后拖动ImgOrc到该目录下做成预制体,如图1-1
图1-1
2、将预制体打成AssetBundle包
打开Assets/ LuaFramework/Editor/Packager.cs文件(用VS或Mono Develop编辑器打开),找到HandleExampleBundle方法,添加对ImgOrc预制体的打包代码,如图1-2所示
图1-2
/// <summary>
/// 处理框架实例包
/// </summary>
static void HandleExampleBundle() {
string resPath = AppDataPath + "/" + AppConst.AssetDir + "/";
if (!Directory.Exists(resPath)) Directory.CreateDirectory(resPath); AddBuildMap("prompt" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Prompt");
AddBuildMap("message" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Message"); //打包我们新加的FirstPanel预制体
AddBuildMap("first" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/CustomPrj/FirstTest");
//打包我们新加的ImgOrc预制体
AddBuildMap("prefabs" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/CustomPrj/Prefabs"); AddBuildMap("prompt_asset" + AppConst.ExtName, "*.png", "Assets/LuaFramework/Examples/Textures/Prompt");
AddBuildMap("shared_asset" + AppConst.ExtName, "*.png", "Assets/LuaFramework/Examples/Textures/Shared");
}打包代码
这里要对AddBuildMap方法的参数加以说明
- 第一个参数是包名,即打包后在StreamingAssets目录中显示的包的名称,AppConst.ExtName是扩展名,框架默认为".unity3d",可以自行修改;
- 第三个参数是要打包的资源的目录,暂且称为源目录;
- 第二个参数是打包模式,以字符串形式过滤出要打包的文件名,比如这里*.prefab就表示源目录下的所有prefab文件。
之所以将ImgOrc预制体打包的包名定义为prefabs而不是ImgOrc,是因为这个打包是针对整个目录的而不是单个资源。为了说明这一情况,我会在CustomPrj/Prefabs目录下再加一个预制体ButtonPrefab。见图1-3
见图1-3
这次不修改打包文件。
找到LuaFramework菜单,点击Build Windows Resources菜单项,开始自动打包操作,中间无需干预。
打包结束,查看StreamingAssets目录,能看到与刚刚给定的包名相应的文件:prefabs.unity3d,见图1-4
图1-4
图中红框标识的还有一个名为prefabs的文件,这是没有显示后缀(其实有后缀,在unity中未显示),这个是prefabs.unity3d包的清单文件,在windows下打开看以看到其全名为prefabs.unity.manifest。
用Notepad++打开这个清单文件,可以看到在37、38行列出一这个AB包包含的两个资源:ButtonPrefab.prefab和ImgOrc.Prefab。见图1-5:
图1-5
此框架的资源打包方式就是这样的,所有资源都需要在代码中添加相应包名、过滤模式、目录。游戏开发前期和资源变动较大时,会频繁改动这个脚本的内容,用起来并不是很方便。
3、在代码中加载预制体
资源包有了,现在需要在代码中加载这个包。
打开FirstCtrl.lua文件,在FirstCtrl.OnCreate方法中添加读取资源包的方法,见代码:
--启动事件--
function FirstCtrl.OnCreate(obj)
gameObject = obj;
message = gameObject:GetComponent('LuaBehaviour'); --加载prefabs.unity3d资源包
resMgr:LoadPrefab("prefabs.unity3d", {"ImgOrc"}, function (prefabs) end);
endresMgr是框架封装好的资源管理工具,LoadPrefab函数用来读取资源包。第一个参数是包名,第二个参数是包里的资源名(Prefab名称),第三个参数是包读取成功的回调,参数prefabs为读出来的资源。
..
继续完成代码,进行实例操作等操作,代码如下:
--启动事件--
function FirstCtrl.OnCreate(obj)
gameObject = obj;
transform = obj.transform; message = gameObject:GetComponent('LuaBehaviour'); 8 --加载prefabs.unity3d资源包
9 resMgr:LoadPrefab("prefabs.unity3d", {"ImgOrc"}, function (prefabs)
10 log(prefabs.Length); --输出 1
11 log(prefabs[0].name) --输出 ImgOrc
12
13 --加载兽人头像到FirstPanel下
14 local go = newObject(prefabs[0]); --实例化
15 go.transform:SetParent(transform); --设置FirstPanel为父对象
16 go.transform.localPosition = Vector3.zero; --设置初始位置
17 go.transform.localScale = Vector3.one; --设置缩放
18
19 end);
end说明点:
- 回调函数的参数prefabs是一个userdata类型的数据(userdata一般是C#中的部分引用类型在Lua中的表示),这里猜测是一个数组,因为通过.Length可以取到长度,能过[0]能取到第一个元素。
- newObject是框架封装好的实例化函数,猜测本质就是c#中的GameObject.Instantiate方法。
- 设置父对象、位置、缩放这几步操作和c#中的操作差不多。因为本身调用的就是c#中的方法,即transform的方法。
- FirstCtrl.lua文件中的gameObject,transform代表的就是FirstPanel面板及面板上transform组件,是在面板创建时(OnCreate方法前两行)注入进来的。
代码完成后,运行Unity,能看到ImgOrc已经加载到了FirstPanel对象下,见图1-6
图1-6
非Panel的预制体加载流程就是这样,加载方法是参照例子的PromptCtrl.lua写的。
resMgr中还有放多其它加载资源的方法,留待以后再探究。
2、怎么给按钮添加监听
在用c#写代码的时候,给Button添加监听有两种方法,一是将脚本绑在Button组件上,通过面板选择脚本中的方法来添加做;二是在代码中通过Button.onClick.AddListener方法添加。
那么在Lua应该怎么做呢?
还是以FirstPanel为例,给FirstPanel右上角添加一个关闭按钮,应用预制体然后重新打包,
然后:
1、在FirstPanel.lua文件中引用按钮
打开FirstPanel.lua文件,在InitPanel函数中添加查找按钮的代码:
--初始化面板--
function FirstPanel.InitPanel()
--查找关闭按钮
this.btnClose = transform:FindChild("CloseButton").gameObject;
end2、在FirstCtrl.lua文件中添加监听
打开FirstCtrl.lua文件,找到OnCreate方法,然后通过FirstPanel所挂的LuaBehaviour脚本来添加监听事件,见图2-1
图2-1
AddClick方法有两个参数,第一个是按钮本身(上一步才引用过的),第二个是点击后的回调函数。
AddClick的具体实现可以可以在LuaBehaviour.cs中找到。
运行Unity,点击关闭按钮,能看到打印了期望中的日志,见图2-2
图2-2
给按钮添加监听就是这么简单,不过里边还藏着一些坑,以后的文章再细讲。
总结一点,用Lua做逻辑的话,所有UI元素的使用都需要先在相应的XxxPanel中引用 ,然后到XxxCtrl中添加事件,对于结构复杂的UI,做起来非常耗时间。
文中多次操作了FirstCtrl.lua和FirstPanel.lua文件,为了方便参阅,现将两个脚本完整的贴出来:
local transform;
local gameObject; FirstPanel = {};
local this = FirstPanel; --启动事件--
function FirstPanel.Awake(obj)
gameObject = obj;
transform = obj.transform; this.InitPanel();
logWarn("Awake lua--->>"..gameObject.name);
end --初始化面板--
function FirstPanel.InitPanel()
--查找关闭按钮
this.btnClose = transform:FindChild("CloseButton").gameObject;
end --单击事件--
function FirstPanel.OnDestroy()
logWarn("OnDestroy---->>>");
endFirstPanel
FirstCtrl = {};
local this = FirstCtrl; local behaviour;
local transform;
local gameObject; --构建函数--
function FirstCtrl.New()
logWarn("FirstCtrl.New--->>");
return this;
end function FirstCtrl.Awake()
logWarn("FirstCtrl.Awake--->>");
panelMgr:CreatePanel('First', this.OnCreate);
end --启动事件--
function FirstCtrl.OnCreate(obj)
gameObject = obj;
transform = obj.transform; behaviour = gameObject:GetComponent('LuaBehaviour');
behaviour:AddClick(FirstPanel.btnClose, function ()
log("你点击了关闭");
end); --加载prefabs.unity3d资源包
resMgr:LoadPrefab("prefabs.unity3d", {"ImgOrc"}, function (prefabs)
log(prefabs.Length); --输出 1
log(prefabs[].name) --输出 ImgOrc --加载兽人头像到FirstPanel下
local go = newObject(prefabs[]); --实例化
go.transform:SetParent(transform); --设置FirstPanel为父对象
go.transform.localPosition = Vector3.zero; --设置初始位置
go.transform.localScale = Vector3.one; --设置缩放 end);
end --单击事件--
function FirstCtrl.OnClick(go)
destroy(gameObject);
end --关闭事件--
function FirstCtrl.Close()
panelMgr:ClosePanel(CtrlNames.Message);
endFirstCtrl
本次的介绍就到这里。
Unity3D热更新之LuaFramework篇[03]--prefab加载和Button事件的更多相关文章
- Unity3D热更新之LuaFramework篇[10]--总结篇
背景 19年年初的时候,进到一家新单位,公司正准备将现有的游戏做成支持热更的版本.于是寻找热更方案的任务就落在了我头上. 经过搜索了解,能做Unity热更的方案是有好几种,但是要么不够成熟,要么不支持 ...
- Unity3D热更新之LuaFramework篇[02]--用Lua创建自己的面板
在上篇文章 Unity3D热更新之LuaFramework篇[01]--从零开始 中,我们了解了怎么获得一个可用的LuaFramework框架. 本篇将我会先介绍一下如何配置Lua开发环境,然后分析在 ...
- Unity3D热更新之LuaFramework篇[09]--资源热更新与代码热更新的具体实现
前言 在上一篇文章 Unity3D热更新之LuaFramework篇[08]--热更新原理及热更服务器搭建 中,我介绍了热更新的基本原理,并且着手搭建一台服务器. 本篇就做一个实战练习,真正的来实现热 ...
- Unity3D热更新之LuaFramework篇[07]--怎么让unity对象绑定Lua脚本
前言 在上一篇文章 Unity3D热更新之LuaFramework篇[06]--Lua中是怎么实现脚本生命周期的 中,我分析了由LuaBehaviour来实现lua脚本生命周期的方法. 但在实际使用中 ...
- Unity3D热更新之LuaFramework篇[05]--Lua脚本调用c#以及如何在Lua中使用Dotween
在上一篇文章 Unity3D热更新之LuaFramework篇[04]--自定义UI监听方法 中,我对LuaBehaviour脚本进行了扩展,添加了两个新的UI监听方法,也提到最好能单写一个脚本处理此 ...
- Unity3D热更新之LuaFramework篇[04]--自定义UI监听方法
时隔一个多月我又回来啦! 坚持真的是很难的一件事,其它事情稍忙,就很容易说服自己把写博客的计划给推迟了. 好在终于克服了自己的惰性,今天又开始了. 本篇继续我的Luaframework学习之路. 一. ...
- Unity3D热更新之LuaFramework篇[08]--热更新原理及热更服务器搭建
前言 前面铺垫了这么久,终于要开始写热更新了. Unity游戏热更新包含两个方面,一个是资源的更新,一个是脚本的更新. 资源更新是Unity本来就支持的,在各大平台也都能用.而脚本的热更新在iOS平台 ...
- Unity3D热更新之LuaFramework篇[01]--从零开始
前言 因工作关系,需要对手头的项目进行热更新支持.了解后发现,Lua的几个变种:XLua.ToLua(原uLua)和Slua都可以做Unity热更,而ToLua更是提供了一个简易的热更框架--LuaF ...
- Unity3D热更新之LuaFramework篇[06]--Lua中是怎么实现脚本生命周期的
前言 用c#开发的时候,新建的脚本都默认继承自Monobehaviour, 因此脚本才有了自己的生命周期函数,如Awake,Start, Update, OnDestroy等. 在相应的方法中实现游戏 ...
随机推荐
- 初步了解学习flask轻量级框架,
关于flask我有话说 flask作为一个轻量级框架,它里面有好多扩展包需要下载,比较麻烦,而且有的时候flask需要在虚拟环境下运行,但是他的优点还是有滴 ,只要是用过Django的人,都会觉得fl ...
- 学习Acegi应用到实际项目中(9)- 实现FilterInvocationDefinition
在实际应用中,开发者有时需要将Web资源授权信息(角色与授权资源之间的定义)存放在RDBMS中,以便更好的管理.事实上,一般的企业应用都应当如此,因为这样可以使角色和Web资源的管理更灵活,更自由.那 ...
- kubernetes1.7.6 ha高可用部署
写在前面: 1. 该文章部署方式为二进制部署. 2. 版本信息 k8s 1.7.6,etcd 3.2.9 3. 高可用部分 etcd做高可用集群.kube-apiserver 为无状态服务使用hap ...
- 多线程.Thread.Sleep方法
多线程执行中,调用Thread.Sleep()方法 分情况: 1. 单核的情况下 是把当前正在工作的主线程停止(也就是从把线程变成非工作线程). 其他需要工作的线程来争夺CPU这个闲下来的核.谁争夺到 ...
- tomcat设置错误页面
今日学习笔记: 当我们访问tomcat的一个不存在的页面,返回错误信息如下: 这样的界面直接暴露给用户并不友好,有时候还不安全,因此一般需要修改默认的错误页. vim /$TOMCAT_HOME/co ...
- 我的C#跨平台之旅(二):开发最为简单的REST API
添加NuGet引用:Microsoft.AspNet.WebApi.Owin 在启动类启用WebApi: 添加一个Controller类,代码如下: 运行程序并访问:http://localhost: ...
- jupyter-notebook快捷键
Jupyter Notebook 的快捷键 Jupyter Notebook 有两种键盘输入模式.编辑模式,允许你往单元中键入代码或文本:这时的单元框线是绿色的.命令模式,键盘输入运行程序命令:这时的 ...
- FineCMS 5.0.10 多个 漏洞详细分析过程
0x01 前言 已经一个月没有写文章了,最近发生了很多事情,水文一篇.今天的这个CMS是FineCMS,版本是5.0.10版本的几个漏洞分析,从修补漏洞前和修补后的两方面去分析. 文中的evai是特意 ...
- Android UID 机制
UID一般理解为User Identifier,在linux中就是用户的ID,表明是哪个用户运行了这个程序.它们主要用于权限的管理. 而在Android 中又有所不同,因为Android为单用户系统, ...
- Kali学习笔记14:SMB扫描、SMTP扫描
SMB(Server Message Block)协议,服务消息块协议. 最开始是用于微软的一种消息传输协议,因为颇受欢迎,现在已经成为跨平台的一种消息传输协议. 同时也是微软历史上出现安全问题最多的 ...