Search Unity

SpriteSkin OnEnable/OnDisable huge performance hit

Discussion in 'Animation' started by TheCosmiCat, Nov 8, 2021.

  1. TheCosmiCat

    TheCosmiCat

    Joined:
    Nov 22, 2018
    Posts:
    6
    Hey everyone,
    I'll start by saying that I already found a massive performance gain in regards to Sprite Mesh deformation using the optional performance boost found at at https://docs.unity3d.com/Packages/com.unity.2d.animation@6.0/manual/SpriteSkin.html

    However, I am using top down 2d characters that have Up, Side, and Down directional gameobjects that get enabled/disabled as they change directions. I am still seeing huge performance hits when I do this, which are caused by SpriteSkin.OnEnable() and SpriteSkin.OnDisable().

    I admit, I do have pretty complex characters. There are times when I have hundreds, maybe even thousands, of SpriteSkins on screen at once. I have a test of 100 character on screen - I can animate them all and keep a steady 120 fps but the moment I have them all the switch directions I get a 1000ms collective call to SpriteSkin.Onenable/OnDisable(). This is an extreme example, but it shows how much of a hit is taken relative to normal Sprite Mesh deformation performance. Even with 10 characters, I am seeing a significant dip in fps.

    Is there any way to optimize this? Any plans to fix it? Workarounds? I suppose there might be ways I can get around it for now, like only disabling my SpriteRenderers on direction change? But that doesn't seem like an ideal long term solution if I can help it.

    Thanks
     
  2. TheCosmiCat

    TheCosmiCat

    Joined:
    Nov 22, 2018
    Posts:
    6
    Bumping this after a few months. It's still a pretty significant issue for me. Is there any word on this get optimized in the future?
     
  3. liyibao

    liyibao

    Joined:
    Sep 6, 2014
    Posts:
    28
    • I had the same problem
     
  4. TheCosmiCat

    TheCosmiCat

    Joined:
    Nov 22, 2018
    Posts:
    6
    I was never able to find a practical workaround for this. So a month ago I started transitioning to Spine Animation. I'll get better performance but it's a ton of rework on my game unfortunately.
     
  5. liyibao

    liyibao

    Joined:
    Sep 6, 2014
    Posts:
    28
    I'm also starting to use spine in my next project, I guess the problem will only be in the editor, maybe SpriteSkin is checking for some errors in the editor.
     
  6. TheCosmiCat

    TheCosmiCat

    Joined:
    Nov 22, 2018
    Posts:
    6
    It's been a while, but I did profile what it was doing and I traced it to OnEnableBatch() and OnResetBatch(). If I turn batching off, then I'll get terrible performance then entire time, which is why it's recommended in the "Optional performance boost" section of the link I posted in my first post. I can also confirm that this is not just an editor issue, it's an issue in release builds as well. I've spent a couple years in development hoping this issue would get fixed but there's been no word nor acknowledgment of it from the Unity devs so I unfortunately need to switch animation tools.
     
  7. oTaijjo

    oTaijjo

    Joined:
    Nov 3, 2019
    Posts:
    30
    Hello, we ran into the same problem and switching technologies was not an option for us. I found a way and want to share it here.

    Unity: 2021.2.17f1
    2D Animation: 7.0.4
    Burst: 1.8.0
    Collections: 1.4.0
    We noticed massive performance Spikes in the profile each time our enemies were enabled/disabled. This happens a lot, since we implemented a culling system to show/hide enemies, if they get too far away from the hero - ironically for performance reasons. We discovered the problem discussed in this thread, which caused noticeable lags during runtime.

    As I've said, switching technologies was not an option. So I went with disabling everything, except the SpriteSkin components. Fortunately our enemy code was already setup in a way that makes this fairly easy. I had to inject a few things in the editor and to fetch some lists at runtime, I'm now iterating over and enable/disable instead of just doing it for the entire GameObject. I do this for gameobjects, but also for individual Behaviour components.

    As you might think this keeps the SpriteSkins active and updating in the background, even if their objects are miles away. To counter this, we made sure all SpriteSkins have their "Always Update" flag disabled. Also, just to be sure, I always move the object containing a character's sprite skins off screen, if disabled.

    I agree, this is rather stupid, but it seems to work well in our case. Hope this helps.
     
  8. DragonCoder

    DragonCoder

    Joined:
    Jul 3, 2015
    Posts:
    1,700
    Another idea that comes to mind:
    Instead of affecting all animated objects/characters at once, why not cascade them?
    At 100 characters, have only one change direction (or whatever triggers the issue) every frame. Maybe make the time gap dependent on Time.deltaTime or use FixedUpdate so it's frame rate independent.
    This spreads out the performance dip. Furthermore sort the order of affected characters by the distance to whatever triggers it and it can even seem like an intended feature by having a wave of motion-delay go through the formation. Even the best trained army will likely not change direction fully synchronous after all and that's sometimes done fully deliberately in RTS for example because it also helps with smoother pathfinding if you have a system with local avoidance.

    If the usecase is just about disabling animations outside the camera, the player will not even notice such a delay if you make sure to start triggering slightly outside the view frustrum.
     
    Last edited: Oct 22, 2022