quick 3.3 "异步"加载Spine方案.md

quick 3.3 "异步"加载Spine方案.md,第1张

概述背景 项目中, 使用了quick 3.3, 由于Spine各个功能相当强大, 所以使用了Spine作为骨骼动画, 但是Spine并非cocos官方支持,因此在一些问题上支持性不是那么好,其中如何异步加载Spine就是一个问题。 比如游戏中经常遇到这么一个问题:在主战斗场景中, 需要加载大量的图片、声音、Spine动画等, 如果我们等用到的时候再去加载,由于文件I/O是比较耗时的, 有可能就会在游戏 背景

项目中, 使用了quick 3.3, 由于Spine各个功能相当强大, 所以使用了Spine作为骨骼动画, 但是Spine并非cocos官方支持,因此在一些问题上支持性不是那么好,其中如何异步加载Spine就是一个问题。

比如游戏中经常遇到这么一个问题:在主战斗场景中, 需要加载大量的图片、声音、Spine动画等, 如果我们等用到的时候再去加载,由于文件I/O是比较耗时的, 有可能就会在游戏过程中造成卡顿的现象,在低端配置手机中体现尤为明显,这或大或小造成游戏体验不佳。

对于这个问题呢, 一种比较常用的解决方案:在进入主战斗之前, 先预加载战斗中大量耗时的资源(并不一定要是所有资源),并且缓存起来,等到真到需要用到的时候,直接去读取缓存中的数据。

比如很多游戏看到的Loading条, 就是用的这种方案。

难点

1、异步加载
cocos本身已经支持了一些资源的异步加载回调, 使用多线程做的,每加载完一个资源,都可以有异步回调作相应的处理(比如显示加载进度)。但是 对于一些cocos官方不支持的资源,比如Spine等,就需要自己实现异步加载回调。

自己实现我知道有两种方法。
一种就是和cocos官方的一样, 也用多线程做, 这个没什么好说的。
一种就是叫做”同步异步化“,开启一个每帧都update函数,在update()里加载一次资源,用同步的方式实现异步加载资源,这种方法叫做:”同步异步化”。
在Lua中还有另一种方法可以实现,就是用Lua的协程,更加的方便。

我自己使用的是使用的update这种方法。

function LoadingLayer:update(ts)   -  --- 每帧加载一次资源    local pngNum = table.nums(ResMng._pngList)    local pListNum = table.nums(ResMng._pListList)    local soundNum = table.nums(ResMng._soundList)    local spineNum = table.nums(ResMng._spineList)    local curLoadNum = ResMng._curLoadNum    -- 加载资源顺序    -- 1、加载PNG    if 0 <= curLoadNum and curLoadNum < pngNum then        ResMng.loadpng()    -- 2、加载PList    elseif pngNum <= curLoadNum and curLoadNum < pngNum + pListNum then        ResMng.loadPList()    -- 3、加载SOUND        elseif pngNum + pListNum <= curLoadNum and curLoadNum < pngNum + pListNum + soundNum then        ResMng.loadSound()    -- 4、加载Spine    elseif pngNum + pListNum + soundNum <= curLoadNum and curLoadNum < pngNum + pListNum + soundNum + spineNum then        ResMng.loadSpine()    else        print("所有资源预加载完成")        ResMng.resortSpine()        self:replaceScene()    end end

2、Spine缓存
cocos 官方都对一些常用的资源支持了缓存,如TextureCache、AnimationCache、SpirteFrameCache、AudioCache, 但是由于Spine并非官方支持,所以对于Spine的缓存需要自己实现, 对于Spine缓存实现方式, 也有两种方法可以参考:
1、在C++层,实现一个和官方类似的缓存方案, 叫做SpineCache,然后增加tolu层代码,这种方式优雅、自然,但是代价比较大
2、在Lua层手动实现一个简易的缓存方案
这里我当然是使用的第二种方案了。

-- 加载一次Spine图function ResMng.loadSpine()    local spineInfo = self._spineList[self._curLoadindex]    assert(spineInfo,"加载Spine索引出错" .. self._curLoadindex)    local spineAnimation = require("app.common.factory.sp_animation").new()    spineInfo.animation = spineAnimation:createWithID(spineInfo.ID)    spineInfo.animation:getNode():retain()    self._curLoadNum = self._curLoadNum + 1    if self._curLoadindex == #self._spineList then        self._curLoadindex = 1    else        self._curLoadindex = self._curLoadindex + 1    endend-- 从缓存中获取Spinefunction ResMng.getSpineByID(spineID)    -- 如果不存在此资源,先加载到缓存    if not self._spineList[spineID] then        print("缓存文件:",spineID)        local spineAnimation = require("app.common.factory.sp_animation"):new()        self._spineList[spineID] = spineAnimation:createWithID(spineID)        self._spineList[spineID]:getNode():retain()    end    local newSpine = require("app.common.factory.sp_animation"):new()    return newSpine:createWithData(self._spineList[spineID])end

3、导出createWithData到Lua层调用
Spine Runtime,加载Spine有两种方式。
一个是createWithfile,使用的是文件IO方式,这个相当耗时
一个是createWithData,使用的是已经加载好的Spine的骨骼数据,这种方法速度比较快。
但是quick 默认两个方法都不自动导出, 都是用的手写代码导出,且只手动导出createWithfile,如果我们需要使用createWithData,这时就需要手动导出了,导出代码如下:
LuaSkeletonAnimation.h

class LuaSkeletonAnimation: public spine::SkeletonAnimation {public:    static LuaSkeletonAnimation* createWithfile (const char* skeletonDatafile,const char* atlasfile,float scale = 1);    static LuaSkeletonAnimation* createWithData(SkeletonAnimation* spineData);    LuaSkeletonAnimation (const char* skeletonDatafile,float scale = 1);    LuaSkeletonAnimation(SkeletonAnimation* spineData);    virtual ~LuaSkeletonAnimation();};

LuaSkeletonAnimation.cpp

LuaSkeletonAnimation::LuaSkeletonAnimation (const char* skeletonDatafile,float scale): spine::SkeletonAnimation(skeletonDatafile,atlasfile,scale){}LuaSkeletonAnimation::LuaSkeletonAnimation(SkeletonAnimation* spineData): spine::SkeletonAnimation(spineData){}LuaSkeletonAnimation* LuaSkeletonAnimation::createWithfile (const char* skeletonDatafile,float scale){    LuaSkeletonAnimation* node = new (std::nothrow) LuaSkeletonAnimation(skeletonDatafile,scale);    node->autorelease();    return node;}LuaSkeletonAnimation* LuaSkeletonAnimation::createWithData(SkeletonAnimation* spineData){    LuaSkeletonAnimation* node = new (std::nothrow) LuaSkeletonAnimation(spineData);    node->autorelease();    return node;}

lua_cocos2dx_spine_manual.cpp

//add by chenhao on 2015/03/24//手动添加Spine tolua代码,解决Spine缓存问题 static int lua_cocos2dx_CCSkeletonAnimation_createWithData(lua_State* L){    if (nullptr == L)        return 0;    int argc = 0;#if COCOS2D_DEBUG >= 1    tolua_Error tolua_err;    if (!tolua_isusertable(L,1,"sp.SkeletonAnimation",&tolua_err)) goto tolua_lerror;#endif    argc = lua_gettop(L) - 1;    if (1 == argc)    {#if COCOS2D_DEBUG >= 1        if (!tolua_isusertable(L,&tolua_err))        {            goto tolua_lerror;        }#endif        SkeletonAnimation* spineData = (SkeletonAnimation*)tolua_tousertype(L,2,0);        auto tolua_ret = LuaSkeletonAnimation::createWithData(spineData);        int nID = (tolua_ret) ? (int)tolua_ret->_ID : -1;        int* pLuaID = (tolua_ret) ? &tolua_ret->_luaID : NulL;        toluafix_pushusertype_ccobject(L,nID,pLuaID,(voID*)tolua_ret,"sp.SkeletonAnimation");        return 1;    }    luaL_error(L,"'createWithfile' function of SkeletonAnimation has wrong number of arguments: %d,was expecting %d\n",argc,2);#if COCOS2D_DEBUG >= 1tolua_lerror:    tolua_error(L,"#ferror in function 'createWithData'.",&tolua_err);#endif    return 0;}

并且在extendCCSkeletonAnimation()中,添加下面这行代码。

tolua_function(L,"createWithData",lua_cocos2dx_CCSkeletonAnimation_createWithData);

为了减少导出自定义类, 我对C++层createWithData的参数类型作了一些修改,但是不影响。改为了:

static SkeletonAnimation* createWithData(SkeletonAnimation* spineData);

以上都是本人自己实现摸索过程中, 探索出来的一些方法,有什么问题大家可以提出来,我好修改。

http://www.jb51.cc/article/p-nawkknxq-bhs.html

总结

以上是内存溢出为你收集整理的quick 3.3 "异步"加载Spine方案.md全部内容,希望文章能够帮你解决quick 3.3 "异步"加载Spine方案.md所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1051403.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存