|
上一篇Assetbundle(三)场景和Navmesh加载
下一篇 AssetBundle(五) 关于SceneManager.LoadScene
ToLua虽然支持Bundle,但是其实现很难应用于实际项目。没有引用计数,不支持其他资源打包,而且还有WWW之类已经过时的Bundle技术。但,瑕不掩瑜,Tolua本身是很优秀的。如果项目有一套完善的支持bundle的资源管理模块,对接Tolua很方便,只需要改两点就能对接好。
在说对接步骤之前,先说下Lua如何存放和读取的问题。游戏包打好以后,本身就带lua的bundle。能想到有两种做法,一种是把包内的lua的bundle,读出来,放到沙盒目录,以后读取lua都从沙盒目录,更新也是更新沙盒目录。总之和包内的lua就没关系了。这样做不是不行,问题在于要把包内的lua写到沙盒去,这个过程时间有点长。这样首次运行时间太长了。而且lua更新和其他资源的更新流程不一致。
推荐第二种方案,就是包内的lua以bundle的形式存在,不用拷贝并解压到沙盒。我们只要做到能读取bundle中lua即可。至于lua的更新,还是走bundle更新,跟之前的博文讲的其他资源的bundle更新一个流程。这种方案相比第一种,无论是效率还是更新逻辑,整体统一性都是更好的选择。
对接只需要做2步
1.写一个Lua加载类,继承Tolua的LuaFileUtils,重载ReadFile,实现自己的lua加载
LuaFileUtils是Tolua中负责加载lua的一个类,Tolua本身也有几个其派生类,但都不是很理想,更多的是用于示范。我们要实现的这个派生类,只需要实现两点。即是开发模式下(非bundle)和发布模式(用bundle)。如果是开发模式和父类差不多,如果是发布模式用自己Bundle接口读出来,再返回bytes
2.根据需要重写ToLuaMenu类中关乎bundle生成的函数BuildNotJitBundles
[MenuItem("Lua/Build bundle files not jit", false, 55)] public static void BuildNotJitBundles() { ClearAllLuaFiles(); CreateStreamDir(GetOS()); 这个类是Tolua的菜单编辑器类。我们只需要修改其中打Bundle的函数即可。实际上我并没有改,而是另写了一个,相当于打bundle不走Tolua的菜单了,而走自己写的菜单。两个原因导致这个类需要自己实现
(1)实际项目中目录规则和Tolua可能不同
(2)最重要的一点是,这个只打Lua的Bundle,实际项目中还有其他资源需要打Bundle。难道我们需要打bundle的时候,资源和lua按不同的菜单打吗?
需要注意的是,bundle的名字不能带反斜杠目录分隔符。我的框架里是“_”代替"/" ,否则在打bundle时会出现不能创建目录的错误。这个错误不是必出,在Unity2017.1.0f3就会出现。
下面是我市的类,LuaLoader ,负责接管ToLua中的lua加载。
using UnityEngine;using LuaInterface;using System.IO;using System.Text;namespace UFrame.ToLua{ /// <summary> /// 接管Tolua的读取lua,从UFrame的资源管理模块读取lua /// beZip 无效 /// </summary> public class LuaLoader : LuaFileUtils { public LuaLoader() { instance = this; beZip = false; } public override byte[] ReadFile(string fileName) { if (!fileName.EndsWith(".lua")) { fileName += ".lua"; }#if !RES_AB string path = FindFile(fileName); byte[] str = null; if (!string.IsNullOrEmpty(path) && File.Exists(path)) {#if !UNITY_WEBPLAYER str = File.ReadAllBytes(path);#else throw new LuaException("can't run in web platform, please switch to other platform");#endif } return str;#else fileName += ".bytes"; var getter = ResHelper.LoadAsset(fileName); var res = getter.Get<TextAsset>(ResHelper.GetPubAssetGetterGo()); return res.bytes;#endif } }} 上面代码的意思是,如果没有定义RES_AB,那属于开发模式,直接从项目目录读取lua;如果是Bundle模式,从ResHelper加载,然后返回TextAsset.bytes。ResHelper是我的框架中读取资源的帮助类。
代码中,如果不是以“.lua”结尾的要加上,因为require是不加.lua后缀的。如果是发布模式,在加了“.lua”的基础上又加了一个".bytes"的后缀,这是因为lua文件不能直接打bundle,加这个后缀就可以打,当然也可以选择加“.txt”。这一步在打包的代码中就要加上。相当于打包的不是".lua"文件,而是“.lua.bytes”文件。这种文件是个拷贝,不是直接改,主要是为了不影响开发模式。
不是Tolua做不好Bundle,而是Tolua不知道具体的项目需求是什么。因为lua加载在项目通常也是资管管理模块的,这个模块除了lua之外还有其他资源。在这种情况下,Tolua自己实现了一套bundle,相当于示范,也方便我们用自己的资源管理模块对接,将其替换掉。这实际上是很不错的设计。 |
|