让你的游戏支持热更新 - 在Unity3D中使用lua

发表于2015-04-29
评论1 5k浏览

1、在Unity中引入lua的主要原因:

     1.1,Unity不支持代码热更新

     C#在ios平台不支持热更新,在Android平台热更新也比较麻烦,而lua支持热更新。

    1.2,为了能够前后台复用关键逻辑代码

     Unity前台使用C#,后台使用C或C++,属性计算和战斗系统代码无法复用,通过lua可以方便实现前后台关键逻辑代码共用。

 

2、lua插件的选择:

    2.1 UniLua

    云风团队的作品,纯C#实现,但使用起来很麻烦,比较鸡肋。

     2.2 uLua    

     uLua是 Lua 、LuaJIT 、LuaInterface的集合,Unity主流的lua插件, AssertStore上售价40美刀。    C#调用lua脚本和从lua脚本中访问C#对象都方便,接下来我们简单了解一下uLua,然后通过一个简单的Demo来深入了解uLua的使用。

 

3、C#调用lua脚本

         基本保持了和C++相同的调用方式,对于用过tolua++的同学非常亲切       

// 初始化lua脚本 //

FLuaMgr.Instance.Init();

 

// 调用Test.lua中的 lua脚本函数//

FLuaMgr.Instance.PCall("Test.ChangeMyClassProperty");

 

 4、lua访问C#对象属性及函数

         uLua利用.Net的反射机制,直接从dll中导出C#类定义。

         这一块功能是通过Lua.cs实现的,具体实现机制比较复杂,我们看一个简答的例子:

         4.1 导入C#类

UnityEngine     = luanet.UnityEngine

System          = luanet.System

 

--- UnityEngine Classes---

Debug           = UnityEngine.Debug

GameObject      = UnityEngine.GameObject

Camera          = UnityEngine.Camera

Transform       = UnityEngine.Transform

 

--- Our Classes ---

luanet.load_assembly('Assembly-CSharp')

MyClass = luanet.import_type('MyClass')

 

       通过这几句代码,我们就将UnityEngine的Debug、GameObject、Camera、Transform类导入进来了,此外将我们自定义的C#类MyClass也导入进了lua。这比用tolua++导出C++对象简单多了。

        4.2 在lua使用使用C#导入类

local myClass = GameObject.Find("MyClass"):GetComponent("MyClass");

 

myClass.DisplayName = "ChangedName From Lua";

local box1 = myClass:DrawBox(1);

 

         GameObject .Find和GetComponent是Unity常用函数,通过uLua可以在lua中直接访问,这是uLua的重要优势。

         此外我们定义类MyClass的属性和函数也可以同样方便的调用,这样扩展起来非常方便。

 

 5加载lua脚本的优化

         创建一个LuaState, 然后使用LuaState的DoString就可以加载lua脚本;

LuaState luaState = new LuaState();

luaState.DoString("print('hello world')");

 

         这样虽然可以加载lua,但是这并不能满项目需求,笔者封装了一个FLuaMgr

        在FLuaMgr的Init函数中加载lua文件下的所有lua文件: 

// 直接读取TextAsset//

private bool DoDirFilesByTextAsset(string path)

{

    TextAsset[] luaCodes = Resources.LoadAll(path);

    for (int i = 0; i < luaCodes.Length; i++)

    {

        string fileName = luaCodes[i].name;

        //Debug.Log("FileName=" + fileName);

        int prefabEnd = fileName.LastIndexOf(GenLuaFileEnding); // 判断是否是lua文件 //

        if (prefabEnd <= 0)

        {

            FDebug.LogWarning("FileName=" + fileName + " is not a lua file!");

            continue;

        }

 

        DoString(luaCodes[i].text, fileName);

    }

 

 

    // 卸载lua脚本文件 //

    Resources.UnloadUnusedAssets();

    return true;

}

 

      5.1 Unity 只能识别.txt文件文件的解决办法

       在Assets/Lua 文件夹编辑lua脚本,然后通过ConvertToLuaTxt 转化到Assets/LuaGen文件夹下。具体内容参考Demo中的ConvertToLuaTxt.cs

 

6、Unity中嵌入lua的Demo介绍

         将附件中的uLuaExample.unitypackage 导入到一个空的Unity项目,然后打开LuaTest.unity,直接运行,lua脚本调用MyClass的函数绘制若干个矩形、球和圆柱体。

-- 调用C#对象的函数

function DrawSomeBoxes()

              -- 直接调用GameObject的导出函数Find,类导出查看ImportClass.lua

              local myClass = GameObject.Find("MyClass"):GetComponent("MyClass");

             

              -- 调用我们的C#类MyClass.DrawBox(float size)

              local box1 = myClass:DrawBox(1);

              box1.transform.position = Vector3(-5,-2.5,0);

             

              local box2 = myClass:DrawBox(1.25);

              box2.transform.position = Vector3(-5,-1.0,0);

             

              local box3 = myClass:DrawBox(1.5);

              box3.transform.position = Vector3(-5,1.5,0);

end

 

        执行效果图:

         http://km.oa.com/files/post_photo/457/212457/a260125f42ac6bd986c926bb52df30e1.jpg

         创建对象和位置排列逻辑由Test.lua实现。

7、lua执行效率

         7.1 加载所有lua脚本的消耗

                   笔者所在的项目有13个lua文件,lua脚本总行数1127行。

                   http://avocado.oa.com/fconv/files/201408/f92ca7b1476fe355ba47c4f26743fb9c.files/image002.jpg

                   在华为荣耀3手机上初始化lua平均耗时270ms。

         7.2 执行简单的lua函数的效率:

function SimpleLuaFunc()

              local id = 1;

              if (id < 1)

              then

                            print("id < 1");

              end

end

 

         http://avocado.oa.com/fconv/files/201408/f92ca7b1476fe355ba47c4f26743fb9c.files/image003.gif

         一次简单的lua调用平均耗时9微秒,性能在可接受的范围内。

 

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引