在cocos2d-lua中,当使用craete方法同时创建加载多个骨骼动画时,会发生卡顿。因为在每次调用craete方法时,都需要先生成一次skeletonData数据。如果可以将skeletonData数据事先加入到缓存中,然后直接用缓存的skeletonData数据去生成骨骼动画,就可以优化卡顿的问题。
先看看如何实现对skeletonData数据进行缓存。
实现将资源数据加入缓存的lua方法如下:
--将skeletonData数据加入缓存
function addSkeletonDataToCache(cacheName,jsonStr,atlasStr)
--参数是否正确
if not cacheName or not jsonStr or not atlasStr then
return;
end
--是否已经存在于缓存中
if sp.SkeletonAnimation:isExistSkeletonDataInCache(cacheName) then
return;
end
--资源是否存在
if not cc.FileUtils:getInstance():isFileExist(jsonStr) or not cc.FileUtils:getInstance():isFileExist(atlasStr) then
return;
end
sp.SkeletonAnimation:readSkeletonDataToCache(cacheName, jsonStr, atlasStr);
end
--将skeletonData数据从缓存中移除
function removeSkeletonDataFromCache(cacheName)
--是否存在于缓存中
if not sp.SkeletonAnimation:isExistSkeletonDataInCache(cacheName) then
return;
end
sp.SkeletonAnimation:removeSkeletonData(cacheName)
end
可以在预加载资源的时候,通过调用上述实现的addSkeletonDataToCache方法将骨骼动画数据加入缓存中。
例如:
addSkeletonDataToCache(“testCacheName”, "test.json", "test.atlas");
在需要使用的时候,通过以下方式调用(使用缓存时定义的名字)。
local testAnimation = sp.SkeletonAnimation:createFromCache("testCacheName");
testAnimation:setAnimation(0, "test", true);
self:addChild(testAnimation);
在不需要的时候,通过removeSkeletonDataFromCache将其从缓存中移除。
-------------------------------------------------以下是分析部分-------------------------------------------------
在cocos2d-lua中,通常情况下,我们使用create
方法创建骨骼动画。
例如:
local testAnimation = sp.SkeletonAnimation:create("test.json", "test.atlas");
testAnimation:setAnimation(0, "test", true);
self:addChild(testAnimation);
来看一下lua中注册的create
方法如下。
tolua_function(L, "create", lua_cocos2dx_CCSkeletonAnimation_createWithFile);
可以发现,create方法其实就是SkeletonAnimation类中的createWithFile
方法,查看createWithFile
方法源码如下:
SkeletonAnimation* SkeletonAnimation::createWithFile (const std::string& skeletonDataFile, spAtlas* atlas, float scale) {
SkeletonAnimation* node = new SkeletonAnimation(skeletonDataFile, atlas, scale);
node->autorelease();
return node;
}
SkeletonAnimation* SkeletonAnimation::createWithFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale) {
SkeletonAnimation* node = new SkeletonAnimation(skeletonDataFile, atlasFile, scale);
node->autorelease();
return node;
}
可以看到,createWithFile可以接受两种形式的参数,上述例子中使用的是所示代码中的第二种形式,所以简单看一下第二种方式的源码实现流程。
SkeletonAnimation::SkeletonAnimation (const std::string& skeletonDataFile, const std::string& atlasFile, float scale)
: SkeletonRenderer(skeletonDataFile, atlasFile, scale) {
initialize();
}
SkeletonRenderer::SkeletonRenderer (const std::string& skeletonDataFile, const std::string& atlasFile, float scale)
: _atlas(0), _debugSlots(false), _debugBones(false), _timeScale(1) {
initWithFile(skeletonDataFile, atlasFile, scale);
}
void SkeletonRenderer::initWithFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale) {
_atlas = spAtlas_createFromFile(atlasFile.c_str(), 0);
CCASSERT(_atlas, "Error reading atlas file.");
spSkeletonJson* json = spSkeletonJson_create(_atlas);
json->scale = scale;
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile.c_str());
CCASSERT(skeletonData, json->error ? json->error : "Error reading skeleton data file.");
spSkeletonJson_dispose(json);
setSkeletonData(skeletonData, true);
initialize();
}
在lua源码中,除了create方法外,还可以看到一个创建骨骼动画的方法,那就是createFromCache
。
tolua_function(tolua_S,"createFromCache", lua_cocos2dx_spine_SkeletonAnimation_createFromCache);
来看一下它的C++实现:
SkeletonAnimation* SkeletonAnimation::createFromCache(const std::string& skeletonDataKeyName)
{
if (spSkeletonData* skeleton_data = getSkeletonDataFromCache(skeletonDataKeyName,true)){
SkeletonAnimation* node = new SkeletonAnimation(skeleton_data, false);
node->skeletonDataKeyName = skeletonDataKeyName;
node->autorelease();
return node;
}
return nullptr;
}
SkeletonAnimation::SkeletonAnimation (spSkeletonData *skeletonData, bool ownsSkeletonData)
: SkeletonRenderer(skeletonData, ownsSkeletonData) {
initialize();
}
SkeletonRenderer::SkeletonRenderer (spSkeletonData *skeletonData, bool ownsSkeletonData)
: _atlas(0), _debugSlots(false), _debugBones(false), _timeScale(1) {
initWithData(skeletonData, ownsSkeletonData);
}
void SkeletonRenderer::initWithData (spSkeletonData* skeletonData, bool ownsSkeletonData) {
setSkeletonData(skeletonData, ownsSkeletonData);
initialize();
}
与之前的create方法对比可以发现,createFromCache
是直接使用skeletonData来初始化骨骼动画的,省去了中间创建skeletonData的过程,所以效率会高很多。而create方法在每次调用的时候,都需要先生成skeletonData数据。