• Runtimes
  • Efficiently create multiple instance from data - bug?

Hey, I am trying to make some custom Cocos2DX examples to get to know the engine better.

As far as I can see, the "automatic" method:

spine::SkeletonAnimation::createWithJsonFile

doesn't seem to be efficient in case you want to create lots of copies of an animated object. The correct way is probably this:

  • create atlas from file
  • create skeleton data from atlas + (json) file
  • create as many instances as you like from skeleton data

Well, that crashes when I try to

addChild

the created instance in my scene. Here is my crashing code:

   if (true)
   {
// this works
      skeletonInstance = spine::SkeletonAnimation::createWithJsonFile(PATH + "goblins.json", PATH + "goblins.atlas", 1.f);
      addChild(skeletonInstance);
      skeletonInstance->setPosition(400, 300);
      skeletonInstance->setAnimation(0, "walk", true);
      skeletonInstance->setSkin("goblin");
   }
   else
   {
// this crashes at render time
      spAtlas* atlas = spAtlas_createFromFile((PATH + "goblins.atlas").c_str(), 0);
      spSkeletonJson* json = spSkeletonJson_create(atlas);
      json->scale = 1.f;
      spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, (PATH + "goblins.json").c_str());
      if (!skeletonData) {
         CCLOG("OOPSA: %s\n", json->error);
         //exit(0);
      }
      skeletonInstance = spine::SkeletonAnimation::createWithData(skeletonData, true);
      addChild(skeletonInstance);
      spSkeletonJson_dispose(json);
   }

crash info:

Exception thrown: read access violation.
attachmentVertices->_triangles was 0x2D.

in file

SkeletonRenderer.cpp, line 226

I've checked how

spine::SkeletonAnimation::createWithJsonFile

works, and it seems it has these lines different:

_attachmentLoader = SUPER(Cocos2dAttachmentLoader_create(_atlas));
spSkeletonJson* json = spSkeletonJson_createWithLoader(_attachmentLoader);

The spine docs IIRC don't mention that the attachmentLoader is essential, but maybe it is? Or is it a library (spine-cpp) bug? Or what? 🙂

Related Discussions
...

Thanks, I got it. Now for some memory management 😉

When do I destroy the intermediate data? I mean:

  • spAtlas*
  • spAttachmentLoader*

I destroy them immediately after disposing the spSkeletonJson like this and I am not getting any errors. Is this the correct way to handle them or should they stay in memory cause they may be required?

spAtlas* atlas = spAtlas_createFromFile((PATH + "goblins.atlas").c_str(), 0);         // parses atlas
spAttachmentLoader* attachmentLoader = &(Cocos2dAttachmentLoader_create(atlas)->super);   // knows how to atlas -> cocos2dx textures
spSkeletonJson* json = spSkeletonJson_createWithLoader(attachmentLoader);            // create json loader with help from above
json->scale = 1.f;
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, (PATH + "goblins.json").c_str());   // parsed json -> skeleton data

spSkeletonJson_dispose(json); // no longer needed, since we have our data
spAtlas_dispose(atlas); // no longer needed ???
spAttachmentLoader_dispose(attachmentLoader); // no longer needed ???

if (!skeletonData) {
   CCLOG("OOPSA: %s\n", json->error);
   //exit(0);
}
for (int i = 0; i < 100; ++i)
{
   skeletonInstance = spine::SkeletonAnimation::createWithData(skeletonData, false); // own=true => destroy the data when instance expires!
   addChild(skeletonInstance);
   skeletonInstance->setPosition(random(0.,1000.), random(0.,700.));
   skeletonInstance->setAnimation(0, "walk", true);
   skeletonInstance->setSkin("goblin");
}

We've written an extensive guide on spine-c, on which the cocos2d-x runtime is based, including memory management.

Have a look at the cocos2d-x batching sample, that shows how to instantiate multiple skeletons from the same (shared) data. As you can see, the shared data (skeleton data, animation state data, atlas, attachment loader), is disposed when the scene is deconstructed. spine-runtimes/BatchingExample.cpp at master