C# 调用 lua
脚本基本的结构
c#脚本
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using XLua;
using System;
using System.IO;
namespace XLuaTest1
{
[CSharpCallLua]
public class mTable{
public string name;
public int value;
}
[LuaCallCSharp]
public class LuaTest : MonoBehaviour
{
// lua虚拟机,建议全局1个
internal static LuaEnv luaEnv = new LuaEnv(); //all lua behaviour shared one luaenv only!
// 用于处理gc
internal static float lastGCTime = 0;
internal const float GCInterval = 1;//1 second
private LuaTable scriptEnv;
// lua虚拟机与unity相杜英的三个生命周期
private Action luaStart;
private Action luaUpdate;
private Action luaOnDestroy;
void Awake()
{
//初始化全局表
scriptEnv = luaEnv.NewTable();
// 为每个脚本设置一个独立的环境,可一定程度上防止脚本间全局变量、函数冲突
// 初始化本地表
LuaTable meta = luaEnv.NewTable();
// 把lua化境交给本地表
meta.Set("__index", luaEnv.Global);
// 将本地表作为元表,给全局表
scriptEnv.SetMetaTable(meta);
//释放本地表
meta.Dispose();
//------------------------运行脚本
luaEnv.DoString("print(888)");
//绑定lua秀吉的生命周期
Action luaAwake = scriptEnv.Get<Action>("awake");
scriptEnv.Get("start", out luaStart);
scriptEnv.Get("update", out luaUpdate);
scriptEnv.Get("ondestroy", out luaOnDestroy);
if (luaAwake != null)
{
luaAwake();
}
}
// Use this for initialization
void Start()
{
//虚拟机启动后触发
if (luaStart != null)
{
luaStart();
}
}
// Update is called once per frame
void Update()
{
//lua脚本跟随mono每帧执行
if (luaUpdate != null)
{
luaUpdate();
}
//gc相关.清除Lua的未手动释放的LuaBase对象(比如:LuaTable, LuaFunction),以及其它一些事情。
if (Time.time - LuaTest.lastGCTime > GCInterval)
{
luaEnv.Tick();
LuaTest.lastGCTime = Time.time;
}
}
void OnDestroy()
{
// 触发销毁相关动作
if (luaOnDestroy != null)
{
luaOnDestroy();
}
// 释放lua相关内存
luaOnDestroy = null;
luaUpdate = null;
luaStart = null;
scriptEnv.Dispose();
}
}
}
lua脚本
-- unity脚本启动时调用的方法
function start()
print("lua start...")
end
-- 销毁时调用
function ondestroy()
print("lua destroy")
end
c# 调用lua脚本的三种方法
【直接运行代码】
luaEnv.DoString("print(888)");
【运行Resources目录下的lua脚本】
// 直读 Assets/Resources下的lua脚本。比如脚本是test.lua.txt,输入脚本名忽略扩展名txt,即test.lua。
TextAsset luaScript = Resources.Load<TextAsset>("lua.lua") as TextAsset;
luaEnv.DoString(luaScript.text, "", scriptEnv);
【运行任意目录下的lua脚本】
void Start(){
//....lua虚拟机初始化等等....//
//加载脚本loader
luaEnv.AddLoader(LuaTxtLoader);
//传入脚本路径并执行脚本
luaEnv.DoString("require 'Resources/lua.lua.txt'");
// 脚本loader 用于访问任意目录
}
private byte[] LuaTxtLoader(ref string filePath)
{
string luaPath = Application.dataPath + "/" + filePath;
string strLuaContent = File.ReadAllText(luaPath);
byte[] result = System.Text.Encoding.UTF8.GetBytes(strLuaContent);
return result;
}
c#调用lua脚本中的变量
【调用脚本的全局变量】
【c#代码】
// 第二种调用脚本方法 运行Resources下的脚本
TextAsset luaScript = Resources.Load<TextAsset>("lua.lua") as TextAsset;
luaEnv.DoString(luaScript.text, "", scriptEnv);
//获取脚本中的全局变量
int mInt = scriptEnv.Get<int>("gloableInt");
Debug.Log("int from lua script:"+mInt);
【lua代码】
-- 全局变量
gloableInt = 23
调用脚本table中的数据
【lua代码】
-- 全局变量
mTable = {
name = "number",
value = 3
}
mTable1 = {"苍井空", "小泽玛利亚"}
【c#代码:用类映射读取】
//为了调用lua table必须在c#创建相应的结构
public class mTable{
public string name;
public int value;
}
public class luaTest:MonoBehaviour{
void Start(){
// 用mTable类 映射lua脚本的同结构table
mTable mtable = scriptEnv.Get<mTable>("mTable");
Debug.Log("int from lua script:" + mtable.name);
}
}
【c#代码:用Dictionary 映射键值对数据】
void Start(){
// 用Dictionary 映射键值对数据
Dictionary<string, object> dic = luaEnv.Global.Get<Dictionary<string,object>>("mTable");
foreach (string item in dic.Keys)
{
print(item + " " + dic[item]);
}
}
【c#代码:用list映射没有key的table数据】
void Start(){
List<object> list = luaEnv.Global.Get<List<object>>("mTable1");
foreach (var item in list)
{
print(item);
}
}
【c#代码:用LuaTable映射没有key的table数据】
void Start(){
// 使用LuaTable类映射
LuaTable luaTable = luaEnv.Global.Get<LuaTable>("mTable");
print(luaTable.Get<string>("name"));
}
c# 调用lua脚本中的函数
没有参数的全局函数
【c# 代码】
// 用Action接受函数
Action act1 = luaEnv.Global.Get<Action>("func");
// 执行
act1();
// 用完了必须注销,否则无法gc
act1 = null;
【lua 代码】
function func()
print("func");
end
带参数和返回值的全局函数
修改带有【CSharpCallLua】标签的代码后,必须生成xlua代码,否则会发生InvalidCastException的报错
步骤:点击unity工具栏 > xLua > Generate Code
【c# 代码】
// 定义委托 并添加编译标签
[CSharpCallLua]
public delegate int Add(int a, int b);
// 执行委托
Add add = scriptEnv.Get<Add>("add");
Debug.Log("有参的方法返回值:" + add(3, 9));
//用完必须注销
add = null;
【lua 代码】
function add(a,b)
print('luaadd:',a+b);
return a+b;
end
有多个返回值的全局函数(ref or out)
修改带有【CSharpCallLua】标签的代码后,必须生成xlua代码,否则会发生InvalidCastException的报错
步骤:点击unity工具栏 > xLua > Generate Code
【c# 代码】
// 定义委托 并添加编译标签
// lua代码中的方法有2个参数,4个返回值。在c#中声明时都要转成参数。包括2个普通参数,4个out/ref参数
[CSharpCallLua]
public delegate void Add(int x, int y, out int a, out int b, out string s, out int c);
// 获取脚本中的函数
Add add = scriptEnv.Get<Add>("add");
//声明返回变量
int a,b,c;string s;
//执行方法,输入两个参数,返回4个值
add(3, 9, out a, out b, out s, out c) ;
Debug.Log("有参的方法返回值:" + a + "-" + b + "-" + s + "-" + c);
//必须注销,否则无法gc
add = null;
【lua 代码】
--输入2参数,返回4参数 ,在c#的委托中都要处理成输入参数。
function add(a,b)
print('luaadd:',a+b);
return 9,6,'结果:',a+b;
end