rkamalya1

Hi.

I have static spine objects in my game that have no animations.
However, these functions are getting called for them.
SkeletonRenderer.LateUpdate();
SkeletonAnimation.Update();
My code looks like this:
playerAnim = (SkeletonAnimation)gameObject.AddComponent("SkeletonAnimation");
playerAnim.skeletonDataAsset = playerData; // playerData is the SkeletonAsset
playerAnim.skeletonDataAsset.atlasAssets[0].Reset();
playerAnim.skeletonDataAsset.Reset();
playerAnim.state = new Spine.AnimationState(playerAnim.skeletonDataAsset.GetAnimationStateData());
playerAnim.calculateNormals = true;
playerAnim.loop = false;
playerAnim.Reset();


To disable that component I've added the following:
playerAnim.enabled = false;
playerAnim.LateUpdate ();
but objects disappeared from the scene.

p.s. I need to colour the slots of that spine object and I'm getting slots from
playerAnim.skeleton.Slots
Any help is appreciated!
rkamalya1
  • Posts: 5

Pharan

Hello

What you're doing is a special case where your SkeletonAnimation only exists at runtime and not in Unity editor.
(I think this is a little unusual, but certainly valid use if you have a LOT of skeleton jsons and making a prefab for each one is nonsense.)
The setup procedure is a bit specific in this case. There may even be an un-accounted-for bug. So let's run through this.

Normally, an existing SkeletonAnimation that was set up in the editor will have its Awake called first.
The current design does these in this order:
  1. Scene starts. Objects get deserialized. Unity calls Awake. Awake calls Reset.
  2. SkeletonRenderer's Reset runs first. It instantiates the components internal meshes and the vertex buffer for rendering.
  3. It will force the SkeletonData JSON to parse and load if it wasn't loaded already, then instantiate a new Spine.Skeleton. (it will orphan an old Skeleton of it existed)
  4. Then it calls LateUpdate once which causes it to initially render the skeleton's base pose.
  5. Then SkeletonAnimation's Reset runs. This will instantiate a new Spine.AnimationState based on the data you typed into your SkeletonDataAsset.

By the end of all this, the Spine data structures should have already been instantiated, and your mesh should already have been generated and visible.

But, if the SkeletonAnimation/SkeletonRenderer's skeletonDataAsset field was null, it will stop at Step 2.

This is important: In Unity, calling AddComponent will immediately call that component's Awake method before the AddComponent method returns.

This means using AddComponent to instantiate a SkeletonAnimation will (1) always throw an error complaining that there wasn't a skeletonDataAsset assigned. But you can fix that with some small edits to SkeletonRenderer.cs (2) need you to call Reset yourself after you've assigned proper values in its fields.

Therefore, I expect your code to work properly if you did this:
playerAnim = (SkeletonAnimation)(gameObject.AddComponent<SkeletonAnimation>());
// gives you an error. "Missing SkeletonData asset." That's okay. Carry on.

// assign the right values.
playerAnim.skeletonDataAsset = playerData;
playerAnim.calculateNormals = true;
playerAnim.loop = false;

// Now that the values are there. Call Reset.
playerAnim.Reset();

// The mesh should have been rendered by Reset's LateUpdate call at this point. You can now disable it.
playerAnim.enabled = false;
I could be wrong. Please share your findings.

Whenever you change the colors of slots, you need to call playerAnim.LateUpdate() so the mesh colors update.

EDIT: Dear future reader, this code does not work. Please see my next post below.
User avatar
Pharan
  • Posts: 5366

rkamalya1

playerAnim.enabled = false;
removes the object from the scene and it is no longer visible.
rkamalya1
  • Posts: 5

Pharan

Thanks for reporting back. I can confirm there's a bug somewhere. We're still looking into it.
For now, this should work:
playerAnim = (SkeletonAnimation)(gameObject.AddComponent<SkeletonAnimation>());

// Assign the right values.
playerAnim.skeletonDataAsset = playerData;
playerAnim.calculateNormals = true;
playerAnim.loop = false;

playerAnim.enabled = false;

playerAnim.Reset(); // Load the data and prepare the necessary objects.
playerAnim.skeleton.UpdateWorldTransform();
playerAnim.LateUpdate(); // Build the mesh.
User avatar
Pharan
  • Posts: 5366

rkamalya1

Thanks, worked like a charm! :)
rkamalya1
  • Posts: 5


Return to Runtimes