Sokuaisushi

In the project my team and I are currently working on we've seemingly ran into a huge roadblock.

In order to support older and lower end devices we added a quality setting to our game, which the user can change during the fights in our game (it's a cross between PunchOut and a political parody). In order to do this I would've liked to just be able to swap out the atlas at run-time with a performance variant, however as far as I can see this isn't possible with the C++/Cocos2d-x runtimes. (If this is possible, could you please point me in the right direction for it. I've been scouring the internet for a solution to this for days now and haven't turned up anything useful.)

To get around this we are disposing of the SkeletonAnimation object, and then creating a new one using the new texture atlas, this part works fine. But in order to maintain the state of the animation tracks before we dispose of the old skeleton we get a reference to the old skeleton's AnimationState, and try to apply this to the new skeleton...

This is where the issue begins, while this code seemingly works and positions the new skeleton in the same position of the animation that the old skeleton was in, the animation does not continue from that point. Until we play a new animation track the new skeleton will forever be in that frozen pose... For the life of me I can't seem to figure out how to maintain the AnimationState from the old skeleton to the new skeleton, and have the animation continue from that point.

So why is the skeleton frozen after using AnimationState->apply, and how do I get the skeleton to continue playing the animation from that point? Maintaining the AnimationState is vital for us because we use tons of TrackEntry's with their own lambda functions onTrackCompletion, independent of the animation itself but based on the state of the fighter, among other things.

I might not be explaining myself or what we are trying to accomplish very well, and am most likely doing something wrong or unintended to achieve this. Any advice and suggestions to fix this system would be greatly appreciated, as I'd rather not have to tell the player that all graphics changes will take place in the next fight... Thank you for your time!

TLDR; I get the AnimationState from a SkeletonAnimation object, create a new SkeletonAnimation object with the same JSON but a different atlas. I then use animationState->apply(*newSkeleton->getSkeleton()), which sets the new skeleton into the correct pose of the correct animation. The problem being that the new skeleton is frozen in that pose until we do newSkeleton->setAnimation(...).
Software Engineer at Firecracker Software currently working on Election Year Knockout!
Аватара пользователя
Sokuaisushi
  • Сообщения: 3

badlogic

In principal, AnimationState is stateless. However, timelines inside animations managed by AnimationState are not quite. The offender here is likely DeformTimeline, which keeps a reference to an attachment to be deformed by it.

Would it be possible for you to whip up a small repro for this? We've had similar reports and I'd like a real world-ish thing I could try to use and improve the API with so this is more easily possible.
Аватара пользователя
badlogic

Mario
  • Сообщения: 2127

Sokuaisushi

badlogic писал(а):In principal, AnimationState is stateless. However, timelines inside animations managed by AnimationState are not quite. The offender here is likely http://esotericsoftware.com/spine-api-reference#DeformTimeline, which keeps a reference to an attachment to be deformed by it.

Would it be possible for you to whip up a small repro for this? We've had similar reports and I'd like a real world-ish thing I could try to use and improve the API with so this is more easily possible.
I must've misunderstood the documentation. I understood AnimationState to be stateful, while AnimationStateData was stateless... If AnimationState is stateless, how should I go about maintaining the state from the old skeleton to the new skeleton?

I will look into the DeformTimeline as well, thank you for the link!

As for a small repro for this issue, it goes something like this:
void PlayerNode::setGraphicsQuality(SettingsManager::GraphicsSettings quality)
{
bool isLowQuality = quality == SettingsManager::GraphicsSettings::LOW;
float renderScale = SCALE_NORMAL; // 1.0f

auto animationState = _spine->getState();

spine::SkeletonAnimation* newSpine;

if(isLowQuality) {
renderScale = SCALE_PERFORMANCE; // 0.25f

newSpine = spine::SkeletonAnimation::createWithJsonFile(SPINE_PATH("player_character.json"), SPINE_PATH("perf_player_character.atlas"), renderScale / Director::getInstance()->getContentScaleFactor());
} else {
newSpine = spine::SkeletonAnimation::createWithJsonFile(SPINE_PATH("player_character.json"), SPINE_PATH("player_character.atlas"), renderScale / Director::getInstance()->getContentScaleFactor());
}

newSpine->setToSetupPose();
animationState->update(0);
animationState->apply(*newSpine->getSkeleton());

this->removeChild(_spine);

_spine = newSpine;

// Add the new spine to our PlayerNode
this->addChild(_spine);
_spine->onEnter();

// Register the event and completion listeners that the old skeleton used.
_spine->setCompleteListener(CC_CALLBACK_1(PlayerNode::onSpineComplete, this));
_spine->setEventListener(CC_CALLBACK_2(PlayerNode::onSpineEvent, this));
}
Here SettingsManager::GraphicsSettings is an enum class with only LOW and HIGH. The PlayerNode is an extension of the Cocos2d-x Node class which maintains a reference to it's spine::SkeletonAnimation, among other things pertaining to the player character.

If you'd like me to create a small Cocos2d-x project to repro these issues too, I'd be more than happy to oblige!

Thanks for your time badlogic!
Software Engineer at Firecracker Software currently working on Election Year Knockout!
Аватара пользователя
Sokuaisushi
  • Сообщения: 3

badlogic

Yeah, a small Cocos2d-x project that actually tries to swap out the textures would be fantastic!
Аватара пользователя
badlogic

Mario
  • Сообщения: 2127

Sokuaisushi

badlogic писал(а):Yeah, a small Cocos2d-x project that actually tries to swap out the textures would be fantastic!
Not a problem! Just give me a little time to create the project as we are preparing for a city fair this weekend to show off the game and have some changes that need to be done first.
Software Engineer at Firecracker Software currently working on Election Year Knockout!
Аватара пользователя
Sokuaisushi
  • Сообщения: 3


Вернуться в Runtimes