• Unity
  • Switching visible skeleton while maintaining animations

Hi guys, I'm working with characters that have skeletons for multiple views (the front view and the back view).

Right now I'm setting animations and updating both SkeletonAnimations, but only rendering the Mesh for the one that should currently be visible (disabling the other mesh). This would be fine except that the characters in this game are pretty complex and are taking up quite a bit of CPU. I would like to figure out a way that I can only update one SkeletonAnimation at a time instead of both.

The reason I was setting the animations / updating both skeletons is that I need to be able to switch from front view to back view (and vice versa) on the fly, and need the character to be at the correct position within the animations when the switch happens. AKA if a character is halfway through the jump animation, and switches to the other view, its already at the correct halfway point in the animation and everything looks correct.

So my question is - instead of always updating both views, is it possible to do this:
1) Disable all updating (disable the SkeletonAnimation?) on the view that isn't currently being shown.
2) On the frame where the view needs to switch from the previous one to the disabled one, re-enable it and copy all relevant animation-information (track entries?) from the previous view and apply them to the one that just got enabled.
3) Disable the previous view

I'm trying to think of all of the animation info that would be necessary to "reproduce what is currently happening". Is it as simple as just copying the all Track Entries from the previously-shown view to the newly-enabled view? I use the same animation names, etc on both Skeletons. I use multiple tracks, empty animations, and timescaling, so all of that would have to be reproduced.

Thanks for any help, and if I need to explain anything in more detail let me know! 🙂

Related Discussions
...

Thinking about your requirements, the easiest way would be to have an option to continue animation (update AnimationState) but not apply the animation timelines and not generate the mesh. I will add the requirement to this issue ticket, it should actually fit in quite nicely anyway:
[unity] Provide two step frustum culling at SkeletonRenderer · #1595

Regarding copying AnimationState status:
It would be possible to copy the state of the AnimationState over to the other SkeletonAnimation object, but this could be rather error-prone, do you really want a perfect copy here? Just out of curiosity: would a shared AnimationState work at your Skeleton setup, in terms of identical animation names, slot names, etc?


We will let you know once the above feature in the issue ticket is implemented.

Harald wrote

Thinking about your requirements, the easiest way would be to have an option to continue animation (update AnimationState) but not apply the animation timelines and not generate the mesh. I will add the requirement to this issue ticket, it should actually fit in quite nicely anyway:
[unity] Provide two step frustum culling at SkeletonRenderer · #1595

That would be awesome! :cooldoge:

Harald wrote

Regarding copying AnimationState status:
It would be possible to copy the state of the AnimationState over to the other SkeletonAnimation object, but this could be rather error-prone, do you really want a perfect copy here? Just out of curiosity: would a shared AnimationState work at your Skeleton setup, in terms of identical animation names, slot names, etc?

I'm not sure that I know enough about AnimationState to reply correctly - does AnimationState do anything besides keeping track of the current animations that are playing/queued (Track Entries) and their mixtimes (AnimationStateData)?

I don't think I would need a 'perfect copy' (as in, a 'clone' of the AnimationState) - I think I would essentially just need to reproduce the Track Entries.

As far as a shared AnimationState goes - I don't quite think I'd be able to do that. Most of the animations for both views are the exact same names, but the bones/slots/images would have different names. There also may be specific cases where I might want to play an ongoing looping animation on just the front view / back view. Also we definitely tweak the mix timings for the front/back views separately. Would have been a neat idea though 😃

Harald wrote

We will let you know once the above feature in the issue ticket is implemented.

Thanks! I think that option would be quite handy, and would be a nice clean implementation :yes:

We can gladly announce that this feature has just been implemented. 8)

From the changelog:

Added frustum culling update mode parameters Update When Invisible (Inspector parameter) and UpdateMode (available via code) to all Skeleton components. This provides a simple way to disable certain updates when the Renderer is no longer visible (outside all cameras, culled in frustum culling). The new UpdateMode property allows disabling updates at a finer granularity level than disabling the whole component. Available modes are: Nothing, OnlyAnimationStatus, EverythingExceptMesh and FullUpdate.

A new 3.8 unitypackage is available for download here as usual:
Spine Unity Download

Hope you like it!

Harald wrote

We can gladly announce that this feature has just been implemented. 8)

From the changelog:

Added frustum culling update mode parameters Update When Invisible (Inspector parameter) and UpdateMode (available via code) to all Skeleton components. This provides a simple way to disable certain updates when the Renderer is no longer visible (outside all cameras, culled in frustum culling). The new UpdateMode property allows disabling updates at a finer granularity level than disabling the whole component. Available modes are: Nothing, OnlyAnimationStatus, EverythingExceptMesh and FullUpdate.

A new 3.8 unitypackage is available for download here as usual:
Spine Unity Download

Hope you like it!

Woohoo! Looks awesome! Going to try implementing it tomorrow :yes: Thanks a lot as always!

You're welcome! Please let us know if there is anything missing that we didn't think of.

This works great!

Here is my understanding of how it works for anyone else reading:

-In the inspector for whichever Skeleton component you're using you set the "Update When Invisible" mode to whichever mode you want.
-When the Mesh Renderer component goes from being visible to not visible, whether by going off-screen (frustum culled) or by having the Mesh Renderer component itself disabled, the Skeleton will switch its UpdateMode to what you set "Update When Invisible" to. Note that if you have the Scene view window open and can still see the Skeleton in that window, the Mesh Renderer is still considered visible (even if it is off-screen in your Game view window).
-When the Mesh Renderer becomes visible again, the UpdateMode will be set to FullUpdate.

In my specific case, I have a semi-complex set up for a character who has a frontside view SkeletonAnimation, and a backside view SkeletonAnimation, and each of those use Skeleton Render Separators - so instead of using the default Mode switching (based on the Mesh Renderer isVisible, as mentioned above) I simply set the UpdateMode when I switch between the views. Since in my specific case I want the front and back view Skeletons to be at the same points in their animations (so that I can switch from showing the front to the back at any point in time. I apply the same animations to both views), I set the UpdateMode to OnlyAnimationStatus on the view that is 'hidden'. (Note that I already had a setup in place that disables/enables the mesh renderers for the "Parts Renderers" since I am using the Skeleton Render Separators). Also, when I then want to show the view that is hidden, I set the UpdateMode back to FullUpdate and also call skeletonAnimation.Update(0); so that the Skeleton's bones/etc are updated immediately to the correct positions. If I don't call that Update(0) it seems that the Mesh can get rendered for one frame at the old position before it is updated.

The characters in my game are high-detail with lots of bones and layers of animations, so this option to update the AnimationState without applying it to the Skeleton is great. It cuts my Spine-related CPU usage in half for any characters that have both a front side and a back side 8)

Thanks for your detailled writeup, I'm sure it helps others along the way!
Glad it works as desired 8).

9 months later

Hi there, and sorry for bringing this topic back to life, but I'm having problems with this feature. Basically, that it doesn't seem to work as "advertised" for me. :rolleyes:

If what James described as normal behavior is correct, I would expect to be seeing how the CPU time allocated for SkeletonAnimation Update and LateUpdate are reduced to almost nothing (which is the setting I'm using myself), but I'm still seeing the milliseconds used in my dev build for those instances, the same as before I activated the culling option on the skeleton prefabs.

How exactly SkeletonAnimation determines if it's visible or not, in dev build mode? The main camera? If that's the case, I'm not seeing that happening, even at 1000 units of distance.

BTW, I have the skeleton render separator enabled at all times. I don't know if that's relevant or not.

Are you using the latest unitypackage? We have fixed this issue very recently which fixed initializing the offscreen update mode properly when the skeleton is starting/instantiated off-screen.

Ah, I see. The one I was using was one month old. I've installed today's version (May 7th)-

However... apart from this, is there any change that could break something related to combined skins and/or multiple tracks playing with several parts renderers?

Because if I activate any option other than Full Update, the skeleton doesn't render at all, rendering (pun intended) the feature useless. :p

Anyway, last night I made a culling system based on the whole skeletons activating/deactivating when they're not visible on a slightly bigger camera than the main one, and it's saving me a lot of frames, so I won't insist on this.

However, if you want to dig in more into my weird issue, I'm here for more troubleshooting.

Thanks!

Abelius wrote

Because if I activate any option other than Full Update, the skeleton doesn't render at all, rendering (pun intended) the feature useless.

That is indeed weird. Could you perhaps send us a minimal test Unity project as a zip package that still shows the issue? To contact@esotericsoftware.com as usual, then we can have a look at what's going wrong.

The main camera? If that's the case, I'm not seeing that happening, even at 1000 units of distance.

Your question is a bit out of context. I assume you want to repeat the question by Abelius here right?

Please note that in the Unity Editor during play mode all cameras, including the scene view camera, are used for determining if a renderer is visible. Or did you encounter this behaviour outside the Unity editor, in a built exacutable?