柚子快報激活碼778899分享:Lua調用C#
柚子快報激活碼778899分享:Lua調用C#
?Lua沒有辦法直接訪問C#,一定是先從C#調用Lua后
才把核心邏輯交給Lua來編輯
Lua使用C#類
Main.cs:
public class Main : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
LuaMgr.GetInstance().Init();
LuaMgr.GetInstance().DoLuaFile("Main");
}
// Update is called once per frame
void Update()
{
}
}
LuaCallCSharp.cs
public class Test
{
public void Speak(string str)
{
Debug.Log("Test1" + str);
}
}
namespace MrTang
{
public class Test2
{
public void Speak(string str)
{
Debug.Log("Test2" + str);
}
}
}
public class LuaCallCSharp : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
Main.lua:
print("主Lua啟動")
--Unity中寫lua執(zhí)行
--xlua幫我們處理
--只要使執(zhí)行l(wèi)ua腳本 都會自動進入重定向函數(shù)中找文件
--require("Test")
require("Lesson1_CallClass")
Lesson1_CallClass.lua
print("*************Lua調用C#類相關知識點***************")
--lua中使用c#的類的固定套路
--CS.命名空間.類名
--Unity的類 比如GameObject Transform 都再UnityEngine命名空間下 —— CS.UnityEngine.類名
--例如 CS.UnityEngine.GameObject
--通過C#中的類 實例化一個對象 lua中沒有new 所以我們直接類名括號就是實例化對象
--默認調用無參構造
local obj1 = CS.UnityEngine.GameObject()
local obj2 = CS.UnityEngine.GameObject("Test")
--為了方便使用和節(jié)省性能 定義全局變量存儲 C#中的類
GameObject = CS.UnityEngine.GameObject
local obj3 = GameObject("Test2")
--類中的靜態(tài)對象 可以直接使用.來調用
local obj4 = GameObject.Find("Test")
--得到對象中的成員變量 直接對象.即可
print(obj4.transform.position)
Debug = CS.UnityEngine.Debug
Debug.Log(obj4.transform.position)
Vector3 = CS.UnityEngine.Vector3
--如果使用對象中的成員方法 一定要加:
obj4.transform:Translate(Vector3.right)
Debug.Log(obj4.transform.position)
--自定義類使用方法相同 只是命名空間不同
local t = CS.Test()
t:Speak("test說話")
local t2 = CS.MrTang.Test2()
t2:Speak("test2說話")
--繼承了Mono的類 不能直接new
local obj5 = GameObject("加腳本測試")
--通過GameObject的AddComponent添加腳本
--xlua提供了一個重要方法 typeof 可以得到類的type
--xlua不支持 無參泛型函數(shù) 所以我們要用另一個重載
obj5:AddComponent(typeof(CS.LuaCallCSharp))
Lua使用C#枚舉
print("*************Lua調用C#枚舉相關知識點***************")
--枚舉調用
--調用Unity中的枚舉
--枚舉的調用規(guī)則和類的調用規(guī)則是一樣的
--CS.命名空間.枚舉名.枚舉成員
PrimitiveType = CS.UnityEngine.PrimitiveType
GameObject = CS.UnityEngine.GameObject
local obj = GameObject.CreatePrimitive(PrimitiveType.Cube)
--自定義枚舉使用方法一樣 只是要注意命名空間
E_MyEnum = CS.E_MyEnum
local c = E_MyEnum.Idle
print(c)
--枚舉轉換相關
--數(shù)值轉枚舉
local a = E_MyEnum.__CastFrom(1)
print(a)
--字符串轉枚舉
local b = E_MyEnum.__CastFrom("Atk")
print(b)
Lua使用C#數(shù)組、list和字典
print("*************Lua調用C#數(shù)組相關知識點***************")
local obj = CS.Lesson3()
--Lua使用C#相關知識
--長度 userdata數(shù)據(jù)類型
--C#怎么獲取 lua就怎么獲取 不能用lua中的#去獲取長度
print(obj.array.Length)
--訪問元素
print(obj.array[0])
--遍歷 要注意 lua中索引從1開始
--但是 數(shù)組是C#那邊的規(guī)則 所以還是得按C#的來
--注意最大值要-1
for i=0,obj.array.Length-1 do
print(obj.array[i])
end
--在Lua中創(chuàng)建一個C#的數(shù)組 Lua中表示數(shù)組和List可以用表
--但是 我們要使用C#中的Array類中的靜態(tài)方法即可(Lua中不能用new)
local array2 = CS.System.Array.CreateInstance(typeof(CS.System.Int32),10)
print(array2.Length)
print(array2[0])
print(array2[1])
print(array2)
print("*************Lua調用C#list相關知識點***************")
--調用成員方法用:
obj.list:Add(1)
obj.list:Add(2)
obj.list:Add(3)
--長度
print(obj.list.Count)
--遍歷
for i = 0 , obj.list.Count - 1 do
print(obj.list[i])
end
print(obj.list)
--在Lua中創(chuàng)建一個List對象
--老版本
local list2 = CS.System.Collections.Generic["List`1[System.String]"]()
print(list2)
list2:Add("123")
print(list2[0])
--新版本 >v2.1.12
--相當于得到了一個List
local List_String = CS.System.Collections.Generic.List(CS.System.String)
local list3 = List_String()
list3:Add("10238910823")
print(list3[0])
print("*************Lua調用C#Dictionary相關知識點***************")
--使用和C#一致
obj.dic:Add (1,"123")
print(obj.dic[1])
for k,v in pairs(obj.dic) do
print(k,v)
end
--在Lua中創(chuàng)建一個字典對象
local Dic_String_Vector3 = CS.System.Collections.Generic.Dictionary(CS.System.String,CS.UnityEngine.Vector3)
local dic2 = Dic_String_Vector3()
dic2:Add("123",CS.UnityEngine.Vector3.right)
for k,v in pairs(dic2) do
print(k,v)
end
--在Lua中創(chuàng)建的字典 直接通過中括號得不到 結果是nil
print(dic2["123"])
print(dic2:TryGetValue("123"))
--如果要通過鍵獲取值 要通過這個固定方法
print(dic2:get_Item("123"))
dic2:set_Item("123",nil)
print(dic2:get_Item("123"))
Lua使用C#拓展方法
public static class Tools
{
public static void Move(this Lesson4 obj)
{
Debug.Log(obj.name + "移動");
}
}
public class Lesson4
{
public string name = "123123";
public void Speak(string str)
{
Debug.Log("str");
}
public static void Eat()
{
Debug.Log("吃東西");
}
}
print("*************Lua調用C#拓展方法相關知識點***************")
Lesson4 = CS.Lesson4
--使用靜態(tài)方法
--CS.命名空間.類名.靜態(tài)方法名
Lesson4.Eat()
--成員方法 實例化出來用
local obj = Lesson4()
--成員方法一定要用冒號
obj:Speak("string")
--使用拓展方法 和使用成員方法一致
--要調用 C#某個類中的拓展方法 一定要在拓展方法的靜態(tài)類前加上LuaCallCSharp特性 并在Unity中生成Lua代碼
obj:Move()
Lua使用C# ref和out函數(shù)
public class Lesson5
{
public int RefFun(int a,ref int b,ref int c,int d)
{
b = a + d;
c = a - d;
return 100;
}
public int OutFun(int a, ref int b, ref int c, int d)
{
b = a;
c= d;
return 200;
}
public int RefOutFun(int a,out int b,ref int c)
{
b = a * 10;
c = a * 20;
return 300;
}
}
print("*************Lua調用C#ref和out方法相關知識點***************")
Lesson5 = CS.Lesson5
local obj = Lesson5()
--ref參數(shù) 會以多返回值的形式返回lua
--如果函數(shù)存在返回值那么第一個值就是改返回值
--之后的返回值就是ref的結果 從左到右一一對應
--ref參數(shù)需要傳入一個默認值來占位置 如果不傳剩余空位會傳入默認值
--a 相當于函數(shù)返回值
--b 第一個ref
--c 第二個ref
local a,b,c = obj:RefFun(1,0,0,1)
print(a)
print(b)
print(c)
--out參數(shù) 會以多返回值的形式返回lua
--如果函數(shù)存在返回值那么第一個值就是改返回值
--之后的返回值就是out的結果 從左到右一一對應
--out參數(shù) 不需要傳占位置的值
print("****************************")
local a,b,c = obj:OutFun(20,30)
print(a)
print(b)
print(c)
--綜合使用時 綜合上面的規(guī)則
--ref 需要站位 out不需要
--第一個是函數(shù)的返回值 之后從左到右依次對應ref或out
print("****************************")
local a,b,c = obj:RefOutFun(20,1)
print(a)
print(b)
print(c)
Lua使用C#重載函數(shù)
public class Lesson6
{
public int Calc()
{
return 100;
}
public int Calc(int a,int b)
{
return a + b;
}
public int Calc(int a)
{
return a;
}
public float Calc(float a)
{
return a;
}
}
print("*************Lua調用C#重載函數(shù)相關知識點***************")
local obj = CS.Lesson6()
--雖然Lua自己不支持重載函數(shù)
--但是Lua支持調用C#中的重載函數(shù)
print(obj:Calc())
print(obj:Calc(1,3))
--Lua雖然支持調用C#重載函數(shù)
--但是因為Lua中的數(shù)值類型只有Number
--所以對C#中多精度重載函數(shù)支持不好 會分不清
--在使用時會出現(xiàn)意想不到的事
print(obj:Calc(10))
print(obj:Calc(10.3))--輸出了0
--解決重載函數(shù)含糊問題
--xLua提供了解決方案 反射機制
--這種方法盡量別用 效率低
--Type是反射的關鍵類
local m1 = typeof(CS.Lesson6):GetMethod("Calc",{typeof(CS.System.Int32)})
local m2 = typeof(CS.Lesson6):GetMethod("Calc",{typeof(CS.System.Single)})
--通過Xlua提供的方法 把它轉換成lua函數(shù)來使用
--一般我們轉一次 然后重復使用
local f1 = xlua.tofunction(m1)
local f2 = xlua.tofunction(m2)
--成員方法 第一個參數(shù)傳對象
--靜態(tài)方法不用傳對象
print(f1(obj,10))
print(f2(obj,10.9))
Lua使用C#委托和事件
public class Lesson7
{
//聲明委托和事件
public UnityAction del;
public event UnityAction eventAction;
public void DoEvent()
{
if(eventAction != null)
eventAction();
}
public void ClearEvent()
{
eventAction = null;
}
}
print("*************Lua調用C#委托相關知識點***************")
local obj = CS.Lesson7()
--委托可以用來裝函數(shù)
--使用C#中的委托 裝lua中的函數(shù)
local fun = function ( )
print("Lua函數(shù)")
end
print("****************************")
--Lua中沒有復合運算符 不能+=
--如果第一次往委托中加函數(shù) 因為是nil 不能直接+
--所以第一次要先賦值=
obj.del = fun
--obj.del = obj.del + fun
obj.del = obj.del + fun
--不建議這么寫 最好是先聲明再加(類似于匿名函數(shù),在委托中刪不掉)
obj.del = obj.del + function ()
print("臨時聲明的函數(shù)")
end
--委托執(zhí)行
obj.del()
print("****************************")
obj.del = obj.del -fun
obj.del = obj.del -fun
obj.del()
--清空所有的函數(shù)
obj.del = nil
--清空后要先賦值
obj.del = fun
obj.del()
print("*************Lua調用C#事件相關知識點***************")
local fun2 = function ()
print("Action")
end
print("****************************")
--事件加減函數(shù)和委托非常不一樣
--lua中使用C#事件 加函數(shù)
--有點類似于使用成員方法 冒號事件名("+",函數(shù)變量)
obj:eventAction("+",fun2)
--最好不要這么寫
obj:eventAction("+",function ()
print("Action")
end)
obj:DoEvent()
print("****************************")
obj:eventAction("-",fun2)
obj:DoEvent()
--清楚事件 不能直接設空
--obj.eventAction=nil會報錯
obj:ClearEvent()
obj:DoEvent()
Lua使用C#二維數(shù)組
public class Lesson8
{
public int[,] array = new int[2, 3] { { 1, 2, 3 }, { 4, 5, 6 } };
}
print("*************Lua調用C#二維數(shù)組相關知識點***************")
local obj = CS.Lesson8()
--獲取長度
print("行:"..obj.array:GetLength(0))
print("列:"..obj.array:GetLength(1))
--獲取元素
--不能通過[0,0]或[0][0]來訪問元素 會報錯
print(obj.array:GetValue(0,0))
print(obj.array:GetValue(1,0))
for i = 0,obj.array:GetLength(0)-1 do
for j=0,obj.array:GetLength(1)-1 do
print(obj.array:GetValue(i,j))
end
end
Lua使用C#的null和nil比較
//為object 拓展一個方法
[LuaCallCSharp]
public static class Lesson9
{
//拓展一個為Objcet判空的方法 主要給Lua用 lua沒法用null和nil比較
public static bool IsNull(this Object obj)
{
return obj == null;
}
}
print("*************Lua調用C# nil和null比較相關知識點***************")
--往場景對象上添加一個腳本 如果不存在就加 存在就不加
GameObject = CS.UnityEngine.GameObject
Rigidbody = CS.UnityEngine.Rigidbody
local obj = GameObject("添加測試腳本")
--得到身上的剛體組件 如果沒有就加 有就不加
local rig = obj:GetComponent(typeof(Rigidbody))
print(rig)
--判斷空
--nil和null沒法進行==比較(rig == nil)
--第一種方法:rig:Equals(nil) then
--[[if rig:Equals(nil) then
print("123")
rig = obj:AddComponent(typeof(Rigidbody))
end]]
--第二種
--[[if IsNull(rig) then
print("123")
rig = obj:AddComponent(typeof(Rigidbody))
end]]
--第三種 在C#中添加方法
if rig:IsNull() then
print("123")
rig = obj:AddComponent(typeof(Rigidbody))
end
print(rig)
Lua和系統(tǒng)類或委托相互使用
public static class Lesson10
{
[CSharpCallLua]
public static List
{
//在這里面加上需要加上[CSharpCallLua]特性的type
typeof(UnityAction
};
[LuaCallCSharp]
public static List
{
typeof(GameObject),
typeof(Rigidbody)
};
}
GameObject = CS.UnityEngine.GameObject
UI = CS.UnityEngine.UI
local slider = GameObject.Find("Slider")
print(slider)
local sliderScript = slider:GetComponent(typeof(UI.Slider))
print(sliderScript)
sliderScript.onValueChanged:AddListener(function (f)
print(f)
end)
Lua使用C#協(xié)程
print("*************Lua調用C# 協(xié)程相關知識點***************")
--xlua提供的一個工具表
--一定是要通過require調用后才能用
util = require("xlua.util")
--C#中協(xié)程啟動都是通過繼承了Mono的類 通過里面的啟動函數(shù)StartCoroutine
GameObject = CS.UnityEngine.GameObject
WaitForSeconds = CS.UnityEngine.WaitForSeconds
--在場景中新建一個空物體 掛一個腳本上去 腳本繼承mono使用它來開啟協(xié)程
local obj = GameObject("Coroutine")
local mono = obj:AddComponent(typeof(CS.LuaCallCSharp))
--希望用來被開啟的協(xié)程函數(shù)
fun = function ()
local a = 1
while true do
--Lua中不能直接使用C#中的yield return
--就使用Lua中的協(xié)程返回
coroutine.yield(WaitForSeconds(1))
print(a)
a = a + 1
if a>5 then
mono:StopCoroutine(b)
end
end
end
--我們不能直接將lua函數(shù)傳入開啟協(xié)程
--如果要把lua函數(shù)當做協(xié)程函數(shù)傳入
--必須先調用xlua.util中的cs_generator(lua函數(shù))
b = mono:StartCoroutine(util.cs_generator(fun))
Lua使用C#泛型函數(shù)
print("*************Lua調用C# 泛型函數(shù)相關知識點***************")
local obj = CS.Lesson12()
local child = CS.Lesson12.TestChild()
local father = CS.Lesson12.TestFather()
--支持有約束有參數(shù)的泛型函數(shù)
obj:TestFun1(child,father)
obj:TestFun1(father,child)
--lua中不支持沒有約束的泛型函數(shù)
--obj:TestFun2(child)
--Lua中不支持有約束但是沒有參數(shù)的泛型函數(shù)
--obj:TestFun3()
--Lua中不支持 非Class的約束
--obj:TestFun4(child)
--有一定使用限制
--Mono打包 這種方式支持使用
--il2cpp打包 如果泛型參數(shù)是引用類型才可以使用
--il2cpp打包 如果泛型參數(shù)是值類型 除非C#那邊已經(jīng)調用過了 同類型的泛型參數(shù)lua中才能調用
--補充知識 讓上面不支持使用的泛型函數(shù) 變得能夠使用
--得到通用函數(shù)
--設置泛型類型再使用
--xlua.get_generic_method(類,"函數(shù)名")
local testFun2 = xlua.get_generic_method(CS.Lesson12,"TestFun2")
local testFun2_R = testFun2(CS.System.Int32)
--調用
--成員方法 第一個參數(shù) 傳調用函數(shù)的對象 如果是靜態(tài)函數(shù)就不用傳
testFun2_R(obj,1)
public class Lesson12
{
public interface ITest
{
}
public class TestFather
{
}
public class TestChild:TestFather,ITest
{
}
public void TestFun1
{
Debug.Log("有參數(shù) 有約束的泛型方法");
}
public void TestFun2
{
Debug.Log("有參數(shù) 沒約束的泛型方法");
}
public void TestFun3
{
Debug.Log("有約束 沒參數(shù)的泛型函數(shù)");
}
public void TestFun4
{
Debug.Log("有約束有參數(shù) 但是約束不是類");
}
}
柚子快報激活碼778899分享:Lua調用C#
好文閱讀
本文內容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉載請注明,如有侵權,聯(lián)系刪除。