Search Unity

Scripting with Mechanim

Discussion in 'Animation' started by tgraupmann, Oct 5, 2013.

  1. tgraupmann

    tgraupmann

    Joined:
    Sep 14, 2007
    Posts:
    828
    I noticed that the Animator API relies heavily on HashIDs per:
    http://unity3d.com/learn/tutorials/projects/stealth/hashids

    I'm not about to hardcode all the strings though. I'm dealing with Mixamo and all the animate states get the .anim filename. That would be a lot of manual hardcoding.

    Code (csharp):
    1. int dyingState = Animator.StringToHash("Base Layer.Dying");
    2.  
    I wanted a way to just get the string from the AnimatorStateInfo.

    I just call the following from my custom inspectors and panels so that I can display the friendly names.

    First I build the layers and hashes in my custom inspector OnEnable.

    Code (csharp):
    1.     private void OnEnable()
    2.     {
    3.         AnimatorEx.BuildLayers();
    4.         AnimatorEx.BuildStateHash();
    5.     }
    And then I can display the friendly name in OnInspectorGUI.

    Code (csharp):
    1. EditorGUILayout.TextField("State Name", AnimatorEx.HashToString(info.nameHash));
    Here's the class to auto build the string lists by searching for .anim files and looking for Animator objects in your scene.

    Code (csharp):
    1. using System.Collections.Generic;
    2. using System.IO;
    3. using UnityEditor;
    4. using UnityEngine;
    5.  
    6. public static class AnimatorEx
    7. {
    8.     private static List<string> m_layers = new List<string>();
    9.  
    10.     public static void BuildLayers()
    11.     {
    12.         foreach (Animator animator in GameObject.FindObjectsOfType(typeof (Animator)))
    13.         {
    14.             if (animator)
    15.             {
    16.                 for (int index = 0; index < animator.layerCount; ++index)
    17.                 {
    18.                     string layer = animator.GetLayerName(index);
    19.                     if (!m_layers.Contains(layer))
    20.                     {
    21.                         m_layers.Add(layer);
    22.                         //Debug.Log(layer);
    23.                     }
    24.                 }
    25.             }
    26.         }
    27.     }
    28.  
    29.     private static Dictionary<int, string> m_stateHash = new Dictionary<int, string>();
    30.  
    31.     public static string HashToString(int hash)
    32.     {
    33.         if (m_stateHash.ContainsKey(hash))
    34.         {
    35.             return m_stateHash[hash];
    36.         }
    37.         else
    38.         {
    39.             return hash.ToString();
    40.         }
    41.     }
    42.  
    43.     public static void BuildStateHash()
    44.     {
    45.         m_stateHash.Clear();
    46.         foreach (string path in AssetDatabase.GetAllAssetPaths())
    47.         {
    48.             if (path.ToLower().EndsWith(".anim"))
    49.             {
    50.                 foreach (string layer in m_layers)
    51.                 {
    52.                     string name = layer + "." + Path.GetFileNameWithoutExtension(path);
    53.                     int hash = Animator.StringToHash(name);
    54.                     //Debug.Log(string.Format("hash: {0} name={1}", hash, name));
    55.                     m_stateHash[hash] = name;
    56.                 }
    57.             }
    58.         }
    59.     }
    60. }
     
    Last edited: Oct 5, 2013
  2. tgraupmann

    tgraupmann

    Joined:
    Sep 14, 2007
    Posts:
    828
    For my next trick, I'm trying to script access to the motion property of the state. I need to be able to assign a different animation so that I can trim the existing animation.

    Is there a way?

    I'll have to dig with reflection and inspection...

    Thanks