写在前面

  • 本文讨论的“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热重载的更多相关文章

  1. lua热重载

    热重载,就是不重新开unity让代码的变化直接看出来,一般在开发时候使用 lua中通过require导入的文件,最终都存在package.loaded这个table中.require会判断是否文件已经 ...

  2. 出售一套Unity + Lua热更新框架代码

    出售一套Unity + Lua的客户端框架代码,功能有资源管理.网络通信.配置文件解析.热更新.文件读写.Lua加密揭秘.UI框架.打包工具.编辑器工具等,已经在多个实际项目(已上线)中使用.代码优雅 ...

  3. KSFramework常见问题:Lua脚本热重载,内存状态数据丢失?

    Lua热重载 内存数据在重载后会丢失 KSFramework中,所有的UI Lua脚本是可以重载的.脚本中的一些内存数据,在重载后会丢失,比如: -- 记录一个UI界面被打开了多少次 function ...

  4. KSFramework:集成U3D热重载框架 - README

    KSFramework KEngine + SLua+ Framework = KSFramework KSFramework是一个整合KEngine.SLua的Unity 5开发框架,并为程序.美术 ...

  5. Unity代码热更新方案 JSBinding + SharpKit 首页

    目前Unity的代码更新方案有很多,主要以lua为主. JSBinding + SharpKit 是一种新的技术,他做了两件事情: JSBinding将C#导出到 JavaScript (引擎是 Mo ...

  6. lua热更框架之XLua

    框架介绍 xLua是当下最流行的unity热更方案之一,作者是腾讯的车雄生前辈,自2016年初推出以来,已经在腾讯的多款游戏项目上应用,目前xLua已经开源到了GitHub.xLua最大的特色是不仅支 ...

  7. unity游戏热更新总结

    1.利用反射来做Dll更新 这种方式只支持windows以及安卓这种支持JIT的平台,对于IOS就不适用了,IOS这种Full-AOT的平台不支持生成新的代码,因此这种热更方式很少用到.   2.利用 ...

  8. webpack使用webpack-dev-middleware进行热重载

    新手,刚开始学习webpack,想使用webdevserver,但定制性太差,于是研究了一下使用webpack-dev-middleware进行指定. 根据文档https://www.npmjs.co ...

  9. .Net 4.X 提前用上 .Net Core 的配置模式以及热重载配置

    1. 前言 在提倡微服务及 Serverless 越来越普及的当下,在 .Net Core 之前,.Net 应用的配置模式往往依赖于一个名为 web.config 的 XML 文件,耦合性高,而可扩展 ...

  10. Node.js + gulp 合并静态页模版,文件更新自动热重载。浏览器可预览

    github地址:https://github.com/Liaozhenting/template 使用的是ejs的语法.其实你用什么文件后缀都可以,都是按ejs来解析. 模板文件放在componen ...

随机推荐

  1. atx

    https://github.com/openatx/atx-agent/releases/download/0.9.4/atx-agent_0.9.4_linux_386.tar.gz

  2. js过滤掉指定html标签

    替换标签 var str = "<p><span style='color:#ccc;'>这是测试标签</span><span>这是测试htm ...

  3. jeecgboot <j-popup

    <a-col :span="24"> <a-form-item label=" 规格" :labelCol="labelCol&qu ...

  4. OA产品并发访问能力

    环境:cpu 16c,内存 32G,系统管理服务.jtportal服务 启动双实例样本:50线程,循环登录60次,共计3000次登录,用时3分钟40秒结论:平均每分钟支持800次登录,均在3秒左右.按 ...

  5. MSDTC突然停用了,后台数据无法更新

    由于前台电脑停电突然关机,导致重启后发现MSDTC无法更新数据,重新添加了link,只能查询,更新失败,报错:无活动事务 1.修改host设置,在C:\Windows\System32\drivers ...

  6. fix: because the volume group on the selected device also consist of physical volumes on other devices

    because the volume group on the selected device also consist of physical volumes on other devices 目标 ...

  7. idea因时区连不上msyql8问题

    转载自https://www.cnblogs.com/lakei/p/11303174.html Connection to api@localhost failed. [08001] Could n ...

  8. 使用HttpClient4.5 使用MultipartEntityBuilder 类发送 multipart/formdata 格式给第三方接口 失败的原因

    1.使用MultipartEntityBuilder的setCharset方法设置 utf-8格式2.在httppost 请求头上 加上Content-Type", "multip ...

  9. python爬虫--房产数据爬取并保存本地

    import requestsimport csvfrom bs4 import BeautifulSoupheaders={'user-agent':'Mozilla/5.0 (Windows NT ...

  10. 自定义函数式@FunctionalInterface异常接口

    1.添加注解 /** * 抛出异常函数接口 * * @author liunancun * @date 2021/2/5 */ @FunctionalInterface public interfac ...