Search Unity

[solved] How to set Root Node to Bip001 in script when importing fbx file?

Discussion in 'Animation' started by laoguai, Feb 2, 2015.

  1. laoguai

    laoguai

    Joined:
    Feb 2, 2015
    Posts:
    4
    I want to use Root motion with generic animation, it need set Root Node to work. Now I want to import many fbx animation files. I need to set Root Node to Bip001 in script. I have searched the forum, but found no answer, can anynone give some idea? thank you so much!
     
  2. Jself

    Jself

    Joined:
    May 29, 2014
    Posts:
    56
    My understanding that Generic root translation and orientation does not work the same as Humanoids. Humanoid can use the Bip001 as it's root and Generic needs a root node that always sits a 0 Y, and translates in Z, X axis in world space and be the parent bone to the whole skeleton.

    That helper node is the node you would chose in Unity as the Root. It basically sits in between the legs, on the floor during all locomotion. It's orientation follows the pelvis's orientation.

    Cryengine requires the same setup (if that helps at all).

    Or I am wrong. Unity wasn't very clear as to how the Root node should be set up and animated in Generics documents. But this process I explained sounds like what they are saying.
     
  3. laoguai

    laoguai

    Joined:
    Feb 2, 2015
    Posts:
    4
    I can set Root Node using unity editor tool manually, tha's a lot of work when there are many fbx files. I just want to set Root Node in script when importing fbx file into unity. but don't kown how. Thank you for your reply!
     
  4. theANMATOR2b

    theANMATOR2b

    Joined:
    Jul 12, 2014
    Posts:
    7,790
    My understanding is (possibly wrong) a little different. If your character hierarchy is set up how Unity likes it will recognize the root node automatically, without need to manually or via code set the root node in the editor.
    If Unity doesn't do this automatically there may be something you can do to your animation rig to help Unity identify the root node. If you can find the proper hierarchy setup Unity should recognize the root automatically.
    Possibly create a Master Root the Bip001 is linked to in Max and re-export. This master root will be the parent Unity should recognize automatically.
    For good measure place it where Jself suggested -
    I'll call upon @Mecanim.Dev the most knowledgeable person I know of on these forums regarding mecanim, to clarify any information that is incorrect.
     
  5. laoguai

    laoguai

    Joined:
    Feb 2, 2015
    Posts:
    4
    Unity doesn't set Root Node by default when Importing generic animation.So i need to set Root Node additionally in order to use animation root motion. maybe i am wrong?
     
  6. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    No you are not wrong, the root motion node is not exposed on ModelImporter API.

    they only way to set it is with SerializedObject.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEditor;
    4. using System.Collections;
    5.  
    6. public class SetRootMotionNode {
    7.  
    8.     [MenuItem("Mecanim/SetRootMotionNode")]
    9.     static void DoSetRootMotionNode()
    10.     {
    11.         Object obj = Selection.activeObject;
    12.         if (obj == null)
    13.             return;
    14.  
    15.         string assetPath = AssetDatabase.GetAssetPath(obj);
    16.         ModelImporter modelImporter = AssetImporter.GetAtPath(assetPath) as ModelImporter;
    17.         if (modelImporter == null)
    18.             return;
    19.  
    20.         SerializedObject modelImporterObj = new SerializedObject(modelImporter);
    21.         SerializedProperty rootNodeProperty = modelImporterObj.FindProperty("m_HumanDescription.m_RootMotionBoneName");
    22.  
    23.         rootNodeProperty.stringValue = "Beta:Hips";
    24.  
    25.         modelImporterObj.ApplyModifiedProperties();
    26.         AssetDatabase.ImportAsset(assetPath);
    27.     }
    28. }
     
    dnokiseki2 and damikuru like this.
  7. theANMATOR2b

    theANMATOR2b

    Joined:
    Jul 12, 2014
    Posts:
    7,790
    My apologies for the incorrect information @laoguai, You are correct root node is set to none by default and doesn't change regardless of the rig setup. And thanks for the clarification mecanim.dev.
     
  8. laoguai

    laoguai

    Joined:
    Feb 2, 2015
    Posts:
    4
    Thank you mecanim.dev, you solved my problem, thank you Unity's great support!

    To theANMATOR2b:
    You are welcome, thank you for your replay.
    And thank you all friends trying to answer my question. Thank you!
     
    theANMATOR2b likes this.
  9. damikuru

    damikuru

    Joined:
    Jul 19, 2013
    Posts:
    1
    Thank you so much!!! This solved my problem too :)
     
  10. jashan

    jashan

    Joined:
    Mar 9, 2007
    Posts:
    3,307
    Haha, kind of funny - this thread is about 2.5 years old, and today, it solved a problem for me, too ;-)

    What I wonder about, though: Why does this not work with ModelImporter.motionNodeName? Also, I first tried using the path from transformPaths which created a very broken model. In our case, while the actual path is Armature/Root, it only works when putting in "Root".
     
    AubreyH likes this.
  11. hong1991

    hong1991

    Joined:
    Sep 16, 2017
    Posts:
    14
    It works, but looks ugly.
     
    Karsten likes this.
  12. AubreyH

    AubreyH

    Joined:
    May 17, 2018
    Posts:
    18
    It would be nice to be able to somehow find the root bone from an Avatar definition at runtime.
     
    Last edited: Jan 18, 2019
  13. Toylips

    Toylips

    Joined:
    Feb 15, 2013
    Posts:
    28
    @Mecanim-Dev thank you for the code!

    Dunno why, but had to fix a bit for working.

    I'm using
    Code (CSharp):
    1. modelImporter.motionNodeName = "root";
    now it looks a bit different

    Code (CSharp):
    1. public class SetRootMotionNode
    2. {
    3.  
    4.     [MenuItem("Mecanim/SetRootMotionNode")]
    5.     public static void DoSetRootMotionNode()
    6.     {
    7.         Object[] objs = Selection.objects;
    8.         if (objs == null)
    9.             return;
    10.  
    11.         foreach (Object obj in objs)
    12.         {
    13.             string assetPath = AssetDatabase.GetAssetPath(obj);
    14.             ModelImporter modelImporter = AssetImporter.GetAtPath(assetPath) as ModelImporter;
    15.             if (modelImporter == null)
    16.                 return;
    17.  
    18.             modelImporter.motionNodeName = "root";
    19.  
    20.             SerializedObject modelImporterObj = new SerializedObject(modelImporter);
    21.  
    22.             modelImporterObj.ApplyModifiedProperties();
    23.  
    24.             AssetDatabase.ImportAsset(assetPath);
    25.         }
    26.     }
    27. }
     
    iglooGameDev likes this.