Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Beware. Animator culling will break if you don't do this properly.

Discussion in 'Animation' started by jhughes2112, Jan 24, 2018.

  1. jhughes2112

    jhughes2112

    Joined:
    Nov 20, 2014
    Posts:
    178
    (This is for FutureMe, and anyone else it helps. I've discovered this once or twice before and forgotten it.)

    I have seen lots of complaints about Animator stopping when it shouldn't, and also experienced this previously (and today, all day) while doing some optimization of an avatar hierarchy.

    DO NOT move the SkinnedMeshRenderers or the Bone hierarchy out from under the Animator. Yes, you may, in fact, move them between different Animators to do level-of-detail, but disable the ones that are no longer supposed to run, and make sure you reparent the bones and renderers under the new one, activate it, and call Rebind() on it.

    Rebind, although it is not documented, is called whenever you click the drop-down and change Culling Mode on the Animator. What Rebind apparently does is recursively collect a list of all bones and all skinned mesh renderers. So, if you Rebind at the wrong time or drag things around in the editor and click the drop-down, you can bork your animated mesh, or fix it the same way. Animator apparently keeps internal lists of game objects, so you can move things around while running in the editor, but calling Rebind again or changing the drop-down again will lose those linkages.

    So, note to self... if you have to switch a character to Animate Always, you've probably screwed up the hierarchy and should just move things back the way it wants to be. Please, please please, Unity, expose the lists of things explicitly so I can see what it's looking at. And add a Rebind button to the Inspector to refresh this. It would take the magic out of this component, and save a lot of people a lot of time. :)

    JH
     
  2. Goatogrammetry

    Goatogrammetry

    Joined:
    Apr 27, 2017
    Posts:
    197
    Wha... It sounds like you know how to make LOD Groups work with animated characters. I've been trying for a while to find out how to do it. I figured that there was a magical link between an animation controller and mesh renderers that was hidden somehow-- Since when I export a mesh with multiple parts they all follow the bones, but I cant use hierarchy to make other meshes (with the same skeleton) follow the same animations. (Guy walks away while his clothing hangs in space not animating). LOD groups just don't animate, but the root motion works on the group and you can see the non-animating mesh drag around. It seemed there must be something weird and hidden going on that I might have to learn how to use code to access. You're suggesting there's a way in the editor to make the connection? Please elaborate if you know the secret.

    PS and !thanks Unity for making a how-to page on the LOD Group for static items like a rock but not showing how to make it work with animated characters. Boooo.
     
  3. jhughes2112

    jhughes2112

    Joined:
    Nov 20, 2014
    Posts:
    178
    Automoda, the easy thing is attaching a rigid object to a transform in a character, because the Animator is just posing the transforms every frame to match the animation. However, getting multiple separate objects to skin together efficiently requires merging the meshes together and making sure they all refer to the same bone hierarchy in their T-pose, or remap it at the time you merge the meshes together. MeshBaker is a plugin that can do such a thing, or you can write your own. It's not built in. Inefficiently, you can stick several skinned mesh renderers under the Animator and just call Rebind() on the animator. It should figure it out.

    Also for FutureMe, do NOT disable Animator components and re-enable them. Ever. Once they are bound to a hierarchy of bones and skinned mesh renderers, leave them that way. Just pause their playablegraph to stop them from operating. This allows having multiple Animators concurrently attached to a single rig and just play/pause which one you want running. Seems to be some cost to that, but it's not nearly as bad as the horrible frame hitching from causing a rebind when an Animator is re-enabled.

    Finally, for Unity: Please fix OptimizeTransformHierarchy so that the string matching of bone names is documented (and works? How about a usable example?), and allow us to access the bone mapping in the Animator so baked meshes can also be optimized and retargeted. Currently not possible with exposed variables. At the moment, we either get to choose faster Animators or fewer draw calls, but not both. Boo.
     
  4. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    theANMATOR2b and LaneFox like this.
  5. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,462
    Also, all 4 and 5 rank bugs are evaluated. File a report and populate it until all 5 bars are full and you're guaranteed to get eyes on to repro.
     
    hippocoder likes this.
  6. jhughes2112

    jhughes2112

    Joined:
    Nov 20, 2014
    Posts:
    178
  7. jhughes2112

    jhughes2112

    Joined:
    Nov 20, 2014
    Posts:
    178
    So, FutureMe, I think we've figured it out. It's possible to get OptimizeTransformHierarchies to work and modify meshes. BUT, it doesn't just work... make sure you:

    1) Check the IsOptimized flag on the FBX asset, so Unity knows to generate an internal matrix table in the Animator for you.
    2) Then, Instance() at the Animator level or above (and insert it into your object or scene hierarchy somewhere else).
    3) [This part I haven't tested exhaustively] Instance your meshes back into the same hierarchy, so their mesh data is unique from the mesh Asset they point to, and modify the mesh. I believe this retains the skinning information.
    4) If you deoptimize transform hierarchies, then optimize transform hierarchy again, you will lose EVERYTHING under the Animator, because (a) the script call is useless when it comes to preserving bones, and (b) the only way to preserve bones correctly is when the FBX importer does it with the exposed bone list (protip: you can edit this in the .meta file directly if you like).

    The critical element is the Animator has the mapping that SkinnedMeshRenderers look to for animated matrices in their local .bones array. If there's a bone hash set, it means look for it under the Animator as a real transform. If there's a null, it means use the Animator's internal matrix for it. The Animator, when the hash is null, does not need to push the matrix data out to a transform, thus dramatically improving the last step of animation. Note, the reason you can move bones around after the Animator has been bound is it internally caches the pointer to the transforms it updates. If you rebind, this is rebuilt and if you have moved or renamed any transforms, it will not find them again.
     
  8. jhughes2112

    jhughes2112

    Joined:
    Nov 20, 2014
    Posts:
    178
    Oh, FutureMe, you're going to love this. Once you Optimize Transform Hierarchies, if the Animator rebinds for any reason, make absolutely sure all SkinnedMeshRenderers are direct children of the Animator. If you attempt to organize a bunch of meshes into a hierarchy, it will screw up the bind pose and although the parts will animate, they will not fit together properly. Even if the intermediary nodes have an identity transform. It just doesn't work. So don't do it. Leave all the Renderers where they are. You'll thank me later.
     
  9. theANMATOR2b

    theANMATOR2b

    Joined:
    Jul 12, 2014
    Posts:
    7,790
    Hey FutureYou and JH - what do you need access to the transform hierarchy for - with optimized hierarchy?

    What end goal are you trying to accomplish - not the problem you are attempting to solve here, the end 'thing' solving this will enable you to create/do?
    A guess - Customizable character with separate mesh components with optimized hierarchy?

    Genuine question - why not just use unoptimized? Aren't there other areas to optimize within the project where the savings are easier to attain.
     
  10. jhughes2112

    jhughes2112

    Joined:
    Nov 20, 2014
    Posts:
    178
    Performance suffers the more transforms the Animator writes to every frame. The Animator is a heavily multi-threaded process, which is fantastic. However, writing to the transforms is a very serial process that happens only on the main thread. Exposing a few bones here and there is no big deal, so you can attach objects to an animating character, but a detailed character will have 80 to 200 bones in it and that adds up quickly, especially if you want to get a hundred or so characters on screen.

    I'm documenting best practices, yo, and since Animator functionality has virtually no docs anywhere, I figured I would put it out there for the community. YMMV when it comes to performance. Profile your project and make decisions accordingly.
     
    theANMATOR2b likes this.