[一个简单的游戏框架]tolua相关

Mar 9, 2018


[https://github.com/HushengStudent/myGameFramework]

1、tolua集成

关于tolua的集成主要参考LuaFramework_UGUI,实现自己的LuaMgr。


//参考(https://github.com/jarjin/LuaFramework_UGUI)集成tolua;  
    public class LuaMgr : MonoSingleton<LuaMgr>   
    {  
        private LuaState lua;  
        private LuaLoaderUtility loader;  
        private LuaLooper loop = null;  
  
        public override void Init()  
        {  
            base.Init();  
            //...  
        }  
  
        public override void AwakeEx()  
        {  
            base.AwakeEx();  
            //初始化LuaMgr;  
            loader = new LuaLoaderUtility();//TODO:Lua AssetBundle的使用;  
            lua = new LuaState();  
            this.OpenLibs();  
            lua.LuaSetTop(0);  
            LuaBinder.Bind(lua);  
            DelegateFactory.Init();  
            LuaCoroutine.Register(lua, this);  
        }  
          
        /// <summary>  
        /// 初始化加载第三方库;  
        /// </summary>  
        void OpenLibs()  
        {  
            lua.OpenLibs(LuaDLL.luaopen_pb);  
            //lua.OpenLibs(LuaDLL.luaopen_sproto_core);  
            //lua.OpenLibs(LuaDLL.luaopen_protobuf_c);  
            lua.OpenLibs(LuaDLL.luaopen_lpeg);  
            lua.OpenLibs(LuaDLL.luaopen_bit);  
            lua.OpenLibs(LuaDLL.luaopen_socket_core);  
            this.OpenCJson();  
        }  
  
        //cjson比较特殊,只new了一个table,没有注册库,这里注册一下;  
        protected void OpenCJson()  
        {  
            lua.LuaGetField(LuaIndexes.LUA_REGISTRYINDEX, "_LOADED");  
            lua.OpenLibs(LuaDLL.luaopen_cjson);  
            lua.LuaSetField(-2, "cjson");  
            lua.OpenLibs(LuaDLL.luaopen_cjson_safe);  
            lua.LuaSetField(-2, "cjson.safe");  
        }  
  
        public void StartLuaMgr()  
        {  
            InitLuaPath();  
            InitLuaBundle();  
            this.lua.Start();    //启动LUAVM;  
            this.StartMain();  
            this.StartLooper();  
        }  
  
        /// <summary>  
        /// 初始化Lua代码加载路径;  
        /// </summary>  
        void InitLuaPath()  
        {  
            lua.AddSearchPath(LuaConst.luaDir);  
            lua.AddSearchPath(LuaConst.luaResDir);  
        }  
  
        /// <summary>  
        /// 初始化LuaBundle;  
        /// </summary>  
        void InitLuaBundle()  
        {  
            if (loader.beZip)  
            {  
                //loader.AddBundle("lua/lua.unity3d");  
            }  
        }  
  
        void StartLooper()  
        {  
            loop = gameObject.AddComponent<LuaLooper>();  
            loop.luaState = lua;  
        }  
  
        void StartMain()  
        {  
            lua.DoFile("Main.lua");  
            LuaFunction main = lua.GetFunction("Main");  
            main.Call();  
            main.Dispose();  
            main = null;  
        }  
  
        public void DoFile(string filename)  
        {  
            lua.DoFile(filename);  
        }  
  
        // Update is called once per frame;  
        public object[] CallFunction(string funcName, params object[] args)  
        {  
            LuaFunction func = lua.GetFunction(funcName);  
            if (func != null)  
            {  
                return func.LazyCall(args);  
            }  
            return null;  
        }  
  
        public void CallLuaModuleMethod(string funcName, params object[] args)  
        {  
            LuaFunction func = lua.GetFunction(funcName);  
            if (func != null)  
            {  
                func.Call(args);  
            }  
        }  
  
        public void CallLuaTableMethod(string module, string funcName, params object[] args)  
        {  
            LuaFunction func = lua.GetFunction(module+"."+ funcName);  
            LuaTable table = lua.GetTable(module);  
            if(func!=null && table != null)  
            {  
                func.Call(table,args);  
            }  
        }  
  
        public void LuaGC()  
        {  
            lua.LuaGC(LuaGCOptions.LUA_GCCOLLECT);  
        }  
  
        public void Close()  
        {  
            loop.Destroy();  
            loop = null;  
  
            lua.Dispose();  
            lua = null;  
            loader = null;  
        }  
    }  

2、C#调用Lua

①在C#中调用Lua的方法:

C#调用Lua文件的方法:如 xxx.func() 这种形式:LuaMgr:

public void CallLuaModuleMethod(string funcName, params object[] args)  
        {  
            LuaFunction func = lua.GetFunction(funcName);  
            if (func != null)  
            {  
                func.Call(args);  
            }  
        }  

C#调用Lua类中的的成员方法,如 xxx:func() 这种形式:LuaMgr:

需要先拿到对应对Table:


public void CallLuaTableMethod(string module, string funcName, params object[] args)  
        {  
            LuaFunction func = lua.GetFunction(module+"."+ funcName);  
            LuaTable table = lua.GetTable(module);  
            if(func!=null && table != null)  
            {  
                func.Call(table,args);  
            }  
        }  

这是两者调用时,点号和冒号的区别。

3、Lua调用C#

在CustomSettings中配置需要被Lua调用的类并导出,在Lua中就可以直接调用。

如参考logUtility的使用。

4、tolua中的事件系统

源文件:myGameFramework\Client\Assets\LuaFramework\ToLua\Lua\event.lua

5.tolua中的定时器

源文件:myGameFramework\Client\Assets\LuaFramework\ToLua\Lua\System\Timer.lua

简单示例:

function Game.Test()  
      
end  
  
function Game.Init()  
    tim = Timer.New(Game.FunTest,1, -1, true)   
--参数1为调用的方法名,参数2为间隔时间,参数3为循环次数(当为-1时无限循环)  
--参数4为是否忽略时间的Scale,scale false 采用deltaTime计时,true 采用 unscaledDeltaTime计时  
    tim:Start()  
end  

5、protoc-gen-lua使用

tolua自带pblua,使用pblua生成lua代码需要配置相关环境: ⑴.解压myGameFramework\File\Source\pblua\protobuff\protobuf-python-3.0.0.zip 到C盘。 ⑵.解压myGameFramework\File\Source\pblua\protobuff\protoc-3.0.0-win32.zip 把Protoc放到protobuf/src下。 ⑶.使用protobuf的python版本必须在2.6以上,protoc的版本要与protobuf的版本保持一致。 ⑷.如果python2.7的版本大于2.7.9,在安装python时setuptools已自动安装,否则则需要手动。 ⑸.cmd进入到protobuf/python 执行以下命令:

python setup.py build
python setup.py install

⑹.致此pblua环境搭建完成。 ⑺.myGameFramework\Tools\protoc-gen-lua-master 为pblua工作目录,已经解压好了。 ⑻.参考代码:PbLuaEditor.cs:


public static void BuildPb2Lua()  
        {  
            paths.Clear();  
            files.Clear();  
            Recursive(pbluaDir);  
            int index = 0;  
            foreach (string f in files)  
            {  
                index++;  
                string name = Path.GetFileName(f);  
                string ext = Path.GetExtension(f);  
                string workPath = Path.GetDirectoryName(f);  
                if (!ext.Equals(".proto")) continue;  
                EditorUtility.DisplayProgressBar("Build PbLua File", "gen proto to lua:" + name, index / files.Count);  
                ProcessStartInfo info = new ProcessStartInfo();  
                info.FileName = protoc;  
                info.Arguments = " --lua_out=./ --plugin=protoc-gen-lua=" + protoc_gen_dir + " " + name;  
                info.WindowStyle = ProcessWindowStyle.Hidden;  
                info.UseShellExecute = true;  
                info.WorkingDirectory = workPath;  
                info.ErrorDialog = true;  
                LogUtility.Print("gen proto to lua:" + name);  
                Process pro = Process.Start(info);  
                pro.WaitForExit();  
            }  
            EditorUtility.ClearProgressBar();  
            AssetDatabase.Refresh();  
        }  

执行该方法,就能生成pb文件对应的lua文件。

6、protogen使用

pb可以生成Lua代码,当然同时也需要生成对应对C#文件,供服务器使用,部分协议客户端也需要使用到C#形式的协议文件:

pb生成C#使用到了protogen: ⑴.解压myGameFramework\File\Source\pblua\protobuff-net\protobuf-net-r668.zip。 ⑵.打开项目下protobuff-net工程,生成。 ⑶.打开ProtoGen工程,生成。 ⑷.其中ProtoGen工程生成的protogen.exe即可以拿来用proto文件生成C#代码。 ⑸.参考代码:PbLuaEditor.cs:


public static void BuildPb2Csharp()  
        {  
            paths.Clear();  
            files.Clear();  
            Recursive(pbluaDir);  
            int index = 0;  
            foreach (string f in files)  
            {  
                index++;  
                string name = Path.GetFileName(f);  
                string ext = Path.GetExtension(f);  
                string workPath = Path.GetDirectoryName(f);  
                if (!ext.Equals(".proto")) continue;  
                //输出目录;  
                string outPath = GetCsharpPath(f);  
                if (null == outPath) continue;  
                if (!Directory.Exists(outPath))  
                {  
                    Directory.CreateDirectory(outPath);  
                }  
                string fileName = Path.GetFileNameWithoutExtension(f);  
                EditorUtility.DisplayProgressBar("Build PbLua File", "gen proto to c#:" + name, index / files.Count);  
                ProcessStartInfo info = new ProcessStartInfo();  
                info.FileName = protogen;  
                info.Arguments = "-i:" + name + " -o:" + outPath + "/" + fileName + ".cs -p:detectMissing";  
                info.WindowStyle = ProcessWindowStyle.Hidden;  
                info.UseShellExecute = true;  
                info.WorkingDirectory = workPath;  
                info.ErrorDialog = true;  
                LogUtility.Print("gen proto to c#:" + name);  
                Process pro = Process.Start(info);  
                pro.WaitForExit();  
            }  
            EditorUtility.ClearProgressBar();  
            AssetDatabase.Refresh();  
        }  

也是使用C#函数调用应用程序根据一定的参数生成对应的C#文件。

客户端与服务器之间通信使用protobuf-net,导入protobuf-net会报错,存在不安全代码,只需要在Asset目录加入mcs.rsp文件即可:


-unsafe