• RuntimesUnity
  • How to disable entire skeleton so that CPU does not compute transforms

Hello friends (:
I am building a multiplayer game on Unity and ran into a CPU bottlenecking issue.
My game server needs to have about minimum 1000 concurrent instances of Spine2D animated monsters roaming the world.
However, My humble little instance hit 100% CPU usage at 140 monsters, far below minimum requirements.
I had innitially assumed that I could simply disable animations on server side, but after testing and reading documentation (e.g. this link:),
I discovered that "Computing a bone's world transform uses the CPU", and I assume this compute happens regardless of animation state.
I am unable to completely remove the spine SkeletonAnimation component from the server side object because the SkeletonAnimation/skeleton data asset does fire events that we use to send out remote procedure calls to clients.

QUESTION:
Is there a way to seperate the timeline information/element of the skeletonAnimation from the skeleton itself, so that I can just get access to the timeline and events information?
If not, is there a way to completely disable a SkeletonAnimation and all its bones from be computed by Unity?
If not, are there any potential solutions that yall suggest?

Thank you so much in advance (:

  • Harald ответили на это сообщение.
    Related Discussions
    ...

    To address your issue of CPU bottlenecking with multiple Spine2D animated monsters in Unity, you can consider a few strategies to reduce the CPU load:

    1. Disable SkeletonAnimation Component: You can disable the SkeletonAnimation component to stop the animation updates and mesh regeneration. This will save CPU resources as the animations won't be processed. However, this might also stop the events from firing, which you need for remote procedure calls.

    2. Custom Culling: Implement custom culling logic to disable GameObjects when they are not needed, such as when they are off-screen. This prevents unnecessary updates and rendering, reducing CPU usage.

    3. Use Fixed Timestep Updates: Consider updating the skeletons at a fixed timestep rather than every frame. This can be done using the SkeletonAnimationFixedTimestep component, which allows you to control the update frequency.

    4. Optimize Skeleton Complexity: Reduce the number of bones and vertices in your skeletons. Fewer bones and vertices mean less computation for the CPU. You can also prune unnecessary weights and simplify the skeleton structure.

    5. Separate Logic and Animation: If possible, separate the logic that handles events from the animation. You might be able to create a lightweight system that only processes the necessary events without involving the full animation system.

    6. Pooling and Reuse: Use object pooling to manage your monsters efficiently. This can help reduce the overhead of creating and destroying GameObjects frequently.

    By implementing these strategies, you should be able to reduce the CPU load and handle more concurrent instances of animated monsters in your game.

    JohnSully My game server needs to have about minimum 1000 concurrent instances of Spine2D animated monsters roaming the world.

    Why does your server handle animation? This makes no sense, as you would also need to sync the detailed animation state of the characters with each client. Your server should handle game logic and physics, in other words game state of each character, not animating them in detail and taking over work that the client needs to do.

    If you really need to run animations on the server, you should set SkeletonAnimation.UpdateMode to e.g. UpdateMode.OnlyEventTimelines accordingly to just process event timelines.

    Hey! Thanks for your reply!

    I think that UpdateMode.OnlyEventTimelines looks like a really good solution that I will test today.
    To answer your question,
    Yes, we do not play animations on the server. but we need the timeline information.
    For example, when an NPC monster attacks, a fireball collider is only spawned midway through the animation when an event fires.
    This collider + VFX spawns on the clients so they can see it, while only the collider spawns on the server so it can validate collisions, if not the game becomes too client-authoritative.
    We do not want the server to animate anything, but the server still needs that timeline and event info for when events happen, and this information is woven into the skeleton data asset, or the skeletonanimation component.

    This post was created because I realized that even when animations are not playing, the CPU still seems to be processing all the bone data every frame as long as the SkeletonAnimation component is enabled in the game object. I am asking for a way to do exactly what you suggest, but take timeline info from my spine files to dictate game logic.

    @JohnSully Glad to hear it's helpful, thanks for the detailed writeup.

    If you need to strip away more AnimationState timeline processing, which I have a feeling should not be performed on a server at all, you could alternatively extract the event timepoints via a Unity Editor script from the SkeletonData, and then just store the time offsets from when the animation starts. Then you could just store and process character state and issue events at certain offsets after entering a specific character state instead of after starting certain animations.

    • JohnSully ответили на это сообщение.

      Harald
      Hey Harald! Thanks again for following up (:
      Accessing the SkeletonData information directly for animation timeline information is an amazing idea, far better than the previously proposed modification of the SkeletonAnimation.UpdateMode.
      Coincidentally, this is what we have been looking into today.
      When examining the SkeletonDataAsset file in inspector, we are able to clearly see the duration of each animation. However, when we open the actual asset file, very predictably it only contains address pointers to the .json file, and itself does not contain any timeline information.
      Does this mean that we'll need to write an editor script to extract that information from the .json file?
      Or is there a way to extract it directly from the SkeletonDataAsset file like you suggested?

      • Harald ответили на это сообщение.

        JohnSully Does this mean that we'll need to write an editor script to extract that information from the .json file?

        A side note: as listed here, for production use you should in general be exporting as binary .skel.bytes format instead of as .json. This is because binary format loads faster and is smaller in size.

        Regarding your actual question:
        I did not mean that you should be parsing the .json file yourself. Instead you should be getting the SkeletonData (note that I wrote SkeletonData, not SkeletonDataAsset) in your editor script. You can access it from SkeletonAnimation via skeletonAnimation.Skeleton.Data. Alternatively you can access it via the SkeletonDataAsset through skeletonAnimation.SkeletonDataAsset.GetSkeletonData(true).

        Then you can access SkeletonData.Animations and at each animation access Animation.Timelines, and if (timeline is EventTimeline) you can cast it and access the timepoints and events accordingly. See AnimationState.ApplyEventTimelinesOnly as a reference.

        JohnSully Or is there a way to extract it directly from the SkeletonDataAsset file like you suggested?

        The SkeletonDataAsset only holds references to the text assets which are then parsed. You should let the spine-unity runtime perform the general loading, and then access the loaded information as described above.