Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

Blender single-posed armature axis update helper script

Discussion in 'External Tools' started by Jovssen, Aug 2, 2019.

  1. Jovssen

    Jovssen

    Joined:
    Jun 3, 2016
    Posts:
    28
    If the conversion of your assets is too time consuming or meaningless (especially if you're near launch), you can modify a python file to fix it all. (But obviously if you've just started a project it's probably best to convert to the new axes.)
    It can be useful to add
    Code (CSharp):
    1. primary_bone_axis='X', secondary_bone_axis='-Y')
    to the Unity-BlenderToFBX.py file.
    But Unity itself is welcoming the new primary axes, so you'd have to keep adding that to every new update.

    This might be useful as well: https://forum.unity.com/threads/blender-unity-rotation-fix.181870/


    And also the update to 2.8 brings object naming (and therefore referencing) issues that can be fixed with this: https://blenderartists.org/t/blende...r-unity-has-used-ascii-fbx-internally/1172264




    The primary bone axis of x changed to y (I believe due to a bug being fixed), so I made a script to update some of my broken armatures (I had posed several static armatures). This doesn't help for animations, but otherwise I hope it can be useful. It's not perfect though, and doesn't cover many use cases, but it might help.

    You need to toggle the collect boolean, this should be done only before you toggle the apply boolean. Just fiddle with the settings. After it's fixed just remove the script.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class ArmatureUpdater : MonoBehaviour
    6. {
    7.     [Tooltip("If the transform fields were overriden, then this information will be put to use")]
    8.     public bool collect;
    9.  
    10.     [Space(100)]
    11.  
    12.     public bool apply;
    13.  
    14.     [Space(20)]
    15.  
    16.     public Vector3 axis0 = new Vector3(0, 0, 1);
    17.     public Vector3 axis1 = new Vector3(-1, 0, 0);
    18.  
    19.     [Tooltip("When the position was overidden, or if the prefab has been unpacked")]
    20.     public bool localPositionAlso;
    21.  
    22.     //public bool doPositionFitting;
    23.     //public int fitCount = 100000;
    24.  
    25.     [Space(100)]
    26.  
    27.     public List<TransformData> transformDatas = new List<TransformData>();
    28.     [System.Serializable]
    29.     public class TransformData
    30.     {
    31.         public Transform transform;
    32.  
    33.         public Vector3 localPosition;
    34.         public Quaternion rotation;
    35.         public Vector3 position;
    36.  
    37.         public int[] children;
    38.     }
    39.  
    40.  
    41.     private TransformData Collect(Transform tr)
    42.     {
    43.         var t = new TransformData();
    44.         transformDatas.Add(t);
    45.         t.transform = tr;
    46.  
    47.         t.rotation = tr.rotation;
    48.         t.localPosition = tr.localPosition;
    49.         t.position = tr.position;
    50.  
    51.         t.children = new int[tr.childCount];
    52.         for (int i = 0; i < tr.childCount; i++)
    53.         {
    54.             t.children[i] = transformDatas.Count;
    55.             Collect(tr.GetChild(i));
    56.         }
    57.  
    58.         return t;
    59.     }
    60.     private void Apply(TransformData t)
    61.     {
    62.         t.transform.rotation = Quaternion.LookRotation(t.rotation * axis0, t.rotation * axis1);
    63.  
    64.         if (localPositionAlso && t.transform != transform)
    65.             //t.transform.position = t.position;
    66.             t.transform.localPosition = new Vector3(t.localPosition.y, -t.localPosition.x, t.localPosition.z);
    67.  
    68.         UnityEditor.EditorUtility.SetDirty(t.transform.gameObject);
    69.  
    70.         for (int i = 0; i < t.children.Length; i++)
    71.             Apply(transformDatas[t.children[i]]);
    72.     }
    73.     private void OnValidate()
    74.     {
    75.         if (apply)
    76.         {
    77.             apply = false;
    78.             UnityEditor.Undo.RegisterFullObjectHierarchyUndo(gameObject, "Fix Armature Pose");
    79.        
    80.  //Apply(transformDatas[0]);
    81.             Apply(transformDatas[transformDatas[0].children[0]]);
    82.        
    83.  
    84.             /*
    85.             if (doPositionFitting)
    86.             {
    87.                 Quaternion original = transform.rotation;
    88.  
    89.                 Quaternion best = new Quaternion();
    90.                 float bestOffness = Mathf.Infinity;
    91.                 for (int i = 0; i < fitCount; i++)
    92.                 {
    93.                     var rot = Random.rotation;
    94.                     transform.rotation = rot;
    95.  
    96.                     float totalOff = 0;
    97.                     for (int ii = 0; ii < transformDatas.Count; ii++)
    98.                     {
    99.                         var td = transformDatas[ii];
    100.                         totalOff += (td.transform.position - td.position).magnitude;
    101.                     }
    102.  
    103.                     if (totalOff < bestOffness)
    104.                     {
    105.                         best = rot;
    106.                         bestOffness = totalOff;
    107.                     }
    108.                 }
    109.  
    110.                 transform.rotation = best;
    111.  
    112.                 Debug.Log((Quaternion.Inverse(original) * best).eulerAngles); //?
    113.             }
    114.             */
    115.         }
    116.  
    117.         if (collect)
    118.         {
    119.             collect = false;
    120.             transformDatas.Clear();
    121.             Collect(transform);
    122.         }
    123.     }
    124.  
    125.     private void OnDrawGizmosSelected()
    126.     {
    127.         for (int i = 0; i < transformDatas.Count; i++)
    128.         {
    129.             var td = transformDatas[i];
    130.  
    131.             Gizmos.color = Color.green;
    132.             Gizmos.DrawSphere(td.position, .25f);
    133.             Gizmos.color = Color.red;
    134.             Gizmos.DrawSphere(td.transform.position, .125f);
    135.  
    136.             Gizmos.color = Color.yellow;
    137.             Gizmos.DrawLine(td.position, td.transform.position);
    138.         }
    139.     }
    140. }
     
    Last edited: Aug 15, 2019