xLua  https://github.com/Tencent/xLua

文档  https://tencent.github.io/xLua/public/v1/guide/index.html

FAQ  https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/faq.md

Features  https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/features.md

教程  https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/XLua%E6%95%99%E7%A8%8B.md

Tutorial

using UnityEngine;
using System.Collections;
using XLua; namespace Tutorial
{
public class ByString : MonoBehaviour
{
LuaEnv luaenv = null;
// Use this for initialization
void Start()
{
luaenv = new LuaEnv();
luaenv.DoString("print('hello world')");
} // Update is called once per frame
void Update()
{
if (luaenv != null)
{
luaenv.Tick();
}
} void OnDestroy()
{
luaenv.Dispose();
}
}
}

LoadLuaScriptByString

Resources/byfile.lua.txt

namespace Tutorial
{
public class ByFile : MonoBehaviour
{
LuaEnv luaenv = null;
// Use this for initialization
void Start()
{
luaenv = new LuaEnv();
luaenv.DoString("require 'byfile'");
} // Update is called once per frame
void Update()
{
if (luaenv != null)
{
luaenv.Tick();
}
} void OnDestroy()
{
luaenv.Dispose();
}
}
}

LoadLuaScriptByFile

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();
}
}
}

LoadLuaScriptLoader

using UnityEngine;
using System.Collections.Generic;
using System;
using XLua; public class CSCallLua: MonoBehaviour { LuaEnv luaEnv = null; string script = @"
a = 1
b = 'hello world'
c = true d = {
f1 = 12,
f2 = 34,
1,2,3,
add = function(self, a, b)
print('d.add called')
return a + b
end
} function e()
print('i am e')
end function f(a, b)
print('a', a, 'b', b)
return 1, { f1 = 1024 }
end function ret_e()
print('ret_e called')
return e
end
"; public class DClass {
public int f1;
public int f2;
} [CSharpCallLua]
public interface ItfD {
int f1 { get; set; }
int f2 { get; set; }
int add(int a, int b);
} [CSharpCallLua]
public delegate int FDelegate(int a, string b, out DClass c); [CSharpCallLua]
public delegate Action GetE(); void Start() {
luaEnv = new LuaEnv();
luaEnv.DoString(script); Debug.Log("_G.a = " + luaEnv.Global.Get<int>("a"));
Debug.Log("_G.b = " + luaEnv.Global.Get<string>("b"));
Debug.Log("_G.c = " + luaEnv.Global.Get<bool>("c")); DClass d = luaEnv.Global.Get<DClass>("d"); // 映射到有对应字段的class, by value
Debug.Log("_G.d = { f1 = " + d.f1 + ", f2 = " + d.f2 + " }"); Dictionary<string, double> d1 = luaEnv.Global.Get<Dictionary<string, double>>("d"); // 映射到Dictionary<string, double>, by value
Debug.Log("_G.d = { f1 = " + d1["f1"] + ", f2 = " + d1["f2"] + "}, d.Count = " + d1.Count); List<double> d2 = luaEnv.Global.Get<List<double>>("d"); // 映射到List<double>, by value
Debug.Log("_G.d.len = " + d2.Count); ItfD d3 = luaEnv.Global.Get<ItfD>("d"); // 映射到interface实例,by ref, 这个要求interface加到生成列表,否则会返回null,建议用法
d3.f2 = ;
Debug.Log("_G.d= { f1 = " + d3.f1 + ", f2 = " + d3.f2 + "}");
Debug.Log("_G.d:add(1, 2) = " + d3.add(, )); LuaTable d4 = luaEnv.Global.Get<LuaTable>("d"); // 映射到一个delegate, 要求delegate加到生成列表,否则返回null,建议用法
Debug.Log("_G.d = { f1 = " + d4.Get<int>("f1") + ", f2 = " + d4.Get<int>("f2") + "}"); Action e = luaEnv.Global.Get<Action>("e"); // 映射到一个delegate,要求delegate加到生成列表,否则返回null, 建议用法
e(); FDelegate f = luaEnv.Global.Get<FDelegate>("f");
DClass d_ret;
int f_ret = f(, "john", out d_ret); // lua的多返回值映射: 从左往右映射到c#的输出参数,输出参数包括返回值,out参数,ref参数
Debug.Log("ret.d = { f1 = " + d_ret.f1 + ", f2 = " + d_ret.f2 + "}, ret = " + f_ret); GetE ret_e = luaEnv.Global.Get<GetE>("ret_e"); // delegate可以返回更复杂的类型,甚至是另外一个delegate
e = ret_e();
e(); LuaFunction d_e = luaEnv.Global.Get<LuaFunction>("e");
d_e.Call();
} void Update() {
if (luaEnv != null) {
luaEnv.Tick();
}
} void OnDestroy() {
luaEnv.Dispose();
}
}

CSharpCallLua

using UnityEngine;
using System;
using XLua; [LuaCallCSharp]
public class BaseClass { public static int BSF = ; public int BMF { get; set; } public static void BSFunc() {
Debug.Log("Derived Static Func, BSF = " + BSF);
} public void BMFunc() {
Debug.Log("Derived Member Func, BMF = " + BMF);
}
} public struct Param1 {
public int x;
public string y;
} [LuaCallCSharp]
public enum TestEnum {
E1,
E2
} [LuaCallCSharp]
public class DerivedClass: BaseClass { [LuaCallCSharp]
public enum TestEnumInner {
E3,
E4
} public void DMFunc() {
Debug.Log("Derived Member Func, DMF = " + DMF);
} public int DMF { get; set; } public double ComplexFunc(Param1 p1, ref int p2, out string p3, Action luafunc, out Action csfunc) {
Debug.Log("P1 = { x = " + p1.x + ", y = " + p1.y + "},p2 = " + p2); luafunc();
p2 = p2 * p1.x;
p3 = "hello " + p1.y; csfunc = () => {
Debug.Log("csharp callback invoked!");
}; return 1.23;
} public void TestFunc(int i) {
Debug.Log("TestFunc(int i)");
} public void TestFunc(string i) {
Debug.Log("TestFunc(string i)");
} public static DerivedClass operator+(DerivedClass a, DerivedClass b) {
DerivedClass ret = new DerivedClass();
ret.DMF = a.DMF + b.DMF;
return ret;
} public void DefaultValueFunc(int a = , string b = "cccc", string c = null) {
UnityEngine.Debug.Log("DefaultValueFunc: a = " + a + ", b = " + b + ", c = " + c);
} public void VariableParamsFunc(int a, params string[] strs) {
UnityEngine.Debug.Log("VariableParamsFunc: a = " + a);
foreach (var str in strs) {
UnityEngine.Debug.Log("str:" + str);
}
} public TestEnum EnumTestFunc(TestEnum e) {
Debug.Log("EnumTestFunc: e = " + e);
return TestEnum.E2;
} public Action<string> TestDelegate = (param) => {
Debug.Log("TestDelegate in C#:" + param);
}; public event Action TestEvent; public void CallEvent() {
TestEvent();
} public ulong TestLong(long n) {
return (ulong)(n + );
} class InnerCalc: ICalc {
public int add(int a, int b) {
return a + b;
} public int id = ;
} public ICalc GetCalc() {
return new InnerCalc();
} public void GenericMethod<T>() {
Debug.Log("GenericMethod<" + typeof(T) +">");
}
} [LuaCallCSharp]
public interface ICalc {
int add(int a, int b);
} [LuaCallCSharp]
public static class DerivedClassExtensions {
public static int GetSomeData(this DerivedClass obj) {
Debug.Log("GetSomeData ret = " + obj.DMF);
return obj.DMF;
} public static int GetSomeBaseData(this BaseClass obj) {
Debug.Log("GetSomeBaseData ret = " + obj.BMF);
return obj.BMF;
} public static void GenericMethodOfString(this DerivedClass obj) {
obj.GenericMethod<string>();
}
} public class LuaCallCs1 : MonoBehaviour { LuaEnv luaEnv = null;
string script = @"
function demo()
--new C#对象
local newGameObj = CS.UnityEngine.GameObject()
local newGameObj2 = CS.UnityEngine.GameObject('helloworld')
print(newGameObj, newGameObj2) --访问静态属性,方法
local GameObject = CS.UnityEngine.GameObject
print('UnityEngine.Time.deltaTime:', CS.UnityEngine.Time.deltaTime) --读静态属性
CS.UnityEngine.Time.timeScale = 0.5 --写静态属性
print('helloworld', GameObject.Find('helloworld')) --静态方法调用 --访问成员属性,方法
local DerivedClass = CS.DerivedClass
local testobj = DerivedClass()
testobj.DMF = 1024--设置成员属性
print(testobj.DMF)--读取成员属性
testobj:DMFunc()--成员方法 --基类属性,方法
print(DerivedClass.BSF)--读基类静态属性
DerivedClass.BSF = 2048--写基类静态属性
DerivedClass.BSFunc();--基类静态方法
print(testobj.BMF)--读基类成员属性
testobj.BMF = 4096--写基类成员属性
testobj:BMFunc()--基类方法调用 --复杂方法调用
local ret, p2, p3, csfunc = testobj:ComplexFunc({x=3, y = 'john'}, 100, function()
print('i am lua callback')
end)
print('ComplexFunc ret:', ret, p2, p3, csfunc)
csfunc() --重载方法调用
testobj:TestFunc(100)
testobj:TestFunc('hello') --操作符
local testobj2 = DerivedClass()
testobj2.DMF = 2048
print('(testobj + testobj2).DMF = ', (testobj + testobj2).DMF) --默认值
testobj:DefaultValueFunc(1)
testobj:DefaultValueFunc(3, 'hello', 'john') --可变参数
testobj:VariableParamsFunc(5, 'hello', 'john') --Extension methods
print(testobj:GetSomeData())
print(testobj:GetSomeBaseData()) --访问基类的Extension methods
testobj:GenericMethodOfString() --通过Extension methods实现访问泛化方法 --枚举类型
local e = testobj:EnumTestFunc(CS.TestEnum.E1)
print(e, e == CS.TestEnum.E2)
print(CS.TestEnum.__CastFrom(1), CS.TestEnum.__CastFrom('E1'))
print(CS.DerivedClass.TestEnumInner.E3)
assert(CS.BaseClass.TestEnumInner == nil) --Delegate
testobj.TestDelegate('hello') --直接调用
local function lua_delegate(str)
print('TestDelegate in lua:', str)
end
testobj.TestDelegate = lua_delegate + testobj.TestDelegate --combine,这里演示的是C#delegate作为右值,左值也支持
testobj.TestDelegate('hello')
testobj.TestDelegate = testobj.TestDelegate - lua_delegate --remove
testobj.TestDelegate('hello') --事件
local function lua_event_callback1() print('lua_event_callback1') end
local function lua_event_callback2() print('lua_event_callback2') end
testobj:TestEvent('+', lua_event_callback1)
testobj:CallEvent()
testobj:TestEvent('+', lua_event_callback2)
testobj:CallEvent()
testobj:TestEvent('-', lua_event_callback1)
testobj:CallEvent()
testobj:TestEvent('-', lua_event_callback2) --64位支持
local l = testobj:TestLong(11)
print(type(l), l, l + 100, 10000 + l) --typeof
newGameObj:AddComponent(typeof(CS.UnityEngine.ParticleSystem)) --cast
local calc = testobj:GetCalc()
print('assess instance of InnerCalc via reflection', calc:add(1, 2))
assert(calc.id == 100)
cast(calc, typeof(CS.ICalc))
print('cast to interface ICalc', calc:add(1, 2))
assert(calc.id == nil)
end demo() --协程下使用
local co = coroutine.create(function()
print('------------------------------------------------------')
demo()
end)
assert(coroutine.resume(co))
"; void Start() {
luaEnv = new LuaEnv();
luaEnv.DoString(script);
} void Update() {
if (luaEnv != null) {
luaEnv.Tick();
}
} void OnDestroy() {
luaEnv.Dispose();
}
}

LuaCallCs

Examples

using UnityEngine;
using XLua; public class Helloworld : MonoBehaviour
{
// Use this for initialization
void Start()
{
LuaEnv luaenv = new LuaEnv();
luaenv.DoString("CS.UnityEngine.Debug.Log('hello world')");
luaenv.Dispose();
} // Update is called once per frame
void Update()
{ }
}

01_HelloWorld 快速入门的例子

LuaTestScript.lua.txt

local speed =
local lightCpnt = nil function start()
print("lua start...")
print("injected object", lightObject)
lightCpnt = lightObject:GetComponent(typeof(CS.UnityEngine.Light))
end function update()
local r = CS.UnityEngine.Vector3.up * CS.UnityEngine.Time.deltaTime * speed
self.transform:Rotate(r)
lightCpnt.color = CS.UnityEngine.Color(CS.UnityEngine.Mathf.Sin(CS.UnityEngine.Time.time) / + 0.5, , , )
end function ondestroy()
print("lua destory")
end LuaBehaviour.cs using UnityEngine;
using XLua;
using System; [System.Serializable]
public class Injection {
public string name;
public GameObject value;
} [LuaCallCSharp]
public class LuaBehaviour : MonoBehaviour { public TextAsset luaScript;
public Injection[] injections; internal static LuaEnv luaEnv = new LuaEnv(); // all lua behaviour shared one luaenv only!
internal static float lastGCTime = ;
internal const float GCInterval = ; //1 second private Action luaStart;
private Action luaUpdate;
private Action luaOnDestroy; private LuaTable scriptEnv; void Awake() {
scriptEnv = luaEnv.NewTable(); // 为每个脚本设置一个独立的环境,可一定程度上防止脚本间全局变量,函数冲突
LuaTable meta = luaEnv.NewTable();
meta.Set("__index", luaEnv.Global);
scriptEnv.SetMetaTable(meta);
meta.Dispose(); scriptEnv.Set("self", this);
foreach (var injection in injections) {
scriptEnv.Set(injection.name, injection.value);
} luaEnv.DoString(luaScript.text, "LuaTestScript", scriptEnv); 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();
}
} void Start() {
if (luaStart != null) {
luaStart();
}
} void Update() {
if (luaUpdate != null) {
luaUpdate();
} if (Time.time - LuaBehaviour.lastGCTime > GCInterval) {
luaEnv.Tick();
LuaBehaviour.lastGCTime = Time.time;
} } void OnDestroy() {
if (luaOnDestroy != null) {
luaOnDestroy();
} luaOnDestroy = null;
luaUpdate = null;
luaStart = null;
scriptEnv.Dispose();
injections = null;
}
}

02_U3DScripting 怎么用lua来写MonoBehaviour

ButtonInteraction.lua.txt

function start()
print("lua start...") self:GetComponent("Button").onClick:AddListener(function()
print("clicked, you input is '" ..input:GetComponent("InputField").text .."'")
end)
end LuaBehaviour.cs using UnityEngine;
using XLua;
using System; [System.Serializable]
public class Injection
{
public string name;
public GameObject value;
} [LuaCallCSharp]
public class LuaBehaviour : MonoBehaviour
{
public TextAsset luaScript;
public Injection[] injections; internal static LuaEnv luaEnv = new LuaEnv(); //all lua behaviour shared one luaenv only!
internal static float lastGCTime = ;
internal const float GCInterval = ;//1 second private Action luaStart;
private Action luaUpdate;
private Action luaOnDestroy; private LuaTable scriptEnv; void Awake()
{
scriptEnv = luaEnv.NewTable(); // 为每个脚本设置一个独立的环境,可一定程度上防止脚本间全局变量、函数冲突
LuaTable meta = luaEnv.NewTable();
meta.Set("__index", luaEnv.Global);
scriptEnv.SetMetaTable(meta);
meta.Dispose(); scriptEnv.Set("self", this);
foreach (var injection in injections)
{
scriptEnv.Set(injection.name, injection.value);
} luaEnv.DoString(luaScript.text, "LuaTestScript", scriptEnv); 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()
{
if (luaUpdate != null)
{
luaUpdate();
}
if (Time.time - LuaBehaviour.lastGCTime > GCInterval)
{
luaEnv.Tick();
LuaBehaviour.lastGCTime = Time.time;
}
} void OnDestroy()
{
if (luaOnDestroy != null)
{
luaOnDestroy();
}
luaOnDestroy = null;
luaUpdate = null;
luaStart = null;
scriptEnv.Dispose();
injections = null;
}
}

03_UIEvent 怎么用UI来写UI逻辑

/*
* Tencent is pleased to support the open source community by making xLua available.
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/ using System;
using UnityEngine;
using XLua; namespace XLuaTest
{
public class PropertyChangedEventArgs : EventArgs
{
public string name;
public object value;
} public class InvokeLua : MonoBehaviour
{
[CSharpCallLua]
public interface ICalc
{
event EventHandler<PropertyChangedEventArgs> PropertyChanged; int Add(int a, int b);
int Mult { get; set; } object this[int index] { get; set; }
} [CSharpCallLua]
public delegate ICalc CalcNew(int mult, params string[] args); private string script = @"
local calc_mt = {
__index = {
Add = function(self, a, b)
return (a + b) * self.Mult
end, get_Item = function(self, index)
return self.list[index + 1]
end, set_Item = function(self, index, value)
self.list[index + 1] = value
self:notify({name = index, value = value})
end, add_PropertyChanged = function(self, delegate)
if self.notifylist == nil then
self.notifylist = {}
end
table.insert(self.notifylist, delegate)
print('add',delegate)
end, remove_PropertyChanged = function(self, delegate)
for i=1, #self.notifylist do
if CS.System.Object.Equals(self.notifylist[i], delegate) then
table.remove(self.notifylist, i)
break
end
end
print('remove', delegate)
end, notify = function(self, evt)
if self.notifylist ~= nil then
for i=1, #self.notifylist do
self.notifylist[i](self, evt)
end
end
end,
}
} Calc = {
New = function (mult, ...)
print(...)
return setmetatable({Mult = mult, list = {'aaaa','bbbb','cccc'}}, calc_mt)
end
}
";
// Use this for initialization
void Start()
{
LuaEnv luaenv = new LuaEnv();
Test(luaenv);//调用了带可变参数的delegate,函数结束都不会释放delegate,即使置空并调用GC
luaenv.Dispose();
} void Test(LuaEnv luaenv)
{
luaenv.DoString(script);
CalcNew calc_new = luaenv.Global.GetInPath<CalcNew>("Calc.New");
ICalc calc = calc_new(, "hi", "john"); //constructor
Debug.Log("sum(*10) =" + calc.Add(, ));
calc.Mult = ;
Debug.Log("sum(*100)=" + calc.Add(, )); Debug.Log("list[0]=" + calc[]);
Debug.Log("list[1]=" + calc[]); calc.PropertyChanged += Notify;
calc[] = "dddd";
Debug.Log("list[1]=" + calc[]); calc.PropertyChanged -= Notify; calc[] = "eeee";
Debug.Log("list[1]=" + calc[]);
} void Notify(object sender, PropertyChangedEventArgs e)
{
Debug.Log(string.Format("{0} has property changed {1}={2}", sender, e.name, e.value));
} // Update is called once per frame
void Update()
{ }
}
}

04_LuaObjectOrented: lua面向对象和C#的配合

using UnityEngine;
using System;
using XLua; namespace XLuaTest
{
[GCOptimize]
[LuaCallCSharp]
public struct Pedding
{
public byte c;
} [GCOptimize]
[LuaCallCSharp]
public struct MyStruct
{
public MyStruct(int p1, int p2)
{
a = p1;
b = p2;
c = p2;
e.c = (byte)p1;
}
public int a;
public int b;
public decimal c;
public Pedding e;
} [LuaCallCSharp]
public enum MyEnum
{
E1,
E2
} [CSharpCallLua]
public delegate int IntParam(int p); [CSharpCallLua]
public delegate Vector3 Vector3Param(Vector3 p); [CSharpCallLua]
public delegate MyStruct CustomValueTypeParam(MyStruct p); [CSharpCallLua]
public delegate MyEnum EnumParam(MyEnum p); [CSharpCallLua]
public delegate decimal DecimalParam(decimal p); [CSharpCallLua]
public delegate void ArrayAccess(Array arr); [CSharpCallLua]
public interface IExchanger
{
void exchange(Array arr);
} [LuaCallCSharp]
public class NoGc : MonoBehaviour
{
LuaEnv luaenv = new LuaEnv(); IntParam f1;
Vector3Param f2;
CustomValueTypeParam f3;
EnumParam f4;
DecimalParam f5; ArrayAccess farr;
Action flua;
IExchanger ie;
LuaFunction add; [NonSerialized]
public double[] a1 = new double[] { , };
[NonSerialized]
public Vector3[] a2 = new Vector3[] { new Vector3(, , ), new Vector3(, , ) };
[NonSerialized]
public MyStruct[] a3 = new MyStruct[] { new MyStruct(, ), new MyStruct(, ) };
[NonSerialized]
public MyEnum[] a4 = new MyEnum[] { MyEnum.E1, MyEnum.E2 };
[NonSerialized]
public decimal[] a5 = new decimal[] { 1.00001M, 2.00002M }; public float FloatParamMethod(float p)
{
return p;
} public Vector3 Vector3ParamMethod(Vector3 p)
{
return p;
} public MyStruct StructParamMethod(MyStruct p)
{
return p;
} public MyEnum EnumParamMethod(MyEnum p)
{
return p;
} public decimal DecimalParamMethod(decimal p)
{
return p;
} // Use this for initialization
void Start()
{
luaenv.DoString(@"
function id(...)
return ...
end function add(a, b) return a + b end function array_exchange(arr)
arr[0], arr[1] = arr[1], arr[0]
end local v3 = CS.UnityEngine.Vector3(7, 8, 9)
local vt = CS.XLuaTest.MyStruct(5, 6) function lua_access_csharp()
monoBehaviour:FloatParamMethod(123) --primitive
monoBehaviour:Vector3ParamMethod(v3) --vector3
local rnd = math.random(1, 100)
local r = monoBehaviour:Vector3ParamMethod({x = 1, y = 2, z = rnd}) --vector3
assert(r.x == 1 and r.y == 2 and r.z == rnd)
monoBehaviour:StructParamMethod(vt) --custom struct
r = monoBehaviour:StructParamMethod({a = 1, b = rnd, e = {c = rnd}})
assert(r.b == rnd and r.e.c == rnd)
monoBehaviour:EnumParamMethod(CS.XLuaTest.MyEnum.E2) --enum
monoBehaviour:DecimalParamMethod(monoBehaviour.a5[0])
monoBehaviour.a1[0], monoBehaviour.a1[1] = monoBehaviour.a1[1], monoBehaviour.a1[0] -- field
end exchanger = {
exchange = function(self, arr)
array_exchange(arr)
end
} A = { B = { C = 789}}
GDATA = 1234;
"); luaenv.Global.Set("monoBehaviour", this); luaenv.Global.Get("id", out f1);
luaenv.Global.Get("id", out f2);
luaenv.Global.Get("id", out f3);
luaenv.Global.Get("id", out f4);
luaenv.Global.Get("id", out f5); luaenv.Global.Get("array_exchange", out farr);
luaenv.Global.Get("lua_access_csharp", out flua);
luaenv.Global.Get("exchanger", out ie);
luaenv.Global.Get("add", out add); luaenv.Global.Set("g_int", );
luaenv.Global.Set(, );
int i;
luaenv.Global.Get("g_int", out i);
Debug.Log("g_int:" + i);
luaenv.Global.Get(, out i);
Debug.Log("123:" + i);
} // Update is called once per frame
void Update()
{
// c# call lua function with value type but no gc (using delegate)
f1(); // primitive type
f2(new Vector3(, , )); // vector3
MyStruct mystruct1 = new MyStruct(, );
f3(mystruct1); // custom complex value type
f4(MyEnum.E1); //enum
decimal dec1 = -32132143143100109.00010001010M;
f5(dec1); //decimal // using LuaFunction.Func<T1, T2, TResult>
add.Func<int, int, int>(, ); // LuaFunction.Func<T1, T2, TResult> // lua access c# value type array no gc
farr(a1); //primitive value type array
farr(a2); //vector3 array
farr(a3); //custom struct array
farr(a4); //enum arry
farr(a5); //decimal arry // lua call c# no gc with value type
flua(); //c# call lua using interface
ie.exchange(a2); //no gc LuaTable use
luaenv.Global.Set("g_int", );
int i;
luaenv.Global.Get("g_int", out i); luaenv.Global.Set(123.0001, mystruct1);
MyStruct mystruct2;
luaenv.Global.Get(123.0001, out mystruct2); decimal dec2 = 0.0000001M;
luaenv.Global.Set((byte), dec1);
luaenv.Global.Get((byte), out dec2); int gdata = luaenv.Global.Get<int>("GDATA");
luaenv.Global.SetInPath("GDATA", gdata + ); int abc = luaenv.Global.GetInPath<int>("A.B.C");
luaenv.Global.SetInPath("A.B.C", abc + ); luaenv.Tick();
} void OnDestroy()
{
f1 = null;
f2 = null;
f3 = null;
f4 = null;
f5 = null;
farr = null;
flua = null;
ie = null;
add = null;
luaenv.Dispose();
}
}
}

05_NoGc: 怎么去避免值类型的GC

CoroutineTest.cs

using UnityEngine;
using XLua; namespace XLuaTest
{
public class CoroutineTest : MonoBehaviour
{
LuaEnv luaenv = null;
// Use this for initialization
void Start()
{
luaenv = new LuaEnv();
luaenv.DoString("require 'coruntine_test'");
} // Update is called once per frame
void Update()
{
if (luaenv != null)
{
luaenv.Tick();
}
} void OnDestroy()
{
luaenv.Dispose();
}
}
} coruntine_test.lua local cs_coroutine = (require 'cs_coroutine') local a = cs_coroutine.start(function()
print('coroutine a started') coroutine.yield(cs_coroutine.start(function()
print('coroutine b stated inside cotoutine a')
coroutine.yield(CS.UnityEngine.WaitForSeconds())
print('i am coroutine b')
end))
print('coroutine b finish') while true do
coroutine.yield(CS.UnityEngine.WaitForSeconds())
print('i am coroutine a')
end
end) cs_coroutine.start(function()
print('stop coroutine a after 5 seconds')
coroutine.yield(CS.UnityEngine.WaitForSeconds())
cs_coroutine.stop(a)
print('coroutine a stoped')
end) cs_coroutine.lua local util = require 'xlua.util' local gameobject = CS.UnityEngine.GameObject('Coroutine_Runner')
CS.UnityEngine.Object.DontDestroyOnLoad(gameobject)
local cs_coroutine_runner = gameobject:AddComponent(typeof(CS.XLuaTest.Coroutine_Runner)) return {
start = function(...)
return cs_coroutine_runner:StartCoroutine(util.cs_generator(...))
end; stop = function(coroutine)
cs_coroutine_runner:StopCoroutine(coroutine)
end
} Coroutine_Runner.cs using UnityEngine;
using XLua;
using System.Collections.Generic;
using System.Collections;
using System; namespace XLuaTest
{
public class Coroutine_Runner : MonoBehaviour
{
} public static class CoroutineConfig
{
[LuaCallCSharp]
public static List<Type> LuaCallCSharp
{
get
{
return new List<Type>()
{
typeof(WaitForSeconds),
typeof(WWW)
};
}
}
}
}

06_Coroutine: lua协程怎么和Unity协程相配合

相关文章

腾讯开源手游热更新方案:Unity3D下的XLua方案介绍

xLua 学习的更多相关文章

  1. 热更新解决方案--xlua学习笔记

    一.热更新方案简介 在Unity游戏工程中,C#代码(编译型语言)资源和Resources文件夹下的资源打包后都不可以更改,因此这部分内容不能进行热更新,而lua代码(解释型语言)逻辑不需要进行预编译 ...

  2. XLua系统学习

    官方网站:https://github.com/Tencent/xLua 学习手册:http://manual.luaer.cn/ 技术博客: http://blog.csdn.net/column/ ...

  3. 热更新应用--热补丁Hotfix学习笔记

    一.热补丁简介 热补丁主要是用于将纯C#工程在不重做的情况下通过打补丁的形式改造成具备lua热更新功能工程,主要是让原来脚本中Start函数和Update函数等函数代码块重定向到lua代码. 二.第一 ...

  4. Unity3D学习笔记(三十二):Xlua(2)

    Xlua支持通过子类对象访问父类的变量属性和方法   对于C#的ref,out参数的方法 当调用的时候:out类型的参数是不需要传递实参的,普通的参数和ref参数需要传递实参. out,ref传出值通 ...

  5. Unity3D学习笔记(三十一):Xlua(1)

    Xlua:腾讯研发,开源免费   配置:文件解压,拷贝到Unity项目里 注意:Xlua文件夹不许移动,不许重命名   运行Xlua: 1.引用命名空间 2.创建虚拟机 3.运行lua语句 4.不需要 ...

  6. Unity XLua 官方教程学习

    一.Lua 文件加载 1. 执行字符串 using UnityEngine; using XLua; public class ByString : MonoBehaviour { LuaEnv lu ...

  7. Unity XLua 官方案例学习

    1. Helloworld using UnityEngine; using XLua; public class Helloworld : MonoBehaviour { // Use this f ...

  8. Unity的学习笔记(XLua的初学用法并在lua中使用unity周期函数)

    自己最近也在研究怎么用lua控制UI,然后看着网上介绍,决定选用XLua,毕竟TX爸爸出的,有人维护,自己琢磨着怎么用,于是弄出来一个能用的作为记录. 当然,XLua主要是用于热更新,我自己是拿来尝试 ...

  9. 基于xlua和mvvm的unity框架

    1.框架简介 这两天在Github上发现了xlua的作者车雄生前辈开源的一个框架—XUUI,于是下载下来学习了一下.XUUI基于xlua,又借鉴了mvvm的设计概念.xlua是目前很火的unity热更 ...

随机推荐

  1. Noip2017Day1T3 逛公园

    题目链接 problem 一个有向无重边自环图,设\(D\)为从\(1\)号点走到\(n\)号点的最短距离.问有多少条从\(1\)到\(n\)的路径长度不超过\(D+K\).\(K\)为给定的值,且\ ...

  2. python--各种锁机制归纳整理

    Q:为什么要用锁?什么样的业务场景下需要用锁? 就拿之前的工单系统来说,当审批方式为角色组审批时,代表该角色组内任意一人审批即可,这时,该角色组内成员的系统上都是可以显示审批按钮,如果此时A审批员和B ...

  3. MySQL中使用group_concat遇到的坑

    在使用group_concat的过程中遇到个问题,这里记录一下:在MySQL中有个配置参数group_concat_max_len,它会限制使用group_concat返回的最大字符串长度,默认是10 ...

  4. SQL语句--查找数据select

    查看全部数据库表参照地址:https://www.cnblogs.com/zhoulixiangblog/p/12078724.html 本文所用数据库表: prod_id vend_id prod_ ...

  5. 05Shell循环语句

    循环语句 for 语法结构 for 变量名 [ in 取值列表 ] do 循环体 done 注意 当for对文件内容进行逐行处理时,会忽略空行 示例 例1 ping 主机的脚本(初始版):缺点执行过程 ...

  6. JAVA 十六进制和十进制、二进制转换

    java十六进制和十进制.二进制转换 十进制转化成十六进制 Integer x = 100; hex = x.toHexString(x); 十六进制转化成十进制 Integer.parseInt(h ...

  7. 愉快地使用Groovy Shell

    这是一篇有关Groovy Shell的帖子,以及它如何在日常工作中为您提供帮助(只要您是软件开发人员).无论您使用哪种编程语言或技术,都可以从Groovy Shell中受益.唯一真正的要求是您能够编写 ...

  8. Spring中ApplicationListener的使用

    背景 ApplicationListener是Spring事件机制的一部分,与抽象类ApplicationEvent类配合来完成ApplicationContext的事件机制. 如果容器中存在Appl ...

  9. LOAD_DLL_DEBUG_EVENT 时读取 DllName

    这句话是说 lpImageName 和 hFile 存在关联(associated),不是一定指向! 继续读后面那句,“这个数字可能为NULL,或者包含着被调试进程空间中的一个字符串地址.这个地址,相 ...

  10. wpf file embeded resource is readonly,Copy always will copy the file and its folder to the bin folder

    Wpf file embeded resource will compile the file into the assembly and it will be readonly and can no ...