【Unity】热更新之xLua C#调用Lua / 自定义加载器 / 加载并执行AB包中的Lua文件

2023-10-27

最近在学习xLua,和大家分享一下学习笔记。

下载xLua

xLua的GitHub下载地址:xLua下载-GitHub-点击进入
xLua GitHub
点击链接进入后,首先点击Code,再点击Download ZIP把压缩包下载下来,下载完后解压得到xLua-master文件夹,在Assets目录下将Plugins文件夹和XLua文件夹拷贝到你的Unity工程的Assets目录下即可导入XLua。
导入后先清理一下xLua产生的代码,不然可能会报错
在这里插入图片描述

C#执行Lua代码(xLua)

首先需要引入XLua命名空间,使用xLua提供的Lua解析器LuaEnv中的DoString方法即可执行Lua代码。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

public class LuaTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        LuaEnv luaEnv = new LuaEnv();
        luaEnv.DoString("print('Hello world!')");
    }
}

将脚本挂到场景的任何一个物体下,点击运行即可看到输出。
Hello world
虽然执行成功了,但是直接把全部Lua代码写在DoString的参数里面显然有点傻,也不符合我们日常编码习惯,所以我们需要用到Lua的require(“Lua文件名”)来执行一段lua代码。
接下来修改一下代码,首先创建一个lua文件(可以直接创建一个文本文件,然后修改后缀名为.lua)保存在Resources文件夹中(默认从Resources文件夹加载lua文件),我这里用的Sublime Text打开编辑(可以使用任何IDE,记事本也可以),随便写一句Lua代码。

保存后关闭编辑器,将你刚创建的Lua代码的后缀名改成txt,直接在后面加上.txt(MyLua.lua.txt)。这里改后缀名的原因我估计是Unity Resources加载文件方法不能识别后缀名为.lua的文件,所以后缀名需要改为.txt。(这里只是我的猜想)
修改刚刚的C#代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

public class LuaTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        LuaEnv luaEnv = new LuaEnv();
        luaEnv.DoString("require('MyLua')");
    }
}

返回Unity,点击运行即可看到Lua脚本的输出。

自定义加载器

上面require(‘Lua文件名’)默认是从Resources上面加载的,如果我们想自定义加载路径怎么办?况且Resources文件夹只是可读的,需要热更新的Lua代码因为需要动态读写,不会存放在Resources里面,那就要需要自定义加载器了。
那如何自定义加载器呢?LuaEnv给我们提供一个方法,我们进入LuaEnv.cs看看。
LuaEnv.cs
这里我们看到有一个AddLoader的方法,参数传入一个委托。我们先定义一个和AddLoader所需要的委托一致的方法MyCustomLoader,这个方法就是我们的自定义加载器,filepath传入的是LuaEnv.DoString(“require(‘Lua文件名’)”)中的Lua文件名。然后添加自定义加载器luaEnv.AddLoader(MyCustomLoader);

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
using System.IO;

public class LuaTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        LuaEnv luaEnv = new LuaEnv();
        //添加自定义加载器
        luaEnv.AddLoader(MyCustomLoader);
        luaEnv.DoString("require('MyLua')");
    }

    byte[] MyCustomLoader(ref string filepath)
    {
        //根据文件名,自定义加载路径,我这里是Asset文件夹下新建了一个Lua文件夹
        string path = Application.dataPath + "/Lua/" + filepath + ".lua";
        //这里判断一下文件是否存在	File需要引用System.IO命名空间
        if (File.Exists(path))
        {
            //如果存在,将文件读取出来并返回出去
            return File.ReadAllBytes(path);
        }
        //如果不存在就返回空
        return null;
    }
}

下面是Lua代码,这里Lua代码因为使用File来读取的文件,所以可以不用修改后缀名为.txt。

--MyLua.lua 代码
print("my lua!")

自定义加载器会比默认加载器先执行,也就是说,xLua会先到自定义加载器中加载Lua文件,当全部自定义加载器(可以有多个自定义加载器)加载失败再到默认加载器中加载Lua文件。
返回Unity运行后可以都看到Lua的输出,说明我们已经正确的加载并执行了Lua文件。
在这里插入图片描述

自定义加载器加载AB包中的Lua文件

因为AB包加载资源不支持lua文件,这里需要先将Lua代码的后缀名添加.txt(我这的文件名是MyLua.lua.txt),然后打包到AB包中,打包时如果出现打包失败并报错,可以尝试清理一下XLua生成的代码,再打AB包。
在这里插入图片描述
我们再自定义一个加载器用来加载AB包中的Lua文件

	byte[] MyABCustomLoader(ref string filepath)
    {
        //先加载Lua文件所在的AB包
        AssetBundle abPage = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/lua");
        //从AB包中加载对应的Lua文件
        TextAsset luaText = abPage.LoadAsset<TextAsset>(filepath + ".lua");

        if (luaText != null)
            return luaText.bytes;

        return null;
    }

接着AddLoader我们自定义的这个加载器就可以了,完整代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
using System.IO;

public class LuaTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        LuaEnv luaEnv = new LuaEnv();
        //添加自定义加载器
        luaEnv.AddLoader(MyCustomLoader);
        luaEnv.AddLoader(MyABCustomLoader);

        luaEnv.DoString("require('MyLua')");
    }

    /// <summary>
    /// 自定义加载器,用来加载自定义路径中的Lua文件
    /// </summary>
    /// <param name="filepath">Lua文件名</param>
    /// <returns>Lua文件字节数组</returns>
    byte[] MyCustomLoader(ref string filepath)
    {
        //根据文件名,自定义加载路径,我这里是Asset文件夹下新建了一个Lua文件夹
        string path = Application.dataPath + "/Lua/" + filepath + ".lua";
        //这里判断一下文件是否存在	File需要引用System.IO命名空间
        if (File.Exists(path))
        {
            //如果存在,将文件读取出来并返回出去
            return File.ReadAllBytes(path);
        }
        //如果不存在就返回空
        return null;
    }

    /// <summary>
    /// 自定义加载器,用来加载AB包中的Lua文件
    /// </summary>
    /// <param name="filepath">Lua文件名</param>
    /// <returns>Lua文件字节数组</returns>
    byte[] MyABCustomLoader(ref string filepath)
    {
        //先加载Lua文件所在的AB包
        AssetBundle abPage = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/lua");
        //从AB包中加载对应的Lua文件
        TextAsset luaText = abPage.LoadAsset<TextAsset>(filepath + ".lua");

        if (luaText != null)
            return luaText.bytes;

        return null;
    }
}

以上就是这篇文章的所有内容了,如有那个地方写的不准确,劳烦大佬指出,感谢,希望对各位看官有所帮助!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Unity】热更新之xLua C#调用Lua / 自定义加载器 / 加载并执行AB包中的Lua文件 的相关文章

  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • GLKit的GLKMatrix“列专业”如何?

    前提A 当谈论线性存储器中的 列主 矩阵时 列被一个接一个地指定 使得存储器中的前 4 个条目对应于矩阵中的第一列 另一方面 行主 矩阵被理解为依次指定行 以便内存中的前 4 个条目指定矩阵的第一行 A GLKMatrix4看起来像这样 u
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • 使用 x509 证书签署 json 文档或字符串

    如何使用 x509 证书签署 json 文档或字符串 public static void fund string filePath C Users VIKAS Desktop Data xml Read the file XmlDocum
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况

随机推荐

  • 如何使用Pytest进行自动化测试(干货)

    为什么需要自动化测试 自动化测试有很多优点 但这里有3个主要的点 可重用性 不需要总是编写新的脚本 除非必要 即使是新的操作系统版本也不需要编写脚本 可靠性 人容易出错 机器不太可能 当运行不能跳过的重复步骤 测试时 速度会更快 全天运行
  • Windows ~~~ ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: NO)

    安装MySQL5或8出问题 1 ERROR 1045 28000 Access denied for user root localhost using password NO 1 1 解决方法 2 ERROR 1045 28000 Acc
  • 预测房价(Python)

    构建神经网络 深度学习模型的基本步骤 深度学习模型具有一定的通用性 使得深度学习的门槛降低 这是深度学习得以重新占据计算机领域一席之地的重要原因 深度学习均可以从下述五个步骤来完成模型的构建和训练 def load data 从文件导入数据
  • 攻防世界新手区web simple_php

    simple php 不认识show source函数 百度一下 可知这个函数是对测试文件 test php 进行 PHP 语法高亮显示 可大致理解为提交a和b的正确形式可得到flag 百度可知is numeric函数判断是否为数字或数字字
  • 与众不同的协同办公工具——飞书

    其实很早就知道飞书 但真正深入了解 还是最近一个月的事情 因为一个知识付费产品的强烈推荐 我才真正试用了一下 试完之后 很有启发 觉得有必要整理和总结一下 以便后续继续深入使用 飞书有什么不同 我觉得有如下三点 第一 不一样的沟通方式 它力
  • windows使用命令行创建文件echo >test.txt(可以是.gp .js .ts..)

    或多说直接上代码 第一步 打开命令行 进入要创建的目录 C Users gt cd C Users lenovo Desktop node 第二步 输入创建文件的指令 echo gt 文件名字 文件名字 就是常见的文件 例如 txt js
  • 关于echarts中南海诸岛的显示问题

    关于echarts中南海诸岛的显示问题 1 china js 文件中 echarts registerMap china 名字要是 china 不能写成 中国 2 echarts 配置中地图名称 mapName china var myCh
  • sequence中实现寄存器前门访问的4种方法

    uvm sequence中实现寄存器访问的方法 在芯片的eda仿真过程中 有的场景需要在发包控制的时候对dut的寄存器进行一些动态配置 这就需要通过寄存器模型来对相关寄存器进行读写操作 小结三种方法如下 通过uvm top这个全局变量来获取
  • django系列 第一节

    一 安装python 安装django 使用虚拟环境 Virtualenv python3的安装方法 http blog csdn net xudailong blog article details 78309857 django的安装方
  • LeetCode(力扣) 312题:戳气球----动态规划求解附带详细注释

    问题描述 有n个气球 编号为 0 到 n 1 每个气球上都标有一个数字 这些数字存在于数组nums中 现在要求你戳破所有的气球 戳破第 i 个气球 你可以获得nums i 1 nums i nums i 1 枚硬币 这里的 i 1 和 i
  • linux给用户添加文件夹的使用权限

    添加权限 将目录 opt 及其下面的所有文件 子目录的文件主改成 liuhai chown R liuhai liuhai opt root localhost sudo chown R oracle home 选项 c或 changes
  • postgresql 服务无法启动,日志中报如下错误

    1 postgresql 服务无法启动 日志中报如下错误 磁盘空间足够 无法找到来自源 PostgreSQL 的事件 ID 0 的描述 本地计算机上未安装引发此事件的组件 或者安装已损坏 可以安装或修复本地计算机上的组件 1 使用pg co
  • 因特网中的电子邮件--应用层协议

    因特网中的电子邮件 因特网中的电子邮件系统主要由三部分组成 用户代理 user agent 邮件服务器 mail server 简单邮件传输协议 Simple Mail Transfer Protocol SMTP 邮件服务器为电子邮件系统
  • matlab计算数据MEA与RMSE误差指标

    MEA Mean Absolute Error 均方差 和RMSE Root Mean Square Error 均方根误差 是两个经常使用的误差评价指标 用于评价模型预测值与真实值之间的误差大如其间的误差 1 MEA 均方差 将预测结果与
  • fastadmin列表自动刷新功能

    在fastadmin框架中 将列表自动刷新给屏蔽了 如果要开启的话 有点麻烦 需要去重新修改框架核心的js代码 然后还需要重新进行编译 在看开发文档的时候 发现列表是存在refresh的方法 既然有这个方法在 那么是否能结合JS的定时器来做
  • 源码追踪,记typeAliasesPackage的使用(ruoyi-cloud中一个疑问的启发)

    首先 提一个思考题 在mapper xml文件中写sql的时候 parameterType指明入参类型的时候 为什么只需要写String Long Integer等 而不用写java lang String java lang Long这样
  • 又一新闻,Meta研发了超越chatGPT的新平台LLAMA

    一 Meta 全新大语言模型 LLaMA 正通过种子公开发放 2 月 24 日 Meta 公司发布了新的大模型系列 LLaMA Large Language Model Meta AI Meta 宣称 LLaMA 规模仅为竞争对手 Chat
  • POST请求错误 net::ERR_EMPTY_RESPONSE

    1 问题 最近在学习使用node js express写后台项目 首先Network发送options 成功 其后的post请求状态一直为pending 在网络上搜索许多方式未能解决 过了一段时间后未响应状态转为failed 2 解决 其状
  • Python:全局替换文件夹下所有文件内容的字符串

    代码参数详解 import os def listFiles dirPath 遍历指定文件夹下打印所有的文件 param dirPath 指定遍历的文件夹路径 return 一个列表 包含指定文件夹下所有的文件绝对路径 准备一个空列表 用来
  • 【Unity】热更新之xLua C#调用Lua / 自定义加载器 / 加载并执行AB包中的Lua文件

    最近在学习xLua 和大家分享一下学习笔记 下载xLua xLua的GitHub下载地址 xLua下载 GitHub 点击进入 点击链接进入后 首先点击Code 再点击Download ZIP把压缩包下载下来 下载完后解压得到xLua ma