【Unity】浅尝xlua热更新插件

前言

之前的学习中了解到了一些热更新的知识,本想系统地学习基于xLua的热更新框架,但时间紧迫,遂浅尝辄止。在此记录一下相关知识。

什么是热更新

这里有一篇博客讲得很好,指路->【Unity框架】基于XLua框架搭建与AssetBundle的使用流程

从云端下载资源包,这些新资源包会被自动整合进现有软件中,达到动态更新软件的目的,而无需重新下载整个软件。而支持热更新的脚本可以打包成AB包上传到服务器,这就能够实现热更新。

最主流的Unity热更新方式的有三种:

  1. XLua
  2. ILRuntime
  3. huatuo

前者是腾讯开源,网上教程很多、十分成熟、好评如潮,但要熟悉新语言lua;
中者用C#来作为热更语言,最大的优势是项目可以用同一个语言来进行开发;
后者是Unity全平台原生c#热更新方案,据说它特性完整、零成本、高性能、低内存、近乎完美。

xLua是什么

Tencent/xLua: xLua is a lua programming solution for C# ( Unity, .Net, Mono) , it supports android, ios, windows, linux, osx, etc. (github.com)

2017年初的一篇文章中这样写道:

2016年12月末,xLua刚刚实现新的突破:全平台支持用Lua修复C#代码bug。
目前Unity下的Lua热更新方案大多都是要求要热更新的部分一开始就要用Lua语言实现,不足之处在于:
1、接入成本高,有的项目已经用C#写完了,这时要接入需要把需要热更的地方用Lua重新实现;
2、即使一开始就接入了,也存在同时用两种语言开发难度较大的问题;
3、Lua性能不如C#;

xLua热补丁技术支持在运行时把一个C#实现(函数,操作符,属性,事件,或者整个类)替换成Lua实现,意味着你可以:
1、平时用C#开发;
2、运行也是C#,性能秒杀Lua;
3、有bug的地方下发个Lua脚本fix了,下次整体更新时可以把Lua的实现换回正确的C#实现,更新时甚至可以做到不重启游戏;
这个新特性iOS,Android,Window,Mac都测试通过了,目前在做一些易用性优化。

Lua:Lua解释执行时,性能接近于native

xLua:xLua是Lua在C#环境( .net)的解决方案

xLua功能特性:

  1. 可以运行时把C#实现(方法,操作符,属性,事件等等)替换成lua实现;
  2. 出色的GC优化,自定义struct,枚举在Lua和C#间传递无C# gc alloc;
  3. 编辑器下无需生成代码,开发更轻量;
    详细说明见此处

如何向项目中引入xLua

github中下载ZIP文件后,解压,进入Assets文件夹,看到有如下四个文件。
image
把这四个文件直接复制进Unity项目中的Asset文件夹下,注意不要错放到Asset的子文件中。等待Unity编译完就可以了。

基于xLua的纯Lua开发框架的基本原则

  1. 游戏场景中不放任何游戏对象。避免冲突,用代码生成对象。

  2. 运行时仅有一个场景,不涉及场景切换。策划、美术、程序分离。

  3. 不手动向预制体上挂载代码。去编辑器化,便于维护代码。

  4. 以纯AssetsBundle代替Resources做资源管理。

    a:方便更新 :更新代码(lua->脚本代码ab包)+更新资源(AssetsBundle)

    b:方便打包:场景+场景依赖的资源;Resources文件夹下的所有资源打入安装包

  5. 制定一个纯Lua开发的组件化框架,方便编写业务逻辑与运算,尽可能减少Lua调用C#提升性能。

  6. 建立调试模式以加载Lua代码与资源:AssetsDatabase加载资源,供Editor模式下使用。

基本框架

目录结构

  1. AssetsPackage:用于存放所有游戏资源。
  2. Scenes:用于存放游戏场景。
  3. Scripts:用于存放框架性质的C#代码。
  4. LuaScripts:用于存放Lua代码。
  5. StreammingAssets:用于存放ab包。若不打空包,则将ab包放入该文件夹内,和安装包一起打包。
  6. Editor:用于扩展编辑器。

框架启动全流程

  1. GameLaunch单例
using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; public class GameLaunch : MonoSingleton<GameLaunch> { public void Awake() { //初始化游戏框架:声音管理,资源管理,网络管理等 } IEnumerator CheckHotUpdate() { //热更新游戏资源+代码 //end yield return null; } IEnumerator GameStart() { yield return this.StartCoroutine(this.CheckHotUpdate()); //进入游戏,通过Lua虚拟机进入Lua逻辑代码 Debug.Log("GameStart"); //end } protected override void OnStart() { StartCoroutine(this.GameStart()); } }

独立化Lua脚本开发

  1. 内置Lua虚拟机。Managers->xLuaManager

  2. 将Lua代码脱离于C#代码,虚拟机加载我们的文本代码并执行。

    虚拟机装载执行第一个Lua脚本,main.lua

  3. 自定义一个Lua代码装载器(LuaScriptLoader),当我们请求装载代码时,到项目指定的路径下装载Lua代码。

  4. 装载方式:调试模式直接在LuaScripts下加载;发布模式LuaScripts->ab包->从ab包中加载Lua内容。

如下是代码示例。

using System; using System.Collections; using System.Collections.Generic; using System.IO; using Unity.VisualScripting; using UnityEditor; using UnityEngine; using XLua; public class xLuaManager : MonoSingleton<xLuaManager> { private static string luaScriptsFolder = "LuaScripts"; private LuaEnv env = null; private bool isGameStarted = false; private void Awake() { this.InitLuaEnv(); } public byte[] LuaScriptLoader(ref string filepath) { //Debug.Log("#" + filepath); string scriptPath = string.Empty; filepath = filepath.Replace(".", "/") + ".lua.txt"; # if UNITY_EDITOR//调试模式 scriptPath = Path.Combine(Application.dataPath, luaScriptsFolder); scriptPath = Path.Combine(scriptPath, filepath); //byte[] data = GameUtility.SafeReadAllBytes(scriptPath); byte[] data = File.ReadAllBytes(scriptPath); return data; #endif //发布模式 return null; } private void InitLuaEnv() { this.env = new LuaEnv(); this.env.AddLoader(this.LuaScriptLoader); } protected override void OnStart() { base.OnStart(); } public void EnterGame() { //游戏正式开始 this.isGameStarted = true; //进入游戏逻辑 //Lua代码:print("helloworld!"); this.env.DoString("require (\"main\")"); this.env.DoString("main.init()"); } private void Update() { if(this.isGameStarted) this.env.DoString("main.update()"); } private void FixedUpdate() { if (this.isGameStarted) this.env.DoString("main.fixedUpdate()"); } private void LateUpdate() { if (this.isGameStarted) this.env.DoString("main.lateUpdate()"); } }

main.lua.txt

--定义全局模块 main = {} local GameApp = require("Game.GameApp") local function init() --print("init") --初始化lua框架:自定义时间、网络、日志... --end --end进入游戏逻辑 GameApp.EnterGame() end main.init = init local function update() --每帧执行 --print("update") end main.update = update local function fixedUpdate() --每帧执行 --print("fixedUpdate") end main.fixedUpdate = fixedUpdate local function lateUpdate() --每帧执行 --print("lateUpdate") end main.lateUpdate = lateUpdate

如何热更新代码与资源

注意:.lua无法打ab包,后缀必须改为.lua.byte才能打包。(有待考证,可能和框架有关)

利用assetbundle,将lua脚本打包为lua.assetsbundle,下载到本地;

加载lua脚本时,从ab包中加载最新的lua代码,加载完后执行。

和热更新其他资源的步骤是一样的。

参考资料

Tencent/xLua (github.com)
smilehao/xlua-framework (github.com)
【Unity框架】基于XLua框架搭建与AssetBundle的使用流程
Unity进阶教程:Xlua热更框架开发游戏【热更新视频教程】
ILRuntime.index


__EOF__

本文作者OtusScops
本文链接https://www.cnblogs.com/OtusScops/p/16743325.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   AshScops  阅读(362)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示