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实现-桥接模式

    桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化. 下面是一个桥接模式的demo: #!/usr/bin/env python # -*- coding: ...

  2. Linux 部署vue项目(使用nginx)

    1.部署Nginx 请参考Linux下部署nginx,此处不再重复 2.Vue项目打包 # 打包正式环境 npm run build:prod # 打包预发布环境 npm run build:stag ...

  3. 《细说PHP》第四版 样章 第23章 自定义PHP接口规范 1

    如今的项目开发中,接口是很普遍的应用技术.现在好多项目组都单独设有接口开发人员.像腾讯.微博.淘宝等开放平台,其所谓的开放,就是提供一些可调用的接口,用于获取相关的信息.例如,微信用户基本信息.淘宝店 ...

  4. linux的vi编辑器常用用法一览

    vi 命令用于编辑文本文件,语法: vi 文件名 vi 是一个比较强大的编辑工具,类似于windows下的notepad,但是功能要强大的多.vi分为三种模式,分别是“一般模式”,“编辑模式”,“命令 ...

  5. Java-100天知识进阶-Java内存-知识铺(四)

    知识铺: 致力于打造轻知识点,持续更新每次的知识点较少,阅读不累.不占太多时间,不停的来唤醒你记忆深处的知识点. 1.Java内存模型是每个java程序员必须掌握理解的 2.Java内存模型的主要目标 ...

  6. 黄聪:微信小程序 服务器 TLS1.0 1TLS.2 配置详细教学!

    下载IISCrypto.exe 点击best 工具自动推荐选中 也可以定义勾选 选择配置完成 然后点击”apply“ 软件弹窗提醒你 手动重启服务器!!!重启服务器 搞定! 最后 https://ww ...

  7. java中的常用类(二)

    java中的常用类(二) Math类 Math类的声明:public final class Math extends Object Math类是与数学计算有关的类,里面的方法都是静态方法,直接使用类 ...

  8. requests库的使用、安装及方法的简单介绍

    requests库的使用.安装及方法的简单介绍 1.requests库的概述 requests库是一个简洁且简单的处理HTTP请求的第三方库,是公认的最好获得第三方信息的库. requests库更多信 ...

  9. Koa 提交和接收 JSON 表单数据

    来自 url 中的 query 参数可直接通过 context.query 获取,但 POST 方式提交的表单数据则需要借助中间件的解析来完成,比如 koa-bodyparser. 首先准备好一个表单 ...

  10. C#上手练习7(构造方法语句)

    创建类的对象是使用“类名 对象名 = new 类名()”的方式来实现的. 实际上,“类名()”的形式调用的是类的构造方法,也就是说构造方法的名字是与类的名称相同的. 构造方法的定义语法形式如下. 访问 ...