AssetBundle(四) Tolua对接

本文介绍了如何使用Tolua对接AssetBundle,讨论了两种lua存储和读取的方案,并提供了对接的两个关键步骤:自定义Lua加载类以适应bundle加载,以及重写或扩展ToLuaMenu以符合项目需求。文章强调了bundle命名规范,以及在开发和发布模式下lua文件处理的差异。

上一篇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,相当于示范,也方便我们用自己的资源管理模块对接,将其替换掉。这实际上是很不错的设计。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值