找回密码
 立即注册
查看: 322|回复: 0

AssetBundle(四) Tolua对接

[复制链接]
发表于 2021-8-11 18:44 | 显示全部楼层 |阅读模式
上一篇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,相当于示范,也方便我们用自己的资源管理模块对接,将其替换掉。这实际上是很不错的设计。
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 07:15 , Processed in 0.090543 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表