XLua只是提供Lua在Unity上运行,并没有提供热更行解决方案。
Lua文件加载
加载字符串
直接使用luaEnv.DoString()
执行一个字符串,字符串必须符合Lua语法
但加载字符串这个方法不常用。
加载Lua文件
用Lua的require函数。
如DoString("require '文件路径(基于Resources文件夹)'")
使用require默认从Resources下进行加载(放Resources下的lua文件得加上txt后缀)。
using UnityEngine;
using XLua;
public class Test : MonoBehaviour {
// 创建一个Lua虚拟机
LuaEnv luaEnv = null;
void Start() {
// 生成了这个虚拟机
luaEnv = new LuaEnv();
// 执行Lua语句
luaEnv.DoString("print('Hello world')");
// 执行byfile(Lua)文件
luaEnv.DoString("require 'byfile' ");
}
// XLua只是提供Lua在Unity上运行,并没有提供热更行解决方案。
void Update() {
if (luaEnv != null)
// 定时清理内存,luaEnv有自己的垃圾回收机制。
luaEnv.Tick();
}
void OnDestroy() {
// 手动释放掉
luaEnv.Dispose();
}
}
自定义加载器
使用require函数只能加载Resources文件下的文件,而Resources无法进行热更新。这时就需要用于自定义加载器。
资源热更新:
- 服务器:制定打包工具、制定打包策略、将需要上传的资源上传到资源服务器。
- 客户端:下载清单文件,对比hash值,一样的话读取本地,不一样下载AB包替换本地资源,并刷新hash值,提供资源管理器,根据资源路径找到对应的AB包,提取AB包中的资源。
逻辑热更新:
- 逻辑热更新依赖于资源热更新,通过资源热更新更新对应的lua脚本内容,在LuaEnv调用之前,用户通过AddLoader添加自定义的逻辑,在自定义的逻辑中使用资源管理器调用AB包中的资源,就能够实现lua逻辑热更新。
using UnityEngine;
using System.Collections;
using XLua;
namespace Tutorial
{
public class CustomLoader : MonoBehaviour
{
LuaEnv luaenv = null;
// Use this for initialization
void Start()
{
luaenv = new LuaEnv();
luaenv.AddLoader((ref string filename) =>
{
if (filename == "InMemory")
{
string script = "return {ccc = 9999}";
return System.Text.Encoding.UTF8.GetBytes(script);
}
return null;
});
luaenv.DoString("print('InMemory.ccc=', require('InMemory').ccc)");
}
// Update is called once per frame
void Update()
{
if (luaenv != null)
{
luaenv.Tick();
}
}
void OnDestroy()
{
luaenv.Dispose();
}
}
}
Lua调用C#脚本逻辑
// C#测试案例
using UnityEngine;
using XLua;
[LuaCallCSharp]
public class Weapon {
public string name = "ailisi_dajian";
}
[LuaCallCSharp]
public class Hero {
// 成员变量
public string name = "ailisi";
// 嵌套成员标量
public Weapon weapon = new Weapon();
public void cheng_yuan_fang_fa() {
Debug.Log("C#:成员方法");
}
public static void jing_tai_fang_fa() {
Debug.Log("C#:静态方法");
}
public string duo_fan_hui_zhi_fang_fa(ref string str) {
return "return";
}
}
// 防止在真机运行时lua不能调用C#
[LuaCallCSharp]
public class Warrior : Hero {
public float Attack = 10;
}
// C#加载Lua文件
using UnityEngine;
using XLua;
public class DOLua : MonoBehaviour {
public TextAsset lua;
public LuaEnv luaEnv = null;
void Start() {
luaEnv = new LuaEnv();
// 使用Xlua默认加载Lua脚本,需要放到Resources下
luaEnv.DoString(lua.text);
}
void Update() {
if (luaEnv != null)
luaEnv.Tick();
}
void OnDestroy() {
luaEnv.Dispose();
}
}
-- Lua调用UnityAPI的时候每次都必须以CS开头,可以先在一个公共类中将频繁调用的类型声明出来
UnityEngine = CS.UnityEngine
GameObject = UnityEngine.GameObject
Transform = UnityEngine.Transform
Debug = UnityEngine.Debug
Hero = CS.Hero
Warrior = CS.Warrior
// Lua调用C#中的逻辑
-- 引入common公共类
require("common")
-- 创建一个GameObject
local obj = GameObject()
-- 改变GameObject名字
obj.name = "LuaCreateObj"
-- 实例化一个角色
local hero = Hero()
-- 输出角色名字
print(hero.name)
-- 输出角色武器名字
print(hero.weapon.name)
-- 使用:调用成员方法
hero:cheng_yuan_fang_fa()
-- 使用.调用静态方法
Hero.jing_tai_fang_fa()
local str ="str"
-- 多返回值成员方法
local a,b = hero:duo_fan_hui_zhi_fang_fa(str)
print(a,b)
-- 实例化一个战士
local warrior = Warrior()
-- 输出继承父类的成员变量
print(warrior.name)
XLua 配置
防止在真机情况下lua不能调用C#逻辑。
-
打标签:用户自定义的类型可以进行打标签,系统api无法进行打标签(该方式方便,但在il2cpp下会增加不少代码,不建议使用)。
[LuaCallCSharp] public class A{ }
-
静态列表:对于没法打标签的类型,这时可以在一个静态类里声明一个静态字段(下面是XLua框架中添加静态列表的脚本)。找到项目中
ExampleGenConfig
文件在里面添加指定的类型即可。 -
动态列表