• Runtimes
  • [Unity] Mecanim now supported in Unity 4 and 5!

Related Discussions
...

Hey! First post here :-)

Thanks Mitch for creating the SkeletonAnimator. I just started using Spine (it's been in my todo list forever) with Unity 5. Against all advice, I'm using mecanim since I'm familiar with the kind of state machines you can create with that (and I can't be arsed to create my own State Machine solution from scratch right now). Your SkeletonAnimator is working like a charm! I can "navigate" the state machine and see the animation change to what I created on Spine. Yay!

My next step is to use events. You said they have the same limitation as when you baked the animation using the previous system (SkeletonAnimation?). That makes me happy, because it seems to imply that I can use Spine events with mecanim in Unity 5. The problem is that I don't see where to hook my delegate to listen for events. I've been searching the C# and Unity runtimes but it only seems to exist hooks in AnimationState (old system). The docs also point to AnimationState. Can we listen to Spine events when using mecanim?

soy_yuma ha scritto

You said they have the same limitation as when you baked the animation using the previous system (SkeletonAnimation?).

He means it's using Unity's Animation events, not Spine-C#'s events.
SkeletonAnimator (and Mecanim) don't touch Spine.AnimationState (where the Spine event delegates live).
SkeletonAnimator also doesn't interface with Spine.EventTimeline.

I'm actually not sure where the events are defined for SkeletonAnimator. I guess in the "dummy" animation clips?

That is awesome!

I'm still a newbie on Spine+Unity (in case it wasn't evident before), so I didn't know there were Unity events. I'll have a look. Thanks a bunch!

18 giorni dopo

Hi Mitch,

I'm brand new to Spine, so please forgive any stupidity in this post. It looks like I've picked up your latest with the unity package runtime, so I can use the create animation controller action you outlined above. But I'm not really understanding how to configure it, or even the intention here


When I instantiate the controller via Spine->InstantiateMecanim, it looks like it generates a mecanim anim controller that flattens all animations to interface with a single GO: "Game Object.Dummy". How is this configured? I see that the SkeletonData seems to retain linkage to the animator once this is done, which I assume is to aid in iteration. But when I generate a new SkeletonAnimation via Spine->InstantiateSkeletonAnim, it doesn't include the new Animation Controller. When I connect the Spine generated animation controller, it complains that it can't find the Dummy object. Am I missing something fundamental here?

Also, just so I'm clear, this is intended as a "lighter" approach to allowing mecanims to control animation state without incurring (most of) the functionality hits of baking it completely into Unity. Am I completely mistaken here? I hope not, because it seems like exactly what I want.

Thanks!


Jeremy

There are 3 ways to go from Spine


making things move in Unity at the moment.

1) Instantiate -> SkeletonAnimation
This is the "Spine" way. All features supported.

2) Instantiate -> Mecanim (or SkeletonAnimator)
This creates a scene graph object and a dummy RuntimeAnimationController with proxy AnimationClips that match the name and length of the SkeletonData associated with your Spine JSON or Binary file. The Dummy property is there simply so Mecanim thinks the animations are the correct length. The SkeletonAnimator component applies animations using the Spine API's Animation Mix and Apply functions. This allows use of Mecanim graphs with the Spine API directly which is a standard Unity animation workflow. It might have a few side effects in terms of attachment keyframes... somewhat hard to track down. This method keeps everything up to date with the SkeletonData.

I think what you might be missing is that it is also generating an object in your Scene Graph in addition to generating the Controller (if it didn't already exist). SkeletonAnimation and SkeletonAnimator are generally interchangeable and both support things like SkeletonUtility.

3) Baking
This removes all dependence on the Spine API. Mesh, Skinned Mesh, and Prefab assets are generated for each Skin, AnimationClips are generated, and a RuntimeAnimationController is generated. This doesn't support all of the features present in the native Spine API however, so it has limits, but it does remove all dependence on the Spine codebase which is necessary for pushing say... an animated character into the Asset Store as the Spine runtime is not distributable to people who don't own Spine. It is also useful to simply use Spine as a rigging tool for simple things without the overhead of the full runtime.

Thanks for the speedy response


I was out Friday, but am looking at this again today.

Aha


I think I get it now. I was sort of stuck on what option #2 was actually doing, but if the Dummy object is only for timing purposes, that makes sense. Just so I get a sense of workflow, how brittle is that animator/animation set when iterating in Unity? As in, if I put some custom function call hooks within an individual animation or substates/conditionals within the animator, will that all need to be redone if I update something like an animation length in the Spine editor (requiring a rebuild from the json upon reimport)?

So far so good though, I have gotten it to work with a custom mecanim state machine, thanks again for the help!

Only the clips themselves get updated, the Graph isn't touched.

Okay, that's what I was hoping


thanks Mitch!

I've got most of it working, but I've moved onto events and had another question. It seems that the general technique for managing events is interfacing via the AnimationState, but I don't know how to query for that when using a SkeletonAnimator.

I am able to receive Spine events as Unity/mecanim style events on the mecanim timeline


though, admittedly, assuming the string name of the event as a hardcoded function call seems a little bizarre, perhaps they should at least be prefixed with "SpineEvent_" for clarity/name-collision safety? Or maybe use something more similar to the way you do your Spine attributes, with a [SpineStringEvent("EventName", "FuncMapping")] style approach?

Anyways, how would you go about getting the Complete/End generic events without AnimationState? Or, maybe a better question: how would you get the AnimationState from SkeletonAnimator?

Also


unrelated: it seems that if you have an animation without any textures in it (a guide animation), the Unity plugin will fail to produce any of the skeleton data exports from the json. Putting a junk texture in there seems to fix the problem, probably just a minor bug.

Thanks again, this has been very helpful!


Jeremy

Err I missed something in my post 🙂

Events are handled the Unity way. The dummy clips also contain AnimationEvent that are mostly equivalent to spine events. TL;DR it uses sendmessage


Anyways, how would you go about getting the Complete/End generic events without AnimationState? Or, maybe a better question: how would you get the AnimationState from SkeletonAnimator?

In unity 5 you can write graph behaviors for mecanim. Good hunting heh

AnimationState does not exist within Skeleton Animator

Okay, I'll use unity graph behaviors for the complete (OnStateEnter) and end (OnStateExit) events.

So I'm seeing a lot of weird twitchy graphical behaviors (such as flipping on the x-axis in the middle of an animation) that I don't see when using a standard skeleton animation. Is there something that I may have misconfigured? Or maybe you have an updated build with some bug fixes?


Oops


nevermind about the twitchy behavior, it was something I had misconfigured. I believe this was caused when I mistakenly had some blending in one of my transitions, causing some very strange results.

Thanks ~ things are looking good with this integration, I like being able to use u5's state machines in my project!

Hi jeremy,

Can you go a bit into details what the problem was and how you solved it?
I seem to have some twitchy behaviors too (flipping X axis). I can indeed pinpoint it to having blending in the mecanim setup.
However, I actually DO want to have blending enabled when switching between animations, so I'm wondering if you managed to somehow have them without the glitches?

I basically turned blending off in mecanim for now to fix any animation weirdness. I'm still not entirely sure what the dummy anims are doing and if blending should actually work via mecanim. I assume the blending could be handled by the Spine animation engine, but I'm not sure if mecanim is able to feed Spine enough information for it to operate properly


this was noted earlier as an issue with mecanim integration in u4.x, maybe u5 solved the problem. Obviously, Mitch would have a lot greater insight here, and maybe lay out some best practices.

Blending works great for Pos/Rot/Scale and well enough for Attachment keys... I've seen some wonkiness in the others. I haven't had a chance to really use the mecanim stuff in one of my own projects but I'll take a look at it sooner or later.

 Loading Image

Animation blending glitches fix.
Check animator state info and apply only that is valid.

 Loading Image

Always apply attachment animation is better for timing, layer mixing.

un mese dopo

I might be missing something obvious, but it seems like there's something wrong with the mecanim animations generated by spine.

Upon dragging in the files in unity, the skeleton is generated automatically as it should. I went ahead and clicked "Generate Mecanim Controller".
The controller get's generated perfectly fine, with the one animation we have inside as it should.
 Loading Image

I then right-click the skeleton and select Spine > Instantiate( Mecanim ), which also generates a correct gameobject ( I presume)
 Loading Image

However, when looking at the animator window, there are no states.
 Loading Image

Same story for the animations window
 Loading Image

I guessed I could just drag in the animation from the animator asset file, but then I end up with some missing stuff, and there is no animation visible.
 Loading Image

Any idea what I could be doing wrong?
Thanks!

Working as intended. Hit the scene Play button after setting up your state. Sorry there isn't a way to scrub an animation using this mode, Unity might expose the things I need to make that happen eventually 🙂

The Dummy track is there simply to represent the duration of the Spine animation, so Mecanim doesn't try to blend as if its a 0 frame animation.

Events are also written to the standard Unity Animation event track as well. (IE: using SendMessage to fire events)

Mitch ha scritto

Working as intended. Hit the scene Play button after setting up your state. Sorry there isn't a way to scrub an animation using this mode, Unity might expose the things I need to make that happen eventually 🙂

The Dummy track is there simply to represent the duration of the Spine animation, so Mecanim doesn't try to blend as if its a 0 frame animation.

Events are also written to the standard Unity Animation event track as well. (IE: using SendMessage to fire events)

Oh right, in all my confusion it seems like I forgot to actually run the game haha. The animation doesn't seem to be looping though, I tried to enable "Loop time" and "Loop Pose" on the animationclip, but that didn't seem to make a difference.

I will probably stick to using the Skeleton Animation though and call SetAnimation() in a StateBehaviour on the corresponding state.

Loop Time should work just fine... just enable it, go to File Save Project, and close/re-open unity a few times... Mecanim in 5.x is a totally buggy PoS.

14 giorni dopo

Hey Mitch,

First of all great work! I learned quite a bit about Spine and Unity by just studying your code and the rest of the runtime. I ran into an issue, however, and I managed to fix it. So I'd like to get your opinion, and maybe include it officially.

I had the same problem as in this thread (http://esotericsoftware.com/forum/Adding-new-animations-to-Mecanim-Controller-4199). The expected behavior was to export from Spine directly into the Assets folder, and have the SkeletonData asset as well as the Mecanim controller asset reflect all changes made in Spine. After digging around a bit, adding this line to SkeletonBaker solved all my problems:

 Loading Image

You make an assumption about the path for the controller, because it is the place you created it in the first place. However, when I moved it to a different location, the resulting behavior is that objs is empty, because there is no controller at the assumed path.

Therefore animations get added again instead of updated, and animations that were deleted stay in the controller.

Hope this helps!

Regards,
Hadi


Rouven ha scritto

@[cancellato] That didn't change anything, unfortunately. I have disabled and even removed my second (upper body) layer in the Animator, but the issues persist within the Base Layer.

I just noticed the keys that are dropped are only those that attach an image to a slot. All Scale/Rotate/Translate keyframes are applied just fine.

I experienced the same issue with dropping frames for attaching an image to a slot.

I'm on my phone right now, I can explain the reason for it later if you need it. Here's the line in spine c# runtime that you need to comment out to stop it from happening.

 Loading Image

Regards,
Hadi