Xlua Examples学习(一)

01_HellowWorld

主要看 new LuaEnv() 里面具体干了什么

void Start () {
    LuaEnv luaenv = new LuaEnv(); //新建一个lua虚拟机
    luaenv.DoString("CS.UnityEngine.Debug.Log('hello world')");
    luaenv.Dispose();             //关闭lua虚拟机
}

02_U3DScripting

主要看 LuaBehaviour.cs 绑定.lua.txt的方法

为什么要把.lua转化为.txt加载

先说结论:

不一定要转化为txt后使用。例子中仅仅是为了方便,把lua文件后加.txt后缀作为TextAsset,就可以被unity识别。

下面说细节:

  • Unity识别不了.lua这种资源,因此既不能拖动到编辑器里,也不能像普通资源那样被识别出依赖关系并打包。

  • 标准做法是:lua文件通过自己的custumLoader加载进来。lua文件本身存放在哪里呢?

  • 放到 Resources 目录下这种方案不行,虽然会被打入包中,但和其他东西一起变成了整体,无法通过文件名提取出来。

  • 放到 StreamingAsset 目录下这种方案貌似可以,由于其不压缩,故可以保留原始的目录信息。但由于该目录只读,因此不可用于存放热更时新下载下来的lua脚本。而且还是无法用Unity提供的加载API,需要自定义的loader加载。

Unity知识:Resources vs StreamingAssets

Resources 和 StreamingAssets 相同点

  • 都会将文件夹中的资源打包

Resources 和 StreamingAssets 区别

LuaBehaviour.cs 做了什么

  • 所有LuaBehaviour共用一个Lua虚拟机(名叫 luaEnv),lua全局空间叫luaEnv.Global。注意并没有在mono脚本中关闭lua虚拟机。

  • 一个LuaBehaviour拥有自己的一个LuaTable(名叫 scriptEnv)作为lua本地空间,并且其元表的__index设置为luaEnv.Global。在mono自己OnDestroy的时候,调用scriptEnv.Dispose()释放回收。

  • 往lua本地空间里塞了c#的引用

    scriptEnv.Set("self",this); 
    //这样可以在绑定的lua脚本中通过 self 访问到LuaBehaviour这个mono类。
  • 从lua本地空间里获取了函数的引用。并在需要的时候调用。

    //这两种Get效果一样
    luaAwake = scriptEnv.Get<Action>("awake");
    scriptEnv.Get("start", out luaStart);
    //xlua还提供一种GetInPath可以按照A.B.C访问lua的表,更多见《Xlua_API》.doc

为什么用 [System.Serializable] 修饰一个非mono类

首先贴代码。

[System.Serializable]
public class Injection
{
    public string name;
    public GameObject value;
}

在LuaBehaviour的Awake方法中有一段:

public Injection[] injections;

void Awake()
{
    foreach (var injection in injections)
    {
        scriptEnv.Set(injection.name, injection.value);
    }
}

可以看到 Injection类提供了将gameObject自动注册到本地空间的功能。在编辑器中,可以将gameObject拖动到LuaBehaviour暴露的变量上面。这就要求 Injection 可序列化。因此必须用[System.Serializable]

绑定的lua脚本里写了什么

  • 读写UnityC#的静态属性、方法,使用前缀CS.。因为在新建LuaEnv的时候,在init_xlua中将这些都存在了名为CS的表中。

local GameObject = CS.UnityEngine.GameObject  -- 先用局部变量引用后访问,能提高性能
GameObject.Find('helloworld')

local r = CS.UnityEngine.Vector3.up * CS.UnityEngine.Time.deltaTime * speed
self.transform:Rotate(r)   -- 访问成员函数用冒号

03_UIEvent

主要掌握给按钮绑定lua回调的方法。注意冒号和点号的使用。

self:GetComponent("Button").onClick:AddListener(function() print("ddd") end)
-- GetComponent(string)本来就是C#的写法,和GetComponent<T>()效果一样
-- 这里的self是LuaBehaviour中传入的指向该cs脚本的this,而不是lua这边的语法糖什么的

下一篇将继续分析示例代码。

Last updated