Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Animation optimization (questions)

Discussion in 'Scripting' started by Velo222, Mar 30, 2013.

  1. Velo222

    Velo222

    Joined:
    Apr 29, 2012
    Posts:
    1,437
    When I have 100 animations on-screen, I get 48-50 fps. When I turn off the animation component on all my units, I get 65-67 fps. To me, this is pretty significant. But perhaps this is normal?

    As far as I know, the lower your fps gets, the amount it takes to drop your framerate by one frame per second multiplies (takes more stress on the cpu/gpu to drop it each frame), thus each frame drop is pretty significant the lower your fps gets. So perhaps this amount of framerate drop with 100 animations on-screen is expected? Does anyone know if this is the case?


    Are there any scripting techniques/optimizations I can use to drastically reduce the amount of "hurt" animations put on my cpu/gpu?

    Here is how I'm scripting the animations currently, most of them are in the Update() function as in the example from Unity's scripting reference page:

    Code (csharp):
    1. if (animComponent.enabled == true  GetComponent(Attack).attacking == false) {
    2.                 if(animComponent["footman2idle"]){
    3.                     animComponent.CrossFade("footman2idle");//My footman2 animation
    4.                 }
    5.                 if(animation["ARCH_combat_mode"]){
    6.                     animation.CrossFade("ARCH_combat_mode");//My Archer animation
    7.                 }
    8.                 if(animation["Idle"]){
    9.                     animation["Idle"].speed = 1.5;
    10.                     animation.CrossFade("Idle");//Red Dragon animation
    11.                 }
    12.                
    13.                 //Debug.Log("Playing animation 1");
    14.                 //animation.CrossFade ("Take 001");
    15.             }

    My main goal, is to try to fit as many animations on-screen as I possibly can, without too much noticeable game-lag. So far, animations seem to be my "bottleneck" in terms of gameplay. I'm not sure if it's the animations themselves, or if it's how I'm scripting the animations to play?

    I don't have Unity pro, so I don't have the profiler (which I really want). So I can't pinpoint exactly what it is in the animations or my animation scripting that's so expensive cpu-wise.
     
  2. Velo222

    Velo222

    Joined:
    Apr 29, 2012
    Posts:
    1,437
    I forgot to add, the amount of work the renderer is doing remains the same whether or not I turn off the animation component on my units, it's just the "main thread" which is affected significantly. Which makes me think it's all cpu/scripting related.

    I feel like calling animation.Play() every update is a bad idea, but that's how the scripting reference has it. How might I get good animations transitions if I don't call the animation.Crossfade() every update though?
     
  3. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,614
    Almost the right conclusion, but for the wrong reasons.

    Read this.

    65-67FPS = ~15ms/frame.
    48-50FPS = ~20ms/frame.

    Thus your 100 animations is taking 5ms/frame, or 0.05ms per animation component, which sounds ballpark reasonable, if a little high. Key things to reduce animation workload are:

    • Use fewer bones
    • Remove redundant curves (e.g. don't include animation curves that just set all your bone scales to (1, 1, 1) if the bones are already set to that
    • Ensure that any bones that have colliders attached also have rigid bodies
     
    XCO likes this.
  4. Velo222

    Velo222

    Joined:
    Apr 29, 2012
    Posts:
    1,437
    All of my characters have colliders and rigidbodies. I don't think the bones (in the character's rigs) have colliders at all, so I think I'm good on that point.

    As for animation curves, I actually have no idea what those actually do (although I've read about them briefly), or how to modify them. I created my models in Blender, and rigged them with an addon that automatically generates the rig. I animated them as well, but never had to mess with animation curves. So I have no idea if, or how, I should modify them.

    I know you're correct about the number of bones. I was just hoping not to have to modify my characters rigs, but if that is the best option, I will. Will lowering my polygon/vertex count on my character's meshes help with animations in that regard as well? Thanks superpig.
     
  5. Themp

    Themp

    Joined:
    Nov 8, 2011
    Posts:
    96
    yes there are

    let's start with editing that code..

    first of.. You don't need to recheck every if statement, because if one of them is true, the others are false (am I right?)
    ALSO the GetComponent Function is rather intensive (in your terms)

    you can avoid to keep getting the component by declaring it once in the start/awake function

    so the final code will be

    Code (csharp):
    1.  
    2. Attack attackScript;
    3. void Start()
    4. {
    5.  attackScript = this.GetComponent<Attack>();
    6. }
    7.  
    8. if (animComponent.enabled == true  attackScript.attacking == false) {
    9.                 if(animComponent["footman2idle"]){
    10.                     animComponent.CrossFade("footman2idle");//My footman2 animation
    11.                 }
    12. else if(animation["ARCH_combat_mode"]){
    13.                     animation.CrossFade("ARCH_combat_mode");//My Archer animation
    14.                 }
    15. else if(animation["Idle"]){
    16.                     animation["Idle"].speed = 1.5;
    17.                     animation.CrossFade("Idle");//Red Dragon animation
    18.                 }
    19.             }
    a last thing you can do as improvement (but it won't be much) is changing the strings you use to find a animation to animationclips, Because it needs to parse the string first now and then find the animation and then use it.. while this overhead isn't very much, it's still overhead that can be avoided.. (by using the direct animationclips)

    you can declare all animationclips in the start function (which will increase first-load time(by maybe 0,0005 secs?) but will help with average frame performance
     
    XCO likes this.
  6. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,614
    The animation curves are the actual individual aspects of the animation. If an object's position changes over the course of the anim, then the anim has position curves for it. If it's rotated, then the anim has rotation curves, and so on. Unity executes the animation by figuring out what frame the animation is on and then sampling every curve in the anim at that point, and setting the sampled values to the objects in your scene (such as the character bones). So if you have curves that are redundant - e.g. that just set the scale of your bones to (1, 1, 1) when the scale's already set to that even with no animation playing - then Unity's spending time sampling and applying that when it doesn't need to.

    There should be some way to inspect the curves in Blender.

    That affects skinning cost, not animation cost. So prima facie, no, but it's possible that some of the 5ms/frame change you're seeing is skinning rather than animation. Try disabling the SkinnedMeshRenderer component on your characters and trying the animation enable/disable comparison again - see if you still get the same increase in frame time.