【Unity】Lua热重载
写在前面
- 本文讨论的“Lua热重载”是基于他人现成工具和相关博文上展开的,所以这里并不会重复实现一遍工具,主要记录我的理解过程。
Lua热重载
探索
- 偶然在知乎上翻到一篇文章“使用ILRuntime遇到的一些问题”,文章最后提到Lua特有的加载机制(如下图),我第一个念头就是“怎么用Lua做了那么久的热更,我却没想到用Lua来做测试呢!”,如果能在不重新启动Unity的前提下重载Lua脚本,测试效率肯定会大大提升,而我最想提升的就是程序员在写好UI脚本后的测试效率,于是我开始在网上搜索有没有现成工具。

刚开始搜索到的博客们实现重点都差不多,代码如下图:
function reimport(name)
local package = package
package.loaded[name] = nil
package.preload[name] = nil
return require(name)
end
于是我直接用这段代码拿工作项目里的图鉴UI做测试,结果没有成功。我没懂为啥不成功,于是我继续搜资料。以下是我主要参考的3篇资料。
【参考A】
【参考A】它是我找到的第一个示例,作者提供了两个G站链接,一个是作者自己的,另一个是作者参考的,而我先误点开的是参考链接,下载代码后发现运行时直接上while(true)的话Unity会卡死(尽管作者有写sleep),肇事代码如下图:

将肇事代码修好后开始测试,第一次测试,可以正常热重载,放到另一个项目的第二次测试,却不能正常热重载。因为这个没有Unity示例,代码一时半会看不懂,所以我暂时放弃……
后来我也打开看过作者的链接,不过那时我已经找到了【参考B】,所以只是粗略的翻了翻。
【参考B】
【参考B】有Unity示例,有代码讲解!是这3篇参考资料里读起来最轻松的(我在阅读的时候发现【参考A】作者链接的代码其实就是【参考B】的完整版,那里update_func()的内容会更加详细)。
它的Unity示例内容简单来说,就是在C#那边监听文件改动,如有改动,调用Lua那边的hotfix脚本。作者写了两个重载时机:管理者的Update和具体脚本的Reload。重载实现以package.loaded为前提。
以下是我在阅读、测试【参考B】代码时冒出的问题和解答(用“——>”符号标识):
- updated_tables感觉只是更新函数,和记录访问过的table,没看出哪里体现更新table ?——> 其实重点就是“更新函数”。

- 为什么会想到upvalue?——> 我最开始猜想是为了不破坏旧引用,后来测试证实,使用旧引用具体是为了维持其他地方的引用不变,所以不能直接拿新引用直接覆盖旧引用。(不过在测试中,正常重载后依然会显示老代码对应的行号,容易误导)

- 作者提供的代码只能在update函数里改,我想在任意函数里改,咋整?——> 写在作者提供的Reload函数中。
- 我在读作者博客时有一段没读懂(如下图),package.load[filename] 拿到的不是布尔值吗,类的类型哪里体现?filename即对应Lua脚本,不管多少次require,都会指向同一对象,怎么会不是类的实例呢?

——> 这里我的理解出错了。package.load[filename] 拿到的不是布尔值,是filename对应的Lua脚本具体返回值,如果没有写返回值,则require会记返回值是true。
“调用package.load[filename] 获得的是类的类型,并不是类的实例。”,首先,作者用的是云风写的Lua类,在class的代码里(如下图,我截图用的是云风版class,作者用的是自己修改后的BaseClass)能看到返回的是class_type(即“类-类型”),class_type用了new()才能拿到实例。

以作者的PlayerMove.lua为例,在PlayerMove.lua代码末尾,他return的是PlayerMove,所以在require("PlayerMove")时,返回的是PlayerMove类型。
如果作者在PlayerMove.lua代码末尾return的是PlayerMove.New(),则在require("PlayerMove")时,返回的是PlayerMove实例。
【参考C】
KSFramework:它的热重载实现写的很简单,完全没碰Lua那边,只是在C#这边把UI的老引用清了,换成新引用。
接入工作项目
我尝试将【参考B】这个现成的重载工具接入工作项目,过程依然问题多多,以下是遇到问题和解决方法记录:
最开始我在C#这新开了一个LuaState来负责监听Lua脚本变化工作,但不行,会出问题(Unity崩溃;工作项目的一些Lua脚本报错但看代码无问题),所以去掉了新开的LuaState。
- 工作项目中基本UI都是用dofile加载的,而不是require,所以在package.loaded[...]中找不到记录(前面提到的图鉴UI就是用dofile加载的,所以最开始测试失败),这里需要我另写函数来处理,如下:

- 虽然【参考B】用的是Lua脚本变化时自动触发重载,但因为工作项目是Unity2017版本,我在Unity2017上测试时发现自动重载时内容未发生变化,而此时Unity自己正在加载,卡住了一小会;如果是在Unity加载完后再触发重载,此时内容有变化,重载正常。因此我将自动触发改为了手动触发。
- 测试发现【参考B】脚本不让在运行时加新函数,会有断言报错。可以改成“在运行时加新函数”,但我不认为有改的必要。
因为UI在C#那边记录的引用比较多,再加上正常重载Lua脚本后还显示旧行号的问题,所以这个工具我用的不多,研究到此告一段落。
【Unity】Lua热重载的更多相关文章
- lua热重载
热重载,就是不重新开unity让代码的变化直接看出来,一般在开发时候使用 lua中通过require导入的文件,最终都存在package.loaded这个table中.require会判断是否文件已经 ...
- 出售一套Unity + Lua热更新框架代码
出售一套Unity + Lua的客户端框架代码,功能有资源管理.网络通信.配置文件解析.热更新.文件读写.Lua加密揭秘.UI框架.打包工具.编辑器工具等,已经在多个实际项目(已上线)中使用.代码优雅 ...
- KSFramework常见问题:Lua脚本热重载,内存状态数据丢失?
Lua热重载 内存数据在重载后会丢失 KSFramework中,所有的UI Lua脚本是可以重载的.脚本中的一些内存数据,在重载后会丢失,比如: -- 记录一个UI界面被打开了多少次 function ...
- KSFramework:集成U3D热重载框架 - README
KSFramework KEngine + SLua+ Framework = KSFramework KSFramework是一个整合KEngine.SLua的Unity 5开发框架,并为程序.美术 ...
- Unity代码热更新方案 JSBinding + SharpKit 首页
目前Unity的代码更新方案有很多,主要以lua为主. JSBinding + SharpKit 是一种新的技术,他做了两件事情: JSBinding将C#导出到 JavaScript (引擎是 Mo ...
- lua热更框架之XLua
框架介绍 xLua是当下最流行的unity热更方案之一,作者是腾讯的车雄生前辈,自2016年初推出以来,已经在腾讯的多款游戏项目上应用,目前xLua已经开源到了GitHub.xLua最大的特色是不仅支 ...
- unity游戏热更新总结
1.利用反射来做Dll更新 这种方式只支持windows以及安卓这种支持JIT的平台,对于IOS就不适用了,IOS这种Full-AOT的平台不支持生成新的代码,因此这种热更方式很少用到. 2.利用 ...
- webpack使用webpack-dev-middleware进行热重载
新手,刚开始学习webpack,想使用webdevserver,但定制性太差,于是研究了一下使用webpack-dev-middleware进行指定. 根据文档https://www.npmjs.co ...
- .Net 4.X 提前用上 .Net Core 的配置模式以及热重载配置
1. 前言 在提倡微服务及 Serverless 越来越普及的当下,在 .Net Core 之前,.Net 应用的配置模式往往依赖于一个名为 web.config 的 XML 文件,耦合性高,而可扩展 ...
- Node.js + gulp 合并静态页模版,文件更新自动热重载。浏览器可预览
github地址:https://github.com/Liaozhenting/template 使用的是ejs的语法.其实你用什么文件后缀都可以,都是按ejs来解析. 模板文件放在componen ...
随机推荐
- Excel 的盒须图 离群值 Outliers
Excel 中的盒须图 翻译自https://www.excel-easy.com/examples/box-whisker-plot.html 本示例教您如何在Excel中创建盒须图.盒须图显示了数 ...
- Docker 使用阿里云加速拉取官方镜像
首先登陆阿里云容器镜像服务控制台,在左侧导航栏选择镜像工具 > 镜像加速器,在镜像加速器页面获取镜像加速地址. 例如: 加速器地址:[系统分配前缀].mirror.aliyuncs.com 配置 ...
- maven加载本地的jar包
方式1 ,通过scope = system的方式加载 <dependency> <groupId>com.sun.jna</groupId> <artifac ...
- 89、des加密算法
import javax.crypto.Cipher; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpe ...
- 织梦dedecms网站迁移搬家图文教程
织梦dedecms网站迁移搬家图文教程 2014-07-31 dedecms教程 文章介绍 织梦作为国内使用最多的程序之一,难免很多新手在接触dede时不知道怎么转移也就是搬家dede的程序,而且 ...
- 测试elasticsearch保存时报找不到类型的错误
java测试存储数据到es时报错:...ActionRequestValidationException: Validation Failed: 1: type is missing... /** * ...
- AD笔记总结
原理图要点: 1.新建工程, 新建的project是要以后缀PrjPCB2.新建原理图.PCB, 右键project,进行New添加3.新建原理图库.PCB库,右键project, 进行new添加 改 ...
- express的使用:接口的编写(三)
1.接口的跨域问题 a.CORS,主流 b.JSONP,只支持get请求 步骤:a.安装 npm install cors b.使用 const cors = require('cors') 导入中 ...
- Easycode—MybatisPlus模板
EasyCode使用指南 1.下载EasyCode插件 2.配置EasyCode 2.1.配置作者名称 2.2.配置代码内容生成模板(模板内容见文末) ...
- G6-Editor 编辑器入门使用教程
一.前言 G6-Editor 是 AntV 官方提供的.专注于图可视化编辑器的类库,也是市面上完成度较高的图可视化编辑器.然而令人诟病的是其文档对新手极度不友好,我一度怀疑此文档只有他们自己开发人员才 ...