tolua是Unity静态绑定lua的一个解决方案,它通过C#提供的反射信息分析代码并生成包装Wrap的类。它是一个用来简化在C#中集成lua的插件,可以自动生成用于在lua中访问Unity的绑定代码,并把C#中的常量、变量、函数、属性、类以及枚举暴露给lua。它是从cstolua演变过来的。从它的名字看出,它是集成了原来的tolua代码通过二次封装了一个C#与tolua(c)的一个中间层。
public string url = "file://F:/testAsset/";//假装是远程服务器
void Awake(){
StartCoroutine (Load());
}
IEnumerator Load(){
using(WWW www = new WWW(url+"1.txt")){
yield return www;
//版本对不上,进行下载,不然加载本地
using(WWW www2 = WWW.LoadFromCacheOrDownload(url+"1.assetbundle",Int32.Parse(www.text))){
yield return www2;
AssetBundle asset = www2.assetBundle;
//获取图片,更改按钮的资源
Sprite sprite = asset.LoadAsset<Sprite>("1");
Image img = GameObject.Find ("Button").GetComponent<Image> ();
img.sprite = sprite;
//加载代码 运行lua代码
TextAsset luaString = asset.LoadAsset<TextAsset> ("1Lua");
LuaState lua = new LuaState ();
lua.Start();
LuaBinder.Bind (lua);
lua.DoString (luaString.text);
LuaFunction func = lua ["changButtonText"] as LuaFunction;
Text txt = GameObject.Find ("Text").GetComponent<Text> ();
func.BeginPCall ();
func.Push (txt);
func.PCall ();
func.EndPCall ();
func.Dispose ();
lua.CheckTop ();
lua.Dispose ();
asset.Unload (false);
}
}
}通过WWW加载一个文本文件,里面的内容表达的是资源的版本号
版本号不同时,去下载远程的assetbundle,相同时,下载本地的assetbundle
assetbundle的资源中lua代码使用txt文件保存,使用TextAsset.string获取
使用www下载到AssetBundle后,通过AssetBundle对象获取文本文件TextAsset时,发现text属性内容为空,但是文本文件确实存在内容。原来是Unity的资源都是要通过它自己处理的,就是要经过导入这个过程,而我是直接在目录文件夹中创建的(没有重启Unity),所有识别不了。
.txt后缀结尾的,使用TextAsset的text获取。.bytes后缀结尾的,使用TextAsset的bytes属性获取。
有些资源,Unity不支持的是不能够打包到AssetBundle里面的,例如后缀为.lua的文件,我设置了它的assetbundle名字和后缀,导出的时候,在文件列表中却发现没有它,改为txt文件就可以了。
private string luaString = @"
local GameObject = UnityEngine.GameObject --获取类
local ParticleSystem = UnityEngine.ParticleSystem; --粒子组件
go = GameObject('go') --创建游戏物体
go:AddComponent(typeof(ParticleSystem)) --添加组件
local trsn = go.transform --获取Transform组件
trsn.position = Vector3.one --赋值属性
GameObject.Destroy(go,2) --2秒后移除物体
";
private LuaState lua;
// Use this for initialization
void Start () {
lua = new LuaState ();
lua.Start ();
lua.LogGC = true;
LuaBinder.Bind (lua);
lua.DoString (luaString);
}
void Update ()
{
lua.CheckTop ();
lua.Collect ();//专业回收垃圾
}
void Destroy(){
lua.Dispose ();
}Update中的lua.Collect(),如果没有了它,lua代码中Destroy了也没有效果
private string luaString = @"
function test(dic)
iter = dic:GetEnumerator()
while iter:MoveNext() do --遍历字典
print('key'.. iter.Current.Key .. 'value' .. iter.Current.Value)
end
keys = dic.Keys --获取字典的键值数组
values = dic.Values --获取字典值的数组
iter = values:GetEnumerator()
while iter:MoveNext() do
print(iter.Current)
end
local hehe,val = dic:TryGetValue(1,nil) --尝试获取键的值,第一个返回状态,第二个才是值
print(val)
dic:Remove(2) --移除键值为2的元素
--跟C#字典的操作一样
end
";
private Dictionary<int,string> dicc = new Dictionary<int, string>();
void Start () {
LuaState lua = new LuaState ();
lua.Start ();
lua.DoString (luaString);
dicc.Add (1, "hello");
dicc.Add (2, "world");
LuaFunction func = lua ["test"] as LuaFunction;
func.BeginPCall ();
func.Push (dicc);
func.PCall ();
func.EndPCall ();
foreach (var item in dicc) {
Debug.Log (item.Value); //只输出了hello
}
func.Dispose ();
lua.CheckTop ();
lua.Dispose ();
}private string luaString = @"
function tset(array)
--array是c#传进来的数组
len = array.Length --获取数组的长度
for i=0,len-1,1 do
print(array[i]) --和c#数组一样的下标方式访问
end
arrTable = array:ToTable()
for i=1,#arrTable do
print(arrTable[i])
end
iter = array:GetEnumerator()
while iter:MoveNext() do
print(iter.Current)
end
print(array:IndexOf(6))
end
";
// Use this for initialization
void Start () {
LuaState lua = new LuaState ();
lua.Start ();
lua.DoString (luaString);
int[] vals = { 1, 3, 5, 4, 6, 1 };
LuaFunction func = lua ["tset"] as LuaFunction;
func.BeginPCall ();
func.Push (vals);
func.PCall ();
func.EndPCall ();
func.Dispose ();
lua.Dispose ();
func = null;
lua = null;
}这里有三种遍历的方式,传入的c#数组,直接安装c#的数组那般使用就行了
也可以转换成Table,还有一个更灵活的GetEnumberator()方法
IndexOf()方法查找元素的下标,从0开始的(C#)
其实好像跟协程一样的写法
private string luaString = @"
function test(len)
print(len)
for i=1,10,1 do
coroutine.yield(i*10)
end
end
function start()
co = coroutine.create(test) --创造线程(协成?)
return co
end
";
// Use this for initialization
void Start () {
LuaState lua = new LuaState ();
lua.Start ();
lua.DoString (luaString);
LuaFunction func = lua ["start"] as LuaFunction;
//func.BeginPCall ();
//func.PCall ();
//LuaThread thread = func.CheckLuaThread (); 通过CheckLuaThread()获取返回值
//func.EndPCall ();
LuaThread thread = func.Invoke<LuaThread>(); //通过Invoke获得线程返回值
thread.name = "test"; //设置线程的名称,应该使用于区别的
for (int i = 0; i < 10; i++) {
int ret;
thread.Resume (10, out ret); //继续方法,传参和接收返回值
Debug.Log (ret);
}
thread.Dispose ();
func.Dispose ();
lua.Dispose ();
thread = null;
func = null;
lua = null;
}
private string luaString = @"
function cor()
print('coroutine start')
coroutine.wait(5) --等待几秒
print('5s ago')
print('frameCount:' .. Time.frameCount)
coroutine.step() --等待一帧
print('frameCount:' .. Time.frameCount)
local www = UnityEngine.WWW('http://www.baidu.com')
coroutine.www(www) --等待www响应
local s = tolua.tolstring(www.bytes)
print(s:sub(1,128))
end
local c = nil
function testCor()
c = coroutine.start(cor) --开始协成
end
function stopCor()
if c ~= nil then
coroutine.stop(c) --停止协成
end
end
";
private LuaState lua;
private LuaLooper looper;
private LuaFunction func;
// Use this for initialization
void Awake () {
lua = new LuaState ();
lua.Start ();
// 不执行绑定无法使用Wrap的函数,就是GameObject等Unity的内置类
LuaBinder.Bind (lua);
// 添加了这个组件后,它会在c#每一帧驱动lua的协同完成所有的协同功能,这里的协同已经不单单是lua自身功能,而是tolua#模拟unity的所有的功能.
looper = gameObject.AddComponent<LuaLooper> ();
looper.luaState = lua; //指定虚拟机
lua.DoString(luaString);
func = lua.GetFunction("testCor");
func.Call ();
LuaFunction stopFunc = lua ["stopCor"] as LuaFunction;
stopFunc.Call ();
stopFunc.Dispose ();
}
void Destroy(){
//擦屁股操作
func.Dispose ();
looper.Destroy ();
lua.CheckTop ();
lua.Dispose ();
func = null;
looper = null;
lua = null;
}private string luaString = @"
print(a)
b = 'hello'
c = {}
c.id = 16485
function test()
print('hehe')
end
";
// Use this for initialization
void Start () {
LuaState lua = new LuaState ();
lua.Start ();
lua["a"] = "这是我C#传过去的";
lua.DoString (luaString);
Debug.Log (lua ["b"]);
LuaTable t = lua ["c"] as LuaTable;
Debug.Log (t.GetStringField("id"));
t.Dispose ();
LuaFunction func = lua ["test"] as LuaFunction;
func.Call ();
func.Dispose ();
lua.CheckTop ();
lua.Dispose ();
}好像没什么好说的,都是通过LuaState 索引的形式设置和获取到变量,给予相应的类型