• Editor
  • [Unity] SkeletonComponent overriding AnimationState changes?

  • Editado

Hey. Still a bit confused here. But after taking a closer look at the C# AnimationState class, I have a better idea of how it does things.
But there's this block in the SkeletonComponent.Update() method in the Unity runtime that I find peculiar:

// Keep AnimationState in sync with animationName and loop fields.
if (animationName == null || animationName.Length == 0) {
	if (state.Animation != null) state.ClearAnimation();
} else if (state.Animation == null || animationName != state.Animation.Name) {
	Spine.Animation animation = skeleton.Data.FindAnimation(animationName);
	if (animation != null)
		state.SetAnimation(animation, loop);
}
state.Loop = loop;

Based on the Spineboy example in Unity, the expectation is to change the value of the string animationName and this block takes care of changing the AnimationState accordingly (by calling SetAnimation for you).

But it seems like it would also negate any attempts to use AnimationState's methods like AddAnimation or ClearAnimation and it would also simply just stop the queue system from working at all, 'cause it would just give a higher priority to the string animationName and call SetAnimation based on it whenever (animationName != state.Animation.Name).

Should I/can I safely remove this block and not rely on the change-this-string-to-change-the-animation interface?
I might be missing something though.

UPDATE (June 2013):
Fixed since May 2013. SkeletonComponent has since been refactored as SkeletonAnimation and the new default expects you to call SetAnimation (which plays the animation immediately) or AddAnimation (which adds an animation to the AnimationState's queue), not change the string. The latter behavior is still available but it's slightly less efficient and also still makes AnimationState's queuing capability nonfunctional.

Related Discussions
...
  • Editado

Yeah, I don't really like that bit of code. 🙁 We have String animationName on SkeletonComponent so that the Inspector UI can set the animation name. Then we have the AnimationState, which actually stores the state. Which of these two is the authority? You're right that it will override the queue. Definitely this needs to be fixed, though I'm not sure how to best solve it. Does this happen in other cases in Unity? How is it solved there?

I'm not really sure. I'm kinda new to Unity so I don't know how other plugins handle it. 🙁

If it helps at all, I don't think the ability to change the animation clip in the Inspector UI dropdown while the game is running is either super useful or standard. Unity's own native animation component UI doesn't behave like that either, as far as I know. It just allows you to set the initial animation.

In which case, the AnimationState could just be the authority and the string-sync could stay if you wanted the Inspector UI to at least show what animation is currently playing in the inspector while the game is running.

Alternatively, you could also just change the field in the UI to say something like "Initial Animation" and use the string only once to set the animation in on initialization— ie, SkeletonComponent's Start() method.

A third option might be to have an extra boolean that's accessible through the UI which switches authority between the string and the AnimationState, but give priority to the AnimationState by default. This way, we could keep the animation changing-on-the-fly-through-UI feature.

I guess your worry was still standardization and a clean interface, but I'm getting the impression that you'd be the first, or one of the few, to actually implement an animation changing through UI feature.

Again, that's just me. I definitely think other, more experienced people need to weigh in on this.

un mes más tarde

Hi Nate, I have a problem implementing custom actions for unity playmaker.

The only way i manage to change animations correctly is using AnimationName

I think the problem is what Pharan described, AnimationName override any attempts to use SetAnimation, AddAnimation.

this is the code

using UnityEngine;

namespace HutongGames.PlayMaker.Actions
{
    [ActionCategory("2D Spine")]
    [Tooltip("Set Animation. \nNOTE: The Game Object must have a SkeletonAnimation attached.")]
public class SpineAnimationName : FsmStateAction
  {
     [RequiredField]
     [Tooltip("The Game Object to work with. NOTE: The Game Object must have a SkeletonAnimation component attached.")]
     
[CheckForComponent(typeof(SkeletonAnimation))] public FsmOwnerDefault gameObject; [RequiredField] [Tooltip("The Animation name to play")] public FsmString AnimationName; public FsmBool aloop; private SkeletonAnimation skeletonAnimation; private void _getSkeletonAnimation() { GameObject go = Fsm.GetOwnerDefaultTarget(gameObject); if (go == null) { return; } skeletonAnimation = go.GetComponent<SkeletonAnimation>(); } public override void Reset() { gameObject = null; AnimationName = null; aloop = false; } public override void OnEnter() { _getSkeletonAnimation(); SetAnimation(); }
void SetAnimation() { if (skeletonAnimation == null) { LogWarning("Missing skeletonAnimation component"); return; } else { skeletonAnimation.animationName = AnimationName.Value; skeletonAnimation.loop = aloop.Value; } } } }

SkeletonAnimation has a useAnimationName field. If false, SkeletonAnimation won't mess with the AnimationState. By default it is false, it is only set to true when you change the animation in the Uinty inspector.

So, if i use

skeletonAnimation.state.SetAnimation(AnimationName.Value, aloop.Value);

is ok?

For some reason it didn't work.

I removed the skeletonAnimation component, and put it again, and now it works. 🙂

Yeah. I think Unity's side does some extra things when you set it up the first time. (Haven't really looked into it in detail. I suspect it's some weird initialization behavior of class fields.).

Our original problem was fixed last month though. Glad it's working for you now.

state.SetAnimation should work just fine with the new default. I've been using it for weeks.