Search Unity

Animations use Enormous Amounts of Disk Space

Discussion in 'Animation' started by Cygon4, Aug 3, 2017.

  1. Cygon4

    Cygon4

    Joined:
    Sep 17, 2012
    Posts:
    382
    Hi!

    In my game, so far I have a single human character. This character has animation clips for a combined duration of 18.5 seconds (stored in a .blend file of 2.1 MiB).

    When I build a player for my Unity game, those 18.5 seconds of animation use 27.4 MiB of disk space:

    Code (CSharp):
    1. -------------------------------------------------------------------------------
    2. Build Report
    3. Uncompressed usage by category:
    4. Textures         45.1 mb      17.9%
    5. Meshes           17.7 mb       7.0%
    6. Animations       27.4 mb      10.9%
    7. Sounds            0.0 kb       0.0%
    8. Shaders           2.4 mb       1.0%
    9. Other Assets    569.7 kb       0.2%
    10. Levels            7.7 mb       3.1%
    11. Scripts           1.6 mb       0.6%
    12. Included DLLs     5.2 mb       2.1%
    13. File headers     59.3 kb       0.0%
    14. Complete size   251.7 mb     100.0%
    I mostly know how this happens:
    • Blender's FBX exporter goes through a process called "Baking"
    It keyframes every bone for every single frame. This is hard to do any other way since bones are often controlled by many modifiers (stretch to, track, copy rotation, inverse kinematics, etc.) that can't be represented in FBX and mostly have no equivalent in Unity.
    • Unity tries to remove redundant keyframes again via "Optimization"
    I imagine this is almost exactly what Blender's "Curve Simplify" script does (https://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Curve/Curve_Simplify), removing keyframes that can be considered redundant because removing them only results in a very small position/rotation error.

    So 1110 keyframed (60 fps keyframes) and a model of ~850 bones makes: (12 bytes position vector + 16 bytes orientation quaternion) * 850 * 1110 = 25.2 MiB.

    - Is there anything I can do to trim that size? Can animations be resampled to 30 fps keyframes by Unity?
    - What capabilities does Unity's animation curve optimization/simplification system have? Can it recover the original curve from a baked spline path?
     
    Ali_V_Quest likes this.
  2. v2-Ton-Studios

    v2-Ton-Studios

    Joined:
    Jul 18, 2012
    Posts:
    238
    I'm interested in this as well.
     
  3. Cygon4

    Cygon4

    Joined:
    Sep 17, 2012
    Posts:
    382
    Could some Maya or 3ds Max users weight in?

    Is the situation the same for you or can Autodesk products export to .fbx with sparse keyframes somehow?
     
  4. theANMATOR2b

    theANMATOR2b

    Joined:
    Jul 12, 2014
    Posts:
    7,790
    I'm also interested :) I wonder if animating at 30fps before export instead of 60 would reduce the sizes?

    @Cygon4 3D Max has a super simple (manual) process o_O for converting 30fps to 60fps and vis-versa.
    If you'd like to perform some tests I can oblige later this afternoon/evening.

    If you want PM me and we can do some simple testing. I'll need a 2012 fbx export without baking to properly convert the fps.
    We can circle back around here after gathering test data @v2-Ton-Studios

    Edit: Oh yeah - 3D Max does not bake keyframes unless the artist performs an internal bake in Max or intentionally performs the bake during the export process. Keyframe data in Unity displays normal, without keys on every animation frame.
     
  5. NoiseFloorDev

    NoiseFloorDev

    Joined:
    May 13, 2017
    Posts:
    104
    With Maya you're almost always baking, since you're normally animating with a more complicated control rig and baking is the only general way to apply the animation to joints for export. For example, one of my rigs orients a joint based on vertices in the chin, so the teeth follow mouth blend shapes automatically. Obviously I'm not going to try to do that in engine, so I need that joint baked.

    I find Unity's keyframe reduction to be mostly useless. It only allows reducing based on a global error value. You can't tell it which joints are important, or reduce based on total error in the hierarchy, so I have to set the error values extremely low, around 0.001, and even then it can reduce poorly. This seems to be a good explanation of the problem: http://nfrechette.github.io/2017/01/30/anim_compression_unity5/

    Maya can do keyframe reduction during bake, but I don't know if it's any better. It doesn't seem to have many options either.

    I have a feeling that if I get hit by this problem, I'll end up writing an FBX processor to do my own keyframe reduction, not that I really want to have to do that myself...
     
  6. NoiseFloorDev

    NoiseFloorDev

    Joined:
    May 13, 2017
    Posts:
    104
    Yuck I figured out one ugly problem with importing animation from Maya that causes baking whether you like it or not.

    Maya joints have a secondary orientation, joint orient, which sets the coordinate space for the joint, and joint rotations happen relative to it. That way, for example, swinging the arm back and forth at the shoulder is only a rotation on a single axis, and twist is on a single axis. Unity doesn't have this, so it just applies the joint orient directly to rotation keys and each joint rotates in its parent's coordinate space like a regular transform.

    This gives correct rotations at the keyframe, but it makes keys interpolate differently. If you put two keys on rotation X in Maya on a joint with joint orient, and import it into Unity, it can interpolate across a completely different path.

    Unity appears to work around this by forcing "Resample Curves" on if a joint has a nonzero joint orient (regardless of the import setting). Keyframe reduction can try to go back in and reduce it back down, but everyone knows the problems with Unity's keyframe reduction, so that's not much help.
     
  7. NoiseFloorDev

    NoiseFloorDev

    Joined:
    May 13, 2017
    Posts:
    104
    I've been looking at using IK to help with this. Maybe it's obvious, but I've always thought of IK as a solution to dynamic problems, not for fully baked animations. It can help a lot here. For example, for an animation of a character reaching and picking up an object, using IK to drive the arm can let you use far fewer keys than FK would need.

    With FK the keys all need to be very precise, so you don't have error accumulate through the hip, spine, shoulder and arms and end up with your character's hand not lining up with the object. You have to turn animation compression way down or off to make it work.

    With IK, you can drive the arm with one or two world-space positioned controls. You still need that control to be in the right place, but you don't have a ton of animated parent joints adding error into the mix, so the animation compression can be much higher.

    I'm doing this with Maya by adding hand and elbow locators which become empty GameObjects in Unity, putting them outside the skeleton in a helper group (or in the root node), and parent constraining them to the hand and elbow joints. That way, when I export the animation, the position of the hands and elbows get baked out to the objects. Then, I just point Final IK's hand and bend goal effectors at those locators. When I turn on the effector, it puts the hand in the right place, and it gets the elbow right in initial tests too, though that's usually less important. It's basically using IK as a complex keyframe compressor.

    Of course, if you have no other need for IK, it sucks to add that sort of complexity and CPU cost just for this, but I guess it's a rare game that can't find other good uses for IK...
     
  8. theANMATOR2b

    theANMATOR2b

    Joined:
    Jul 12, 2014
    Posts:
    7,790
    I like your details about using IK goals for Final IK set up - however I don't think this is really relevant to the discussion simply because - everyone who is animating characters is using IK.
    It isn't anything new/ground breaking for people who are animating characters.
    Additionally - I think their is ZERO overhead difference when exporting IK vs FK animated rigs out of any package into Unity. The data and bone count is exactly the same regardless of what technique was used to move/rotate the bones. IK has no cost - unless the artist is exporting the IK goals for a set up as you have explained.
    Most animators do not include the IK goals in the export. They are useless once in engine.
     
  9. NoiseFloorDev

    NoiseFloorDev

    Joined:
    May 13, 2017
    Posts:
    104
    I didn't say it was groundbreaking (actually, I said it was probably obvious to some), and of course it's relevant to the discussion: a way to make animations use a less enormous amount of disk space.

    I don't know what you mean by "zero overhead difference", but I'm talking about the amount of animation data that ends up in the build. This results in that data being much smaller, since it allows you to turn keyframe reduction up much higher without error accumulation becoming an issue.

    If you do this, of course you need to adjust your export process to include the necessary data. Note that you don't export high-level rigging IK effectors that the animator might be using (the IK system in your animation package isn't going to behave the same as an IK system in game), you export the position of the resulting joints.

    Another useful property of this is that since the FK data is still being included (just overridden in-game, and inaccurate from keyframe reduction), animation previews, transition previews, etc. are still usable.

    Hmm. Unrelated to this: my FBX exports have translate keys on joints, which are all the same value. (There's no actual animation on translation, it's just the way Maya bakes.) For some reason no matter what I set keyframe reduction to, Unity isn't reducing them at all. They're all identical, it should reduce them all to one or two keys. That's a problem, need to look into that some more...
     
  10. theANMATOR2b

    theANMATOR2b

    Joined:
    Jul 12, 2014
    Posts:
    7,790
    Sorry Noise - I missed that part. I can see how it could be helpful to create animation in engine, but I do not see this animation reduction benefit on IK animations compared to FK animations. - The data is the same when exported/imported into the engine. Same size file, same reduction. Maybe this is a maya exclusive feature.
    On a side note - I've not ran into a development issue where I needed to use animation reduction in engine. I think other things can be optimized before meddling with my glorious animations! :D:cool:
    Compress those sound files, and textures - leave the animations alone!
     
  11. NoiseFloorDev

    NoiseFloorDev

    Joined:
    May 13, 2017
    Posts:
    104
    (The topic is "my animations are too big, how do I make them smaller", so I'm not sure "don't bother" is very helpful. :)

    Remember, we're talking about in-engine IK here, not animation tool IK that gets baked out to FK. The point is to export the position of the hand joint to be used as an IK effector inside a Unity IK system. By doing that, far less data can be needed to produce the same animation. The IK effector isn't accumulating error over a half dozen or more joints, so keyframe reduction can do a much better job with far less error introduced. This isn't theoretical, I've tried it and it works.

    Not that it's without its limitations--it won't work as well with layered animations affecting the same joints, for example. But it definitely has its applications, like if your game has a lot of cutscenes.


    [FONT=Roboto, sans-serif]I don't know why this is happening, but it's definitely a bug. Case 940692
    [/FONT]
     
  12. theANMATOR2b

    theANMATOR2b

    Joined:
    Jul 12, 2014
    Posts:
    7,790
    That makes sense - I'll keep that in mind when developing a system like that.
     
  13. NoiseFloorDev

    NoiseFloorDev

    Joined:
    May 13, 2017
    Posts:
    104
    (Why is the forum inserting literal FONT tags that aren't being parsed? Not that people should be allowed to choose their own fonts, but it inserted the tag itself. A bit silly.)

    Apparently this is an old, known issue that just isn't getting fixed. That's frustrating--this alone is probably making my animation files ten times larger. I think it happens if there's any rounding error in position keys, eg. if keys are 0.00005 apart it won't reduce them (which means positional error isn't working at all). I think I can improve it by filtering the FBX to clamp nearby keys to exactly the same value, since it does seem to remove keys that are exactly the same, but I sure seem to spend a lot of time writing complicated workarounds for Unity bugs.

    Not something I'm going to tackle right now, but if I do this I'll link it here.
     
  14. Cygon4

    Cygon4

    Joined:
    Sep 17, 2012
    Posts:
    382
    Using in-engine IK would not be that far-fetched. In Blender I could create a second Armature (skeleton) with only select bones and use "copy transform" modifiers so that I have hand positions and elbow targets but the upper arm and forearm FK bones aren't baked.

    Just for fun, I imported my animations into UE4:

    unreal-engine-animation-compression.png

    So again, Blender bakes my animations into a 36.8 MiB .fbx file.

    Unexpectedly, all animations together amount to 2.1 MiB. When played back, I do not notice any accuracy issues, even with IK chains baked into 6 bones (3 roll bones per segment to prevent candy wrapper effect).
     
  15. studioyogyog

    studioyogyog

    Joined:
    Apr 11, 2017
    Posts:
    2
    Total newbie here but.... (to Unity - Not Blender)

    So there IS a clean keys function.... I guess it would recognise a hold (bone is still for a few frames) and clean those keyframe? So, if I animate with that in mind.... lots of holds, looking a bit more like traditional animation, then I can reduce a lot more?

    And where do I find this reduce keyframe function? Can you give me like a key phrase to Google tutorials from?