欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

目錄

柚子快報(bào)激活碼778899分享:游戲 設(shè)計(jì)模式 xLua詳解

柚子快報(bào)激活碼778899分享:游戲 設(shè)計(jì)模式 xLua詳解

http://yzkb.51969.com/

目錄

環(huán)境準(zhǔn)備xLua導(dǎo)入

C#調(diào)用LuaLua解析器Lua文件加載重定向Lua解析管理器全局變量的獲取全局函數(shù)的獲取List和Dictionary映射table類映射table接口映射tableLuaTable映射table

Lua調(diào)用C#準(zhǔn)備工作Lua使用C#類Lua調(diào)用C#枚舉Lua使用C# 數(shù)組 List 字典數(shù)組List字典

Lua使用C#擴(kuò)展方法Lua使用C# ref和out函數(shù)refout

函數(shù)重載lua調(diào)用C# 委托和事件Lua使用C#二維數(shù)組Lua中null與nil的比較系統(tǒng)類型與Lua互相訪問lua使用C#協(xié)程Lua使用C#泛型

環(huán)境準(zhǔn)備

xLua導(dǎo)入

我們來到github搜索xLua,直接下載zip壓縮包 我們把這兩個(gè)文件夾復(fù)制到工程中 編譯完之后窗口上就會(huì)有這個(gè)Xlua的選項(xiàng)(這里有可能會(huì)提示某個(gè)腳本編譯失敗,加個(gè)using System.Reflection) 我們可以先點(diǎn)擊第二個(gè)選項(xiàng),再點(diǎn)擊第一個(gè)選項(xiàng)生成 然后這里要導(dǎo)入ABbrowser工具,詳情請(qǐng)看AssetBundle詳解 這里根據(jù)教程還需要導(dǎo)入三個(gè)類 我依次寫到這上面 BaseManager

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class BaseManagerwhere T:new()//where T:new() 指定了泛型類型 T 必須具有無參數(shù)的構(gòu)造函數(shù)

{

private static T instance;

public static T GetInstance()

{

if (instance == null)

instance = new T();

return instance;

}

}

SingletonAutoMono

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class SingletonAutoMono:MonoBehaviour where T : Monobehaviour

{

private static T instance;

public static T GetInstance()

{

if (instance == null)

{

GameObject obj = new GameObject();

obj.name = typeof(T).ToString();

DontDestoryOnLoad(obj);

instance = obj.AddComponent();

}

return instance;

}

}

SingletonMono類

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

// Start is called before the first frame update

public class SingletonMono : MonoBehaviour where T : MonoBehaviour

{

private static T instance;

public static T Getinstance()

{

retrun instance;

}

protected virtual void Awake()

{

instance = this;

}

}

然后我們要導(dǎo)入AB包管理器,這個(gè)也在AssetBundle詳解里

C#調(diào)用Lua

Lua解析器

這里的核心就是LuaEnv,我們把腳本附著到相機(jī)上,然后運(yùn)行

public class Lesson1_LuaEnv : MonoBehaviour

{

// Start is called before the first frame update

void Start()

{

//Lua解析器 能夠讓我們?cè)赨nity中執(zhí)行Lua

LuaEnv env = new LuaEnv();

//執(zhí)行Lua語言

env.DoString("print('こにちは')");

}

// Update is called once per frame

void Update()

{

}

}

//幫助我們定時(shí)清除Lua中沒有手動(dòng)釋放的對(duì)象

//在幀更新中定時(shí)執(zhí)行或切場(chǎng)景時(shí)執(zhí)行

env.Tick();

//銷毀Lua解析器

env.Dispose();

這里如果有很多個(gè)語句需要執(zhí)行,一句一句調(diào)用太慢了怎么辦,我們這里可以使用DoString通過字符名來執(zhí)行Lua腳本名,Lua中使用require來跨腳本運(yùn)行 我們現(xiàn)在先在Unity中新建一個(gè)Resources文件夾, 然后在文件夾中新建一個(gè).txt文件再把后綴更改為.lua 再用相應(yīng)的lua軟件打開 我們先只寫一句話 但是現(xiàn)在又有個(gè)問題,Unity無法直接識(shí)別Lua文件,所以再改成Main.lua.txt

env.DoString("require('Main')");

Lua文件加載重定向

這部分的內(nèi)容是自定義lua文件加載路徑 當(dāng)require被調(diào)用時(shí),會(huì)先去Addloader中的函數(shù)路徑找文件,然后再去默認(rèn)路徑(Resources)中尋找 我們現(xiàn)在寫一個(gè)基本邏輯,Addloder會(huì)實(shí)現(xiàn)重定向功能,它接受一個(gè)委托

void Start()

{

LuaEnv env = new LuaEnv();

env.AddLoader(MyCustomLoader);

env.DoString("require('Main')");

}

//自動(dòng)執(zhí)行

private byte[] MyCustomLoader(ref string filePath)

{

Debug.Log(filePath);

//通過函數(shù)中的邏輯,去加載lua文件

return null;

}

我們新建一個(gè)叫做Lua的文件夾 然后在里面新建一個(gè)Main文件 我們來詳細(xì)解釋一下這段代碼 這里AddLoader的調(diào)用參數(shù)是一個(gè)委托變量,類似于C++中的函數(shù)指針,而MyCustomLoader這里是通過env傳入的lua文件名。如果我把 env.DoString(“require(‘Main’)”);這行注釋掉,那么MyCustomLoader將不會(huì)執(zhí)行 在這里,filePath是Main,Application.dataPath是Unity/xxx/Asset

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using XLua;

using System.IO;

using Unity.VisualScripting;

public class Lesson2_Loader : MonoBehaviour

{

void Start()

{

LuaEnv env = new LuaEnv();

env.AddLoader(MyCustomLoader);

env.DoString("require('Main')");

}

//自動(dòng)執(zhí)行

private byte[] MyCustomLoader(ref string filePath)

{

//傳入的參數(shù)是require執(zhí)行的腳本文件名

string path = Application.dataPath + "/Lua/" + filePath + ".lua";

Debug.Log(path);

if(File.Exists(path))

{

return(File.ReadAllBytes(path));

}

else

{

Debug.Log("重定向失敗,文件名為" + filePath);

}

//拼接一個(gè)lua所在路徑

//通過函數(shù)中的邏輯,去加載lua文件

return null;

}

}

Lua解析管理器

我們用一個(gè)管理器來管理LuaEnv 其他邏輯都是前面提到過的

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using XLua;

using System.IO;

//Lua管理器

//提供lua解析器

//保證解析器的唯一性

public class LuaMgr:BaseManager

{

//執(zhí)行Lua語言的函數(shù)

//釋放垃圾

//銷毀

//重定向

private LuaEnv luaEnv;

public void Init()

{

//如果已經(jīng)初始化了,直接返回

if (luaEnv != null)

return;

luaEnv = new LuaEnv();

//加載lua腳本重定向

luaEnv.AddLoader(MyCustomLoader);

}

private byte[] MyCustomLoader(ref string filePath)

{

string path = Application.dataPath + "/Lua/" + filePath + ".lua";

Debug.Log(path);

if (File.Exists(path))

{

return (File.ReadAllBytes(path));

}

else

{

Debug.Log("重定向失敗,文件名為" + filePath);

}

return null;

}

public void DoString(string str)

{

luaEnv.DoString(str);

}

public void Tick()

{

luaEnv.Tick();

}

public void Dispose()

{

luaEnv.Dispose();

luaEnv = null;

}

}

然后我們寫一個(gè)測(cè)試類來測(cè)試 我們的代碼邏輯在這個(gè)腳本中第一次使用LuaMgr,所以需要Init,如果初始化之后在其他的腳本就可以直接使用LuaMgr了

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class Lesson3_LuaMgr : MonoBehaviour

{

// Start is called before the first frame update

void Start()

{

LuaMgr.GetInstance().Init();//LuaMgr是一個(gè)單例類,所以可以直接訪問

LuaMgr.GetInstance().DoString("require('Main')");

}

// Update is called once per frame

void Update()

{

}

}

接下來我們講AB包和Mgr相關(guān)邏輯 由于AB包不識(shí)別lua,所以還是先修改成txt 我們選中Main文件,新建一個(gè)lua的AB包 我們先清除一下代碼 然后構(gòu)建 現(xiàn)在我們要做的其實(shí)就是在AB包中執(zhí)行l(wèi)ua 我們?cè)賮斫忉尯瘮?shù)邏輯 這里我們又加了一個(gè)重定向邏輯MyCustomABLoader,用來從AB包中加載數(shù)據(jù),在MyCustomABLoader中,我們之前使用的邏輯是手動(dòng)聲明AB包的對(duì)象然后進(jìn)行讀取,但是我們?cè)贏B包的教程中做了一個(gè)AB包管理器,所以這里使用AB包管理器來做

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using XLua;

using System.IO;

//Lua管理器

//提供lua解析器

//保證解析器的唯一性

public class LuaMgr:BaseManager

{

//執(zhí)行Lua語言的函數(shù)

//釋放垃圾

//銷毀

//重定向

private LuaEnv luaEnv;

public void Init()

{

//如果已經(jīng)初始化了,直接返回

if (luaEnv != null)

return;

luaEnv = new LuaEnv();

//加載lua腳本重定向

luaEnv.AddLoader(MyCustomLoader);

luaEnv.AddLoader(MyCustomABLoader);

}

public void DoLuaFIle(string fileName)

{

string str = string.Format("require('{0}')",fileName);

}

private byte[] MyCustomLoader(ref string filePath)

{

string path = Application.dataPath + "/Lua/" + filePath + ".lua";

Debug.Log(path);

if (File.Exists(path))

{

return (File.ReadAllBytes(path));

}

else

{

Debug.Log("重定向失敗,文件名為" + filePath);

}

return null;

}

//重定向加載AB包中的lua腳本

private byte[] MyCustomABLoader(ref string filePath)

{

//從AB包中加載lua文件

//加載AB包

// string path = Application.streamingAssetsPath + "/lua";

// AssetBundle ab = AssetBundle.LoadFromFile(path);

// TextAsset tx = ab.LoadAsset(filePath+".lua");

// //加載除了lua文件 byte數(shù)組

return tx.bytes;

TextAsset lua=ABMgr.GetInstance().LoadRes("lua",filePath+".lua");

if (lua != null)

return lua.bytes;

else

return null;

}

public void DoString(string str)

{

luaEnv.DoString(str);

}

public void Tick()

{

luaEnv.Tick();

}

public void Dispose()

{

luaEnv.Dispose();

luaEnv = null;

}

}

全局變量的獲取

我們?cè)贛ain.lua的文件下新建一個(gè)Test.lua 在test中定義如下變量 這里我們?cè)L問全局變量的方式是通過Main.lua進(jìn)行的 這里很有意思的是,require調(diào)用Test的邏輯本質(zhì)上并不是Main自己調(diào)用的,而是xlua調(diào)用的,通過堆??梢钥吹?所以如果我require(‘一個(gè)不存在的文件’),會(huì)在xlua層報(bào)錯(cuò)也是有跡可循的了。

現(xiàn)在我們要使用mgr來調(diào)用Test中的變量 這個(gè)Globe有點(diǎn)類似大G表,可以通過這個(gè)操縱Test中的數(shù)據(jù)

int i=LuaMgr.GetInstance().Global.Get("testNumber");

Debug.Log(i);

可以發(fā)現(xiàn)成功打印 但是這里取到的值也只是個(gè)拷貝,并不會(huì)修改原來的數(shù) 如果想修改可以使用set 這里也不能取到test中聲明的本地變量,換言之只能操作大G表的內(nèi)容

全局函數(shù)的獲取

函數(shù)我們依舊在test中寫 我們先調(diào)用無參無返回值方法,使用委托

public class Lesson5_CallFunction : MonoBehaviour

{

// Start is called before the first frame update

void Start()

{

LuaMgr.GetInstance().Init();

LuaMgr.GetInstance().DoLuaFile("Main");

//無參無返回的獲取

//委托

CustomCall call = LuaMgr.GetInstance().Global.Get("testFun");

call();

}

// Update is called once per frame

void Update()

{

}

}

有參有返回:

public delegate void CustomCall2(int a);

//調(diào)用

[CSharpCallLua]//自定義委托一定要有

CustomCall2 call2 = LuaMgr.GetInstance().Global.Get("testFun2");

call2(10);

這里可能會(huì)報(bào)錯(cuò),去xlua窗口重新生成一下就好了 這里委托都可以使用Unity/C#/提供的,不需要自己寫 接下來是多返回值,在C#中使用out 和 ref來接收 首先是聲明委托

//多返回值委托

[CSharpCallLua]

public delegate int CustomCall3(int a, out int b, out bool c, out string d, out int e);

然后是接收

//多返回值獲取

CustomCall3 call3 = LuaMgr.GetInstance().Global.Get("testFun3");

int b;bool c; string d; int e;

Debug.Log("多返回值:" + call3(100, out b, out c, out d, out e));

Debug.Log(b + "_" + c + "_" + d + "_" + e);

然后是變長(zhǎng)參數(shù) 首先說一下ref和out的區(qū)別 ref 關(guān)鍵字用于傳遞一個(gè)已初始化的變量作為參數(shù),并且要求方法在使用這個(gè)參數(shù)之前初始化它。 out 關(guān)鍵字用于傳遞一個(gè)未初始化的變量作為參數(shù),方法在使用這個(gè)參數(shù)之前必須將其初始化。 我們依舊可以用這些參數(shù)

[CSharpCallLua]

public delegate int CustomCall4(int a, ref int b, ref bool c, ref string d, ref int e);

//多返回值獲取

CustomCall4 call4 = LuaMgr.GetInstance().Global.Get("testFun3");

int b1=0; bool c1=false; string d1=""; int e1=0;//要初始化

Debug.Log("變長(zhǎng)參數(shù):" + call4(100, ref b, ref c, ref d, ref e));

Debug.Log(b + "_" + c + "_" + d + "_" + e);

以下是完整代碼

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UIElements;

using XLua;

//無參無返回值的委托

public delegate void CustomCall();

//有參有返回的委托

[CSharpCallLua]

public delegate void CustomCall2(int a);

//多返回值委托

[CSharpCallLua]

public delegate int CustomCall3(int a, out int b, out bool c, out string d, out int e);

//變長(zhǎng)參數(shù)

[CSharpCallLua]

public delegate int CustomCall4(int a, ref int b, ref bool c, ref string d, ref int e);

public class Lesson5_CallFunction : MonoBehaviour

{

// Start is called before the first frame update

void Start()

{

LuaMgr.GetInstance().Init();

LuaMgr.GetInstance().DoLuaFile("Main");

//無參無返回的獲取

//委托

CustomCall call = LuaMgr.GetInstance().Global.Get("testFun");

call();

//有參有返回的獲取

CustomCall2 call2 = LuaMgr.GetInstance().Global.Get("testFun2");

call2(10);

//多返回值獲取

CustomCall3 call3 = LuaMgr.GetInstance().Global.Get("testFun3");

int b;bool c; string d; int e;

Debug.Log("多返回值:" + call3(100, out b, out c, out d, out e));

Debug.Log(b + "_" + c + "_" + d + "_" + e);

//多返回值獲取

CustomCall4 call4 = LuaMgr.GetInstance().Global.Get("testFun3");

int b1=0; bool c1=false; string d1=""; int e1=0;

Debug.Log("變長(zhǎng)參數(shù):" + call4(100, ref b, ref c, ref d, ref e));

Debug.Log(b + "_" + c + "_" + d + "_" + e);

}

// Update is called once per frame

void Update()

{

}

}

List和Dictionary映射table

我們先在test中聲明

testList={1,2,3,4,5,6}

testList2={"123","123",true,1,1.2}

--Dictionary

testDic1={

["1"]=1,

["2"]=1,

["3"]=1,

["4"]=1

}

testDic2={

["1"]=1,

[true]=1,

[false]=true

["123"]=false

}

老方法調(diào)用

List list = LuaMgr.GetInstance().Global.Get>("testList");

for(int i = 0; i < list.Count; i++)

{

Debug.Log(list[i]);

}

不過get還是不能改數(shù)據(jù)本身 我們?cè)倏匆幌聞偛诺膖estDic,testList2存的不只有int型 所以我們?cè)谌〉街档臅r(shí)候選擇object

List list2 = LuaMgr.GetInstance().Global.Get>("testList2");

for (int i = 0; i < list2.Count; i++)

{

Debug.Log(list2[i]);

}

Dictionary dic = LuaMgr.GetInstance().Global.Get>("testDic1");

foreach(string i in dic.Keys)

{

Debug.Log(i + "_" + dic[i]);

}

至于testDic2,我們可以都用dictory和上述一樣

類映射table

在這里我們要實(shí)現(xiàn)類邏輯 首先在test中寫一個(gè)類邏輯

testClass={

testInt=2,

testBool=true,

testString="123",

testFun=function()

print("123123123")

end

}

然后在腳本中聲明一個(gè)名字一樣的類

public class CallLuaClass

{

//在這個(gè)類中聲明成員變量

//名字一定要和Lua那邊的一樣

public int testInt;

public bool testBool;

public float testFloat;

public string testString;

public UnityAction testFun;

//這個(gè)自定義中的變量可以更多也可以更少

//如果比lua中的多少都會(huì)忽略

}

然后在腳本中把這個(gè)類”實(shí)例化“出來

LuaMgr.GetInstance().Init();

LuaMgr.GetInstance().DoLuaFile("Main");

CallLuaClass obj = LuaMgr.GetInstance().Global.Get("testClass");

Debug.Log(obj.testBool);

Debug.Log(obj.testInt);

Debug.Log(obj.testFun);

和之前一樣,這個(gè)是值拷貝而不是引用拷貝 然后我們?cè)賮砜匆幌虑短子成?,我們?cè)谶@個(gè)類里再加一個(gè)

testClass={

testInt=2,

testBool=true,

testString="123",

testFun=function()

print("123123123")

end

testClass2={

testInt2=3;

}

}

然后在聲明處

public class CallLuaClass2

{

public int testInt2;

}

void Start()

{

LuaMgr.GetInstance().Init();

LuaMgr.GetInstance().DoLuaFile("Main");

CallLuaClass obj = LuaMgr.GetInstance().Global.Get("testClass");

// Debug.Log(obj.testClass2.testInt2);

CallLuaClass2 obj2 = obj.testClass2;

Debug.Log(obj2.testInt2);

}

接口映射table

先定義一個(gè)接口

[CSharpCallLua]//這里也要加

public interface ICSharpCallInterface

{

//接口中是不允許有成員變量的

//用屬性來接收

public int testInt

{

get;

set;

}

public bool testBool

{

get;

set;

}

UnityAction testFun

{

get;

set;

}

}

ICSharpCallInterface obj = LuaMgr.GetInstance().Global.Get("testClass");

obj.testFun();

但是這里唯一不同的是,接口拷貝是引用拷貝,lua表中的值也變了

LuaTable映射table

我們經(jīng)常使用的Globe本質(zhì)上就是一個(gè)luaTable 所以想訪問一個(gè)屬性很簡(jiǎn)單

LuaTable table= LuaMgr.GetInstance().Global.Get("testClass");

ebug.Log(table.Get("testInt"));

table.Get("testFun").Call();//調(diào)用函數(shù)

不建議使用LuaTable和luaFunction 效率比較低

用完之后一定要記住table.Dispose銷毀

Lua調(diào)用C#

準(zhǔn)備工作

我們先來新建一個(gè)文件夾,專門存Lua調(diào)用C#的代碼 然后新建一個(gè)Main腳本 Lua沒有辦法直接訪問C#,一定是先從C#調(diào)用Lua腳本后才把核心邏輯交給Lua來編寫 先做準(zhǔn)備工作

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class Main : MonoBehaviour

{

void Start()

{

LuaMgr.GetInstance().Init();

LuaMgr.GetInstance().DoLuaFile("Main");

}

}

把Main腳本放到攝像機(jī)上

我們新建一個(gè)lua 我們?cè)贛ain中調(diào)用新建的lua

Lua使用C#類

Lua使用C#的類非常簡(jiǎn)單

CS.命名空間.類名 先看Main腳本

--Main腳本

print("主Lua腳本已啟動(dòng)")

require("Lesson1_CallClass")

然后是Lesson1_CallClass腳本

Lua中沒有new 所以我們類名括號(hào)就是實(shí)例化對(duì)象

--Lesson1_CallClass

print("lua調(diào)用C#類相關(guān)知識(shí)點(diǎn)")

local obj1=CS.UnityEngine.GameObject()

我們來梳理一下函數(shù)邏輯

首先我們?cè)贑#中調(diào)用初始化函數(shù):先創(chuàng)建唯一實(shí)例LuaEnv,然后使用重定向(找到lua文件的位置)通過LuaEnv的DoString方法執(zhí)行l(wèi)ua邏輯現(xiàn)在我們到了lua腳本中,由于之前我們已經(jīng)聲明將調(diào)用lua中的Main文件,所以來到Main文件,這里執(zhí)行打印語句,然后執(zhí)行require語句,轉(zhuǎn)到Lesson1_CallClass中來到Lesson1_CallClass中,先打印,然后在場(chǎng)景中創(chuàng)建一個(gè)空GameObject

結(jié)果:

現(xiàn)在我使用CS.UnityEngine.GameObject()相當(dāng)于調(diào)用一個(gè)無參函數(shù),我也可以在括號(hào)里面?zhèn)魅朊肿鳛橐粋€(gè)有參函數(shù)

如果是類對(duì)象中的成員方法,要加冒號(hào)

這里我們使用帶參構(gòu)造函數(shù),并且使用Gameobject作為別名,我們通過obj3.transform再加冒號(hào)調(diào)用translate

print("lua調(diào)用C#類相關(guān)知識(shí)點(diǎn)")

local obj2=CS.UnityEngine.GameObject("Theshy")

GameObject=CS.UnityEngine.GameObject

local obj3=GameObject.Find("Theshy")

obj3.transform:Translate(CS.UnityEngine.Vector3.right)

可以發(fā)現(xiàn)確實(shí)移動(dòng)了 我們之前看的都是Unity自己的類,現(xiàn)在我們寫一個(gè)我們自己的類

public class Test

{

public void Speak(string str)

{

Debug.Log(str);

}

}

namespace Theshy

{

public class Test2

{

public void Speak(string str)

{

Debug.Log("Test2: " + str);

}

}

}

然后在lua里

local t=CS.Test()

t:Speak("我々はここで死に")

local t2=CS.Theshy.Test2()

t2:Speak("次の生者に意味を託す")

接下來我們要為實(shí)例化對(duì)象添加腳本,這里別忘了還是使用冒號(hào)

GameObject=CS.UnityEngine.GameObject

local obj5=GameObject("加腳本測(cè)試")

obj5:AddComponent(typeof(CS.MyClass))

Lua調(diào)用C#枚舉

我們先聲明一個(gè)枚舉 然后利用這個(gè)枚舉創(chuàng)建一個(gè)立方體

PrimitiveType=CS.UnityEngine.PrimitiveType

GameObject=CS.UnityEngine.GameObject

local obj=GameObject.CreatePrimitive(PrimitiveType.Cube)--創(chuàng)建立方體

我們這里自己新建一個(gè)枚舉,和剛才我們自己寫類的方法一樣

CS.(命名空間.)枚舉名

Lua使用C# 數(shù)組 List 字典

數(shù)組

我們先在C#腳本中定義一個(gè)數(shù)組,list,字典

public class VectorSet

{

public int[] array = new int[5] { 1, 2, 3, 4, 5 };

public List list = new List();

public Dictionary dic = new Dictionary();

}

然后我們?cè)趌ua中,先寫數(shù)組邏輯

print("lua調(diào)用容器相關(guān)知識(shí)點(diǎn)")

local obj = CS.VectorSet()

--Lua使用C#數(shù)組

--這里不能使用#

print(obj.array.Length)

--訪問元素

print(obj.array[0])

然后是數(shù)組的遍歷,雖然lua中的索引從1開始 但是數(shù)組是C#的數(shù)組,所以還要按C#的來 并且在lua的for循環(huán)默認(rèn)最后條件是<=的,所以要減一

for i=0,obj.array.Length-1 do

print(obj.array[i])

end

如果我想在Lua中創(chuàng)建C#的數(shù)組呢? 由于lua中沒有new,所以不能像C#一樣聲明數(shù)組,但是在Unity中數(shù)組是一個(gè)數(shù)組類,里面提供了一個(gè)靜態(tài)方法,直接創(chuàng)建一個(gè)數(shù)組,所以我們這里直接調(diào)用這個(gè)靜態(tài)方法就可以了

local array2=CS.System.Array.CreateInstance(typeof(CS.System.Int32),10)

print(array2.Length)

print(array2[0])

print(array2[1])

List

對(duì)于List也一樣,遍歷和數(shù)組一模一樣

obj.list:Add(1)

obj.list:Add(2)

obj.list:Add(3)

print(obj.list.Count)

接下來要寫用list創(chuàng)建對(duì)象 分兩個(gè)版本 老版本(2.1.12之前)

local list2=CS.System.Collections.Generic["List`1[System.String]"]()

新版本

local List_String=CS.System.Collections.Generic.List(CS.System.String)--相當(dāng)于得到一個(gè)類

local list3=List_String()

字典

添加元素用add,和上面兩個(gè)一樣 遍歷需要用pairs

for k,v in pairs(obj.doc)do

print(k,v)

end

然后是在Lua中創(chuàng)建一個(gè)字典對(duì)象

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 i,v in pairs(dic2) do

print(i,v)

end

如果我現(xiàn)在想通過我剛才新建的dic2來訪問鍵值呢? 可以發(fā)現(xiàn)打印的是nil

print(dic2["123"])

這里要用

print(dic2:get_Item("123"))

如果要修改鍵值也要用set_Item

Lua使用C#擴(kuò)展方法

先聲明一個(gè)類和一個(gè)拓展方法

public static class Tools

{

//拓展方法

public static void Move(this testClass obj)

{

Debug.Log(obj.name + "移動(dòng)");

}

}

public class testClass

{

public string name = "Theshy";

public void Speak(string str)

{

Debug.Log(str);

}

public static void Eat()

{

Debug.Log("吃東西");

}

}

然后在lua中調(diào)用

print("擴(kuò)展方法")

testclass=CS.testClass

--使用靜態(tài)方法

testclass.Eat()

--使用成員函數(shù)

local obj=testclass()

obj:Speak("wryyyyyyy")

--使用拓展方法,和使用成員方法方法一致

CS.Tools.Move(obj)

但是會(huì)報(bào)錯(cuò)

所以想要在xLua中使用擴(kuò)展方法,一定要在工具類前面加上特性,然后不要忘了重新生成代碼

如果考慮性能的話,可以把所有l(wèi)ua中需要的東西都寫上LuaCallCSharp,因?yàn)閘ua底層是通過反射來與C#聯(lián)系的,會(huì)有一定性能損失

[XLua.LuaCallCSharp]

//拓展方法

public static void Move(this testClass obj)

{

Debug.Log(obj.name + "移動(dòng)");

}

Lua使用C# ref和out函數(shù)

ref

我們先在Unity中寫個(gè)類

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 OufFun(int a, out int b, out 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;

}

}

我們先來看ref的,ref是多返回值,并且需要顯式初始化 首先a是第一個(gè)返回值,接收的就是函數(shù)本身的返回值100,然后b和c分別接ref b ref c

Lesson5=CS.Lesson5

local obj=Lesson5()

local a,b,c=obj.RefFun(1,0,0,1)

print(a)

print(b)

print(c)

out

out不需要傳占位置的值

local obj=Lesson5()

local a,b,c=obj:OutFun(20,30)

print(a)

print(b)

print(c)

函數(shù)重載

我們先寫幾個(gè)簡(jiǎn)單的重載函數(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;

}

}

然后是lua層

local obj=CS.Lesson6()

print(obj:Calc())

print(obj:Calc(15,1))

可以看出lua支持調(diào)用C#中的重載函數(shù)

然后我們?cè)僬{(diào)用后面的

print(obj:Calc(10))

print(obj:Calc(10.2))

lua中只有number類型,而C#中有多個(gè)屬性,所以對(duì)多精度數(shù)據(jù)支持的并不好 用反射來解決多精度重載(效率低,盡量別用)

local m1=typeof(CS.Lesson6):GetMethod("Calc",{typeof(CS.System.Int32)})

local m2=typeof(CS.Lesson6):GetMethod("Calc",{typeof(CS.System.Single)})

local f1=xlua.tofunction(m1)

local f2=xlua.tofunction(m2)

f1(obj,10)

f1(obj,10.2)

lua調(diào)用C# 委托和事件

我們?cè)賹憘€(gè)類,一個(gè)委托,一個(gè)事件,和一個(gè)調(diào)用事件的函數(shù)

public class Lesson7

{

public UnityAction del;

public event UnityAction eventAction;

public void DoEvent()

{

eventAction();

}

}

這里不能直接+=,并且第一次往委托中加函數(shù)是nil不能直接加

local obj=CS.Lesson7()

local fun = function ( )

print("Lua函數(shù)Fun")

end

obj.del=fun

obj.del()--執(zhí)行委托

然后是事件

local obj=CS.Lesson7()

local fun2=function()

print("事件加的函數(shù)")

end

obj:eventAction("+",fun2)

obj:eventAction("+",fun2)

obj:DoEvent()

相應(yīng)的,想減少調(diào)用就用減號(hào) 如果我想清除事件,不能直接像委托del=nil 而是需要在C#層加一個(gè)函數(shù)

public void ClearEvent()

{

eventAction = null;

}

然后

obj:ClearEvent()

Lua使用C#二維數(shù)組

我們先在C#中聲明一個(gè)二維數(shù)組

public class Lesson8

{

public int[,] array = new int[2, 3] { { 1, 2, 3 }, { 4, 5, 6 } };

}

我們?cè)趌ua中先取到一個(gè)簡(jiǎn)單的二維數(shù)組

print("二維數(shù)組")

local obj=CS.Lesson8()

--獲取長(zhǎng)度

print(obj.array:GetLength(0))

print(obj.array:GetLength(1))

在Lua中訪問C#的二維數(shù)組不能通過[0,0]或[0][0]來訪問 和之前array一樣,二維數(shù)組提供了一個(gè)方法來返回值

print(obj.array:GetValue(0,0))

print(obj.array:GetValue(0,1))

然后是二維數(shù)組的遍歷

for i=0,obj:GetLength(0)-1 do

for j=0,obj:GetLength(1)-1 do

print(obj.GetValue(i,j))

end

end

Lua中null與nil的比較

我們現(xiàn)在實(shí)現(xiàn)一個(gè)需求,先實(shí)例化一個(gè)物體嗎,然后判斷其有沒有剛體組件,如果沒有再加

GameObject=CS.UnityEngine.GameObject

Rigidbody=CS.UnityEngine.Rigidbody

local obj=GameObject("測(cè)試加腳本")

local rig=obj:GetComponent(typeof(Rigidbody))

print(rig)

if rig==nil then

rig=obj:AddComponent(typeof(Rigidbody))

end

print(rig)

這里發(fā)現(xiàn)即使沒有腳本,也不會(huì)新加,可以通過測(cè)試發(fā)現(xiàn)if rig==nil 這行邏輯沒進(jìn) 原因是因?yàn)閚ull 和nil不是一個(gè)東西 所以這里要用 我們可以自己在lua中的Main文件中寫一個(gè)邏輯

function IsNull( obj )

if obj==nil or obj:Equals(nil) then

return true

else return false

end

我們也可以使用一個(gè)擴(kuò)展方法,這樣就把核心邏輯寫在C#中而不是lua中了

系統(tǒng)類型與Lua互相訪問

如果我需要在lua中使用一個(gè)只讀的代碼(系統(tǒng)庫(kù)或三方庫(kù)),不能加LuaCallCSharp代碼,應(yīng)該怎么做: 假如說我現(xiàn)在需要為UnityAction< float >加特性 我們寫這么一段代碼

public static class Lesson10

{

[CSharpCallLua]

public static List csharpCallLuaList = new List()

{

typeof(UnityAction)

};

}

然后點(diǎn)生成代碼

lua使用C#協(xié)程

這里我們?yōu)樾聞?chuàng)建的Gameobject添加了一個(gè)腳本,然后通過這個(gè)腳本調(diào)用StartCoroutine

GameObject =CS.UnityEngine.GameObject

WaitForSeconds=CS.UnityEngine.WaitForSeconds

local obj=GameObject("Coroutine")

local mono=obj:AddComponent(typeof(CS.LuaCallCSharp))

--希望用來被開啟的協(xié)程

fun=function ()

local a=1

while true do

coroutine.yield()

print(a)

a=a+1

end

end

mono:StartCoroutine(fun)

但是這樣會(huì)報(bào)錯(cuò) 所以不能通過StartCoroutine來直接調(diào)用fun

所以我們使用一個(gè)xlua官方自帶的一個(gè)工具表

util=require("xlua.util")

mono:StartCoroutine(util.cs_generator(fun))

Lua使用C#泛型

我們先在C#里寫幾個(gè)泛型函數(shù)

public class Lesson12

{

public interface ITest

{

}

public class TestFather

{

}

public class TestChild:TestFather,ITest

{

}

public void TestFun1(T a, T b) where T : TestFather

{

Debug.Log("有參數(shù)有約束的泛型方法");

}

public void TestFun2(T a)

{

Debug.Log("有參數(shù),無約束");

}

public void TestFun3() where T : TestFather

{

Debug.Log("無參數(shù),有約束");

}

public void TestFun4(T a) where T : ITest

{

Debug.Log("有參數(shù),有約束,約束不是類是接口");

}

}

然后來到lua 我們先來測(cè)試第一個(gè)

local obj=CS.Lesson12()

local child = CS.Lesson12.TestChild()

local father = CS.Lesson12.TestFather()

obj:TestFun1(child,father)

obj:TestFun1(father,child)

然后我們來調(diào)用第二組

報(bào)錯(cuò)了,可以發(fā)現(xiàn)lua中不支持不約束的泛型 然后第三組,可以發(fā)現(xiàn)lua也不支持無參帶約束的泛型 然后看最后一組 因?yàn)樵贑#中child類繼承自接口,所以用child傳進(jìn)去

obj:TestFun4(child)

可以發(fā)現(xiàn)4也不行,lua中不支持非class的約束 接下來講讓上面不支持的泛型函數(shù)變得能用

local testFun2=xlua.get_generic_method(CS.Lesson12,"TestFun2")

local testFun2_R=testFun2(CS.System.Int32)

--第一個(gè)參數(shù)傳調(diào)用函數(shù)的對(duì)象

testFun2_R(obj,1)

柚子快報(bào)激活碼778899分享:游戲 設(shè)計(jì)模式 xLua詳解

http://yzkb.51969.com/

推薦文章

評(píng)論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。

轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19074980.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄