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. Python解释器和Python集成环境小结

    目录 一.执行Python程序的两种方式 1.1 交互式 1.2 命令行式 二.执行Python程序的两种IDE 2.1 Pycharm 2.2 Jupyter 一.执行Python程序的两种方式 1 ...

  2. es6一句话拾遗

    Symbol最大的作用就是用于消除魔术字符串: Set跟数组的最大区别,就是Set的成员都是唯一的,没有重复:(方法:add(value),has,delete,clear) Map跟对象的最大区别, ...

  3. linux 主机通过虚拟机(win10)上网

    公司内网必须安装安全软件(exe)才可以上网,但是我的系统是deepin,用deepin-wine无法安软该exe,于是用vmware安装了win10虚拟机,通过虚拟机上网 先简单介绍下vmware以 ...

  4. 关于js里的那一堆事件

    分类 事件名 触发描述 一般事件 onclick 鼠标点击事件 ondbclick 鼠标双击事件 onmousedown/up 鼠标按下/松开事件 onmouseover/move/out 鼠标悬浮/ ...

  5. 使用HTMLTestRunner模块更优美地展示接口测试报告

    优化版本的HTMLTestRunner模块,从我的百度网盘获取: 链接:https://pan.baidu.com/s/1f8eLpX5qBrpJsVlXKjquRQ 提取码:qqlu 测试报告展示: ...

  6. Docker容器 MySQL中文乱码解决方案

    docker exec进入容器 sudo docker exec -it 588340b778f6 bash 执行以下命令,将 character-set-server=utf8 写入mysql配置文 ...

  7. oidc hybrid flow 与另外两种模式的异同

    很多学习identityserver的文章都没有解释清楚oidc hybrid混合模式的含义.本文将解释hybrid模式与另外两种模式的主要区别. 我们先看一下一手文档: https://openid ...

  8. python执行shell实时输出

    1.使用readline可以实现 import subprocess def run_shell(shell): cmd = subprocess.Popen(shell, stdin=subproc ...

  9. MySQL的基本概念和数据操作

    1.连接服务器 数据库是CS模式的软件,所以要连接数据库必须要有客户端软件.MySQL数据库默认端口号是3306         1.1window界面连接服务器         1.2通过web窗体 ...

  10. 清新水墨色中国风通用教育培训课件PPT模板

    模板来源:http://ppt.dede58.com/jiaoxuekejian/26220.html