【Unity】热更新原理与 Xlua 配置

热更新

直接理解即是让代码可以像资源包一样被运行时更新。当然它其实还一个名称叫热修复,即实现不重新打包项目也能把 Bug 修好,这也正是它常用的地方。

原理

  1. C# 无法直接热更新

    C# 是编译型语言,需要先编译成 IL 再送到虚拟机里才可运行。部分平台不支持 C# 编译器的使用,所以没法通过直接重新编译 C# 代码来实现热更新。

  2. lua 可以轻松热更新

    lua 是解释性语言,不需要编译,直接在代码中传递字符串给解释器就能运行,所以可以将其作为文本资源对待,更新起来非常轻松。

  3. 不建议完全使用 lua 编程

    解释性语言执行效率低,且 Unity 是 C# 编程环境,开发和学习的难度都会大幅提升。

  4. 在 C# 中混合 lua 实现热更新

    例如在每个 C# 函数的开头加一句判断,如果资源文件里有该函数对应的 lua 文件,才调用 lua 代码,否则说明还不需要热更新,正常调用后续的 C# 代码就行。这样的话只有需要修 Bug 的时候才要编写 lua 代码,否则正常情况可以一直使用 C# 开发。

  5. 手动混合 C# 和 lua 过于麻烦

    必须要求每个函数开头都要加上一段代码,想想就可怕,这工作量太大了,视觉效果也不美观。如果能实现自动把这些代码写上去且只在打包项目时才写上就好了。

  6. 通过 Mono.Cecil 实现 C# 库的自动修改

    C# 首先会被打包成 IL 库,最后才被 IL2CPP 编译成平台代码,IL 的状态下反编译非常容易。利用 Mono.Cecil 我们可以通过程序对这些 IL 库的内容进行调整,比如实现自动修改里面每个函数的代码,从而实现上述需求。

  7. 使用 Xlua 实现上述需求

    Xlua 已经完成了以上需求的实现,并且免费开源,我们可以直接白嫖,又有大厂加持,安全稳定,不说了开冲。

Xlua 热更新

Xlua 在官方的介绍里说是为 Unity 增加了使用 lua 脚本的能力,所以他的功能其实比较多,热更新只是其中一个。在官方文档里,热更新又叫热补丁,热补丁的文档链接如下,必看。

https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/hotfix.md

使用简介

  1. 安装方式不说了,直接去他的仓库看。 https://github.com/Tencent/xLua
  2. 为项目添加 HOTFIX_ENABLE 宏,从而打开热更新功能。
  3. 把所有你需要热更新的代码打上[Hotfix]标签,具体看文档,注意方式一高版本 Unity 用不了。
  4. 搞个单例类,在里面开一个 lua 虚拟机,在里面加载一个文本文件给虚拟机。
  5. 这个加载上来的文本文件就是写 lua 热更新代码的地方,即出了 bug 需要替换上的新代码。
  6. lua 热更新代码里主要是调用 xlua.hotfix 函数实现代码替换,具体看文档。
  7. 点击菜单项 XLua/Generate Code,然后直接打包游戏就行,Xlua 会自动按之前说过的原理修改标记好函数使其支持热更新。

注意点

  1. 高版本 Unity 中所有打标签方式都请使用文档中打[Hotfix]标签的方式二。

  2. 使用 IL2CPP 时,仅 lua 中用到的类有可能会被字节代码剥离程序删除。

    IL2CPP 的过程中会自动删除没有被使用无效代码,而 lua 中调用 C#代码的方式有点类似于反射,这种间接的类型访问方式无法被 IL2CPP 程序识别,因而会导致相关代码被错误的剥离。

    推荐打上[LuaCallCSharp]或[ReflectionUse]标签来解决这个问题,这样 XLua 便能自动把这些类型配置为不可被剥离。

  3. GenerateCode 前建议先调用 ClearGenerateCode,这样才能保证生成的文件确实和代码中设置的一致。

其他猜想

  1. 为什么 C# 变 C++ 代码后,代码结构剧变,lua 也能正常调用?

    C# 访问函数的方式不是直接使用地址,而是先用符号(函数名)去检索地址,然后再跳转到该地址。IL2CPP 中虽然 C# 代码被转换,但这种访问方式被保留了下来,其符号信息就存在 global-metadata.dat 文件中,所以 lua 使用 C# 中的名称也能正常访问。

总结

抛开细节不谈还是蛮简单的,不说了学 lua 去了。

【Unity】热更新原理与Xlua配置的更多相关文章

  1. 深入理解xLua热更新原理

    热更新简介 热更新是指在不需要重新编译打包游戏的情况下,在线更新游戏中的一些非核心代码和资源,比如活动运营和打补丁.热更新分为资源热更新和代码热更新两种,代码热更新实际上也是把代码当成资源的一种热更新 ...

  2. 深入理解xLua基于IL代码注入的热更新原理

    目前大部分手游都会采用热更新来解决应用商店审核周期长,无法满足快节奏迭代的问题.另外热更新能够有效降低版本升级所需的资源大小,节省玩家的时间和流量,这也使其成为移动游戏的主流更新方式之一. 热更新可以 ...

  3. Unity 热更新XLua

    什么是冷更新 开发者将测试好的代码,发布到应用商店的审核平台,平台方会进行稳定性及性能 测试.测试成功后,用户即可在AppStore看到应用的更新信息,用户点击应用更 新后,需要先关闭应用,再进行更新 ...

  4. Unity3D热更新之LuaFramework篇[08]--热更新原理及热更服务器搭建

    前言 前面铺垫了这么久,终于要开始写热更新了. Unity游戏热更新包含两个方面,一个是资源的更新,一个是脚本的更新. 资源更新是Unity本来就支持的,在各大平台也都能用.而脚本的热更新在iOS平台 ...

  5. 另类Unity热更新大法:代码注入式补丁热更新

    对老项目进行热更新 项目用纯C#开发的? 眼看Unity引擎热火朝天,无数程序猿加入到了Unity开发的大本营. 一些老项目,在当时ulua/slua还不如今天那样的成熟,因此他们选择了全c#开发:也 ...

  6. ElasticStack系列之七 & IK自动热更新原理与实现

    一.热更新原理 elasticsearch开启加载外部词典功功能后,会每60s间隔进行刷新字典.具体原理代码如下所示: public void loadDic(HttpServletRequest r ...

  7. 【热更新IK词典】ElasticSearch IK 自动热更新原理与实现

    一.热更新原理 elasticsearch开启加载外部词典功功能后,会每60s间隔进行刷新字典.具体原理代码如下所示: public void loadDic(HttpServletRequest r ...

  8. webpack与browser-sync热更新原理深度讲解

    本文首发于CSDN网站,下面的版本又经过进一步的修订.原文:webpack与browser-sync热更新原理深度讲解本文包含如下内容: webpack-hot-middleware EventSou ...

  9. unity热更新方案对比

    Unity应用的iOS热更新 •  什么是热更新 •  为何要热更新 •  怎样在iOS 上对Unity 应用进行热更新 •  支持Unity iOS 热更新的各种Lua 插件的对照 什么是热更新 • ...

  10. Unity热更新对比

    https://www.jianshu.com/p/f9d90edf4a7c Unity 热更新为啥用Lua 详解 ILRuntime的优势 同市面上的其他热更方案相比,ILRuntime主要有以下优 ...

随机推荐

  1. Java基础 —— 集合(一)

    集合(一) 数组和集合的区别 数组是固定长度的数据结构,而集合是动态的数据结构 数组可以包含基本数据类型和对象,集合只能包含对象 数组只能存放同一类型的数据,而集合可以蹲房不同类型的 数组可以直接访问 ...

  2. windows下fopen,fclose断电数据丢失解决办法

    #include <io.h> //在fclose之前调用fflush和_commit,可以有效防止断电数据丢失 fflush(file); _commit(fileno(file)); ...

  3. The 2nd GUAT Collegiate Programming Contest (Round 1)

    第二届 GUAT大学生程序设计大赛 第一场 题解(A-M) 前言 比赛的内容主要包括计算机科学的常用算法,基本的计算理论,(如:离散数学,具体数学,组合数学基础),数据结构基础,程序设计语言(规定是C ...

  4. 深入聊聊async&Promise

    正文 最近在学习JavaScript里的async.await异步,对于其中的Promise状态以及背后的Js引擎实际运行状态不大理解且很感兴趣,因此花了一点时间仔细研究了一下. 从Example说起 ...

  5. 在 .NET 下,Fiddler 不再抓取 Web Service 流量问题

    在 .NET 下,Fiddler 不再抓取 Web Service 流量问题 问题现象 原来的一个应用中,需要访问 SOAP 服务.在原来的 .NET Framework 版本中,使用 Fiddler ...

  6. 【数据库】MongoDB服务启动失败的问题。

    1.确保MongoDB所在文件夹拥有所有权限 2.确保打开CMD窗口是以管理员身份运行的 3.配置文件中的路径应该为完整路径,且不包含空格和特殊字符(不建议包含) systemLog: destina ...

  7. redis中是没有Long类型的

    redis中没有Long类型,存储进去后取出来会是Interger类型.需要自行转化,不可直接强转.否则将CCE. 本人在处理springboot的redisTemplate封装时发生了这个异常.解决 ...

  8. office文件所对应的的 Content-type类型总结

    最近做文件下载因为涉及到不同类型的文件,所以重新查阅了一下文件所对应的的content-type类型,好记性不如烂笔头,记录一下. 文件后缀 MIME TYPE .doc application/ms ...

  9. manim边学边做--同伦变换

    在Manim中,移动一个元素除了之前介绍的方法之外,还可以通过同伦运算来移动一个元素. 与普通的移动元素方式相比,使用同伦运算移动一个元素时,实际上是在考虑整个空间的连续变形过程中元素的相应变化. 这 ...

  10. Qt通用方法及类库2

    函数名 //初始化数据库 static void initDb(const QString &dbName); //初始化文件,不存在则拷贝 static void initFile(cons ...