Search Unity

[Editor] Rename AnimatorController parameters by script?

Discussion in 'Animation' started by FeastSC2, Mar 26, 2020.

  1. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    978
    I want to rename the parameters in my animatorController without calling AnimatorController.RemoveParameter (or the controller loses the references to the parameters in its transitions).

    Calling parameter.name = newName does not work, it seems the only way to modify a parameter is to call AddParameter.

    This code below works BUT it destroys the references to the parameters on the transitions.
    Any idea how I can rename the parameters by script without destroying the parameter's references?

    Code (CSharp):
    1.    
    2.     private static void ReplaceAnimatorParameterNames(AnimatorController _controller, string _from, string _by = "")
    3.     {
    4.         var parameters = _controller.parameters;
    5.         var count = parameters.Length;
    6.         Undo.RegisterCompleteObjectUndo(_controller, "Animator rename states");
    7.         for (var i = 0; i < count; i++)
    8.         {
    9.             var param = parameters[i];
    10.             _controller.RemoveParameter(param);
    11.             param.name = param.name.Replace(_from, _by);
    12.             _controller.AddParameter(param);
    13.         }
    14.     }
    15.  
     
    ColorStorm and mandisaw like this.
  2. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    I assume you've already tried all the functions that look like they might work so I wouldn't be surprised if it's not directly possible. You could try looking through the source code of the Animator window to find out how it does it. Or you might be able to do it by parsing the file as text and modifying the part you want.
     
  3. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    978
    I ended up editing the .controller file.

    Here's the code, it's messy but it works


    Code (CSharp):
    1.  public static void EditParameterNames(AnimatorController _controller, bool _addParameterTypeInName)
    2.     {
    3.         if (_controller == null)
    4.         {
    5.             Debug.LogError($"no controller");
    6.             return;
    7.         }
    8.      
    9.         var path = AssetDatabase.GetAssetPath(_controller).Substring(7);
    10.         string filename = $"{Application.dataPath}/{path}";
    11.         StringBuilder result = new StringBuilder();
    12.         Debug.Log($"path: {filename}");
    13.         var nameID = "- m_Name: ";
    14.  
    15.         Dictionary<string, ParameterRenamed> renameList = new Dictionary<string, ParameterRenamed>();
    16.  
    17.         if (System.IO.File.Exists(filename))
    18.         {
    19.             Debug.Log($"opened file: {filename}");
    20.             PopulateRenameList(filename, nameID, renameList);
    21.  
    22.             using (StreamReader streamReader = new StreamReader(filename))
    23.             {
    24.                 String line;
    25.                 while ((line = streamReader.ReadLine()) != null)
    26.                 {
    27.                     var newLine = line + Environment.NewLine;
    28.                     foreach (var p in renameList)
    29.                     {
    30.                         var oldName = p.Value.StartName;
    31.                         if (line.Contains(oldName, StringComparison.Ordinal))
    32.                         {
    33.                             Debug.Log($"found line with '{p.Value.StartName}': {line}");
    34.                             var newName = oldName.Replace(" ", "");
    35.                             var paramLetter = ParamToString(p.Value.ParamType);
    36.                          
    37.                             var paramDesc = paramLetter +  "_";
    38.                             newName = _addParameterTypeInName ? paramDesc + newName : newName;
    39.                             newLine = line.Replace(oldName, newName) + Environment.NewLine;
    40.                             break;
    41.                         }
    42.                     }
    43.  
    44.                     result.Append(newLine);
    45.                 }
    46.             }
    47.         }
    48.      
    49.         using (System.IO.StreamWriter file =
    50.             new System.IO.StreamWriter(@filename))
    51.         {
    52.             Debug.Log("writing");
    53.             file.WriteLine(result.ToString());
    54.             file.Close();
    55.         }
    56.     }
    57.  
    58.     private static void PopulateRenameList(string filename, string nameID, Dictionary<string, ParameterRenamed> renamed)
    59.     {
    60.         using (StreamReader streamReader = new StreamReader(filename))
    61.         {
    62.             String line;
    63.             while ((line = streamReader.ReadLine()) != null)
    64.             {
    65.                 if (line.Contains(nameID, StringComparison.Ordinal))
    66.                 {
    67.                     var startName = line.Substring(nameID.Length + 2);
    68.  
    69.                     if (renamed.ContainsKey(startName) == false)
    70.                     {
    71.                         var nextLine = streamReader.ReadLine();
    72.                         //  Find the parameter type!
    73.                         var type = TryGetParameterType(nextLine);
    74.  
    75.                         renamed.Add(startName, new ParameterRenamed() {StartName = startName, ParamType = type});
    76.                     }
    77.                 }
    78.             }
    79.         }
    80.     }
    81.  
    82.     private static string ParamToString(Param _param)
    83.     {
    84.         switch (_param)
    85.         {
    86.             default:
    87.             case Param.Unknown:
    88.                 return string.Empty;
    89.             case Param.T:
    90.                 return "T";
    91.             case Param.B:
    92.                 return "B";
    93.             case Param.F:
    94.                 return "F";
    95.             case Param.I:
    96.                 return "I";
    97.         }
    98.     }
    99.  
    100.     private static Param TryGetParameterType(string _nextLine)
    101.     {
    102.         var typeID = "    m_Type: ";
    103.         if (_nextLine.Contains(typeID, StringComparison.Ordinal))
    104.         {
    105.             var numberString = _nextLine.Substring(typeID.Length, 1);
    106.             int number = int.Parse(numberString);
    107.             if (number == 4)
    108.                 return Param.B;
    109.             if (number == 9)
    110.                 return Param.T;
    111.             if (number == 3)
    112.                 return Param.I;
    113.             if (number == 1)
    114.                 return Param.F;
    115.         }
    116.         return Param.Unknown;
    117.     }
    118.  
    119. public struct ParameterRenamed
    120. {
    121.     public string StartName;
    122.     public Param ParamType;
    123. }
    124. public enum Param
    125. {
    126.     Unknown,
    127.     T,
    128.     B,
    129.     F,
    130.     I
    131. }
    132.  
    133.  
     
    ColorStorm likes this.
  4. mandisaw

    mandisaw

    Joined:
    Jan 4, 2018
    Posts:
    83
    Thanks for this - I just did a replace on the controller file with a text editor directly. It's weird that Unity doesn't have a command for this already.
     
    FeastSC2 likes this.
  5. ColorStorm

    ColorStorm

    Joined:
    Jul 4, 2012
    Posts:
    28
    Lifesaver, thanks!
     
    FeastSC2 likes this.