lua和unity如何交互_(XLua)C#与Lua中的交互

Paste_Image.png

下载后接下来就是导入XLua到unity里了,解析出来的XLua有下面几个文件夹

Paste_Image.png

我们只需要将Assests:主目录里面的东西全部导入到Unity里面就OK了,导入后再XLua的文件夹下有这么几个。里面都有学习的文档,也可自行去学。

Paste_Image.png

hotfix的环境配置

在unity的PlayerSetting下的Other Settings里面打开XLua的宏HOTFIX_ENABLE,只有打开这个宏以后才能进行Xlua的修复以及更新

image.png然后我们打开工程中XLua例子中的第八个例子08_Hotfix看看是如何配置的

image.png

定义后后生成代码并注入

image.png如有报错请看注意事项

使用建议

对所有较大可能变动的类型加上[Hotfix]标识;

建议用反射找出所有函数参数、字段、属性、事件涉及的delegate类型,在C#函数中调用Lua,在C#函数上标注[CSharpCallLua];

业务代码、引擎API、系统API,需要在Lua补丁里头高性能访问的类型,在Lua中调用C#函数,在C#函数上标注加上[LuaCallCSharp];

引擎API、系统API可能被代码剪裁调(C#无引用的地方都会被剪裁),如果觉得可能会新增C#代码之外的API调用,这些API所在的类型要么加LuaCallCSharp,要么加ReflectionUse;

开发过程:

首先开发业务代码->在所有可能出现问题的类上打上hotfix的标签,在所有lua调用CSharp的方法上打上LuaCallCSharp,在所有CSharp调用Lua的方法上打上CSharpCallLua->打包发布->修改bug时只需要更新Lua文件,修改资源时(声音,模型,贴图,图片,UI)只需要更新ab包。用户只需要去下载lua文件跟ab包。

C#访问Lua中的全局变量与table

首先创建一个在Resources下面创建一个文本文件并给其命名为Hello world.lua.txt,这样我们就可以读取到Lua文本文件了,然后写入以下

print("hello world from file")

a=100

Str="NiHao"

IsDie=false

person=

{

name="Tao",age=20,

eat=function(self,a,b) --一个函数 self代表自身 隐藏参数 后面再跟两个int参数

print(a+b)

print("OK")

end

}

接着我们创建一个脚本HolloworldXLua引入程序集XLua在Start方法下写入

一个LuaEnv实例对应Lua虚拟机,出于开销的考虑,建议全局唯一

DoString参数为String,可输入任意合法的Lua代码.

using UnityEngine;

using XLua;

public class HolloworldXLua: MonoBehaviour {

// Use this for initialization

void Start () {

LuaEnv luaenv = new LuaEnv();//一个LuaEnv实例对应Lua虚拟机,出于开销的考虑,建议全局唯一

luaenv.DoString("require 'Hello world'");//通过内置的Loder加载lua源文件

int a = luaenv.Global.Get("a");//获取到Lua里面的全局变量a

Debug.Log(a);

string Str = luaenv.Global.Get("Str");

Debug.Log(Str);

bool IsDie = luaenv.Global.Get("IsDie");

Debug.Log(IsDie);

//Person p = luaenv.Global.Get("person");

IPerson p = luaenv.Global.Get("person");

Debug.Log(p.name+p.age);

p.eat(12,22);//调用Lua里面的函数 p.eat(p,12,22)有隐藏参数

luaenv.Dispose();

}

class Person

{

public string name;

public int age;

}

//获取Lua里面的列表用接口也可以映射的,但是要加上CSharpCallLua

[CSharpCallLua]

interface IPerson

{

string name { get; set; }

int age { get; set; }

void eat(int a,int b);

}

}

在这里访问Lua中的Table有几种方法一种是映射到类中,另一种是映射到接口中去,但是这两种方法结果都是相同但是,有一点是不一样的,那就是映射到类中只拷贝Lua里面的数据但是用接口映射的话可以修改Lua里面的数据.,用接口相当与引用

然后我们就可以看到输出的结果,输出的就是Lua脚本里面的全局变量与里面的table里面的

Paste_Image.png

然后还可以通过Dictionary或者List去映射Lua表里面的数据

void Start()

{

LuaEnv luaenv = new LuaEnv();//一个LuaEnv实例对应Lua虚拟机,出于开销的考虑,建议全局唯一

luaenv.DoString("require 'Hello world'");//通过内置的Loder加载lua源文件

Dictionary dict = luaenv.Global.Get>("person");//person表示哪个表

foreach (string Key in dict.Keys)

{

print(Key + ":" + dict[Key]);

}

luaenv.Dispose();

}

输出结果:

Paste_Image.png

下面使用List也可以映射那些没有Key的值,

Lua脚本里面

print("hello world from file")

a=100

Str="NiHao"

IsDie=false

person=

{

name="Tao",age=20,2,2,212,15

}

function person:eat(a,b)

print(a+b)

end

C#脚本里面

void Start()

{

LuaEnv luaenv = new LuaEnv();//一个LuaEnv实例对应Lua虚拟机,出于开销的考虑,建议全局唯一

luaenv.DoString("require 'Hello world'");//通过内置的Loder加载lua源文件

List list = luaenv.Global.Get>("person");//person表示哪个表

foreach (object o in list)

{

print(o);

}

luaenv.Dispose();

}

最后输出可以看到2输出两次212和15分别输出一次对应Lua脚本里面的数据:

Paste_Image.png

还有一种访问Tab的方式就是使用LuaTable,这种方式不推荐使用,性能比较慢,我推荐使用第二种方式通过去创建Intaface去映射Lua中的Table。

访问一个全局的Function

首先Lua脚本里面写入函数方法,一个有多个返回值有参数的方法

function add(a,b)

print(a+b)

return a+b,a,b

end

那么在C#中如何去调用呢下面来看看,因为我们在C#中只能有一个返回值而在Lua中可以有多个返回值,那么在C#返回值的时候只能返回第一个值,而Lua后面的返回值可以在C#中用out或者ref去接收后面的返回值

[CSharpCallLua]

delegate int Add(int a, int b,out int resa,out int resb);//定义一个有返回值有参数的委托

void Start()

{

LuaEnv luaenv = new LuaEnv();//一个LuaEnv实例对应Lua虚拟机,出于开销的考虑,建议全局唯一

luaenv.DoString("require 'Hello world'");//通过内置的Loder加载lua源文件

Add add = luaenv.Global.Get("add");

int resa, resb;

int res=add(12,15,out resa,out resb);

print(res);

print(resa);

print(resb);

add = null;//Action有映射如果直接释放Lua虚拟机的话直接会报错只有将Action函数置空后才能释放虚拟机

luaenv.Dispose();

}

输出结果,前面两个是Lua里面输出的,后面是C#里面输出的,这样就轻松调用了Lua里面的方法了

Paste_Image.png

还有一种方式就是使用Lua自带的LuaFction,和上面LuaTable使用一样比较耗费性能,但是使用简单所以这里也不推荐使用

添加自定义Load的方法

如果我们的Lua文本不想放在Resource里面加载想放到其他地方加载怎么办呢,Xlua也提供了自定义的Load方法,比如我们想把我们的Lua脚本放在StreamingAssets文件夹下面,那么该如何做呢,首先先在Unity里面创建一个StreamingAssets文件夹,然后把我们的Lua脚本放在StreamingAssets文件夹下,创建一个脚本CreateLoade,写入代码

private LuaEnv luaenv;

// Use this for initialization

void Start () {

luaenv = new LuaEnv();

luaenv.AddLoader(MyLoader);//添加自己的Load

luaenv.DoString("require 'hello world'");

}

private byte[] MyLoader(ref string filePath)

{

// Application.streamingAssetsPath表示找到Asses里面的StreamingAssets

string absPath = Application.streamingAssetsPath + "/" + filePath + ".lua.txt";

return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(absPath)); ;

}

private void OnDestroy()

{

luaenv.Dispose();

}

然后我们在Unity里面运行起来看结果,输出了Lua脚本里输出的结果。这样就没问题了.

Paste_Image.png

在Lua中构造Unity里面游戏物体并且查找游戏对象获取相应组件

在Lua脚本中写入

--构造游戏物体,New一个对象

CS.UnityEngine.GameObject("NewByLua")

--访问静态属性

print(CS.UnityEngine.Time.deltaTime)

--局部变量 访问Unity里面的游戏物体

local gameobject=CS.UnityEngine.GameObject

local camera=gameobject.Find("Main Camera")

local light=gameobject.Find("Directional Light")

light.name="UpdataLight"

--获取light游戏物体里面的Light组件 调用成员方法的时候,使用冒号

local lightCom=light:GetComponent("Light")

--销毁lightCom组件

gameobject.Destroy(lightCom)

这时候C#中构造虚拟机运行的时候就会在Unity里面构造一个空的游戏物体,运行后会生成一个名为NewByLua的空游戏物体,并且会查找到Directional Light并修改名为为UpdataLight,并移除了里面的Light组件

Paste_Image.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值