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