Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How to create their your own Humanoid Avatar without fbx importing

Discussion in 'Animation' started by Abbrew, Dec 24, 2020.

  1. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    You need to have a GameObject hierarchy that matches the avatar hierarchy.
    Once you have this, select the Root GameObject and click on the Custom Tools Tab and click Create Human Avatar. A Humanoid Avatar will be generated at the Assets directory. If you need to include additional body parts, add its name to HUMAN_NAMES and its GameObject to the hierarchy.

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEditor;
    3. using UnityEngine;
    4.  
    5. public class AvatarMaker
    6. {
    7.     private static readonly List<string> HUMAN_NAMES = new List<string>()
    8.     {
    9.         "Head",
    10.         "Hips",
    11.         "LeftFoot",
    12.         "LeftHand",
    13.         "LeftLowerArm",
    14.         "LeftLowerLeg",
    15.         "LeftUpperArm",
    16.         "LeftUpperLeg",
    17.         "RightFoot",
    18.         "RightHand",
    19.         "RightLowerArm",
    20.         "RightLowerLeg",
    21.         "RightUpperArm",
    22.         "RightUpperLeg",
    23.         "Spine",
    24.     };
    25.  
    26.     private static readonly int RECURSION_DEPTH_LIMIT = 50;
    27.  
    28.     [MenuItem("CustomTools/MakeHumanAvatar")]
    29.     private static void MakeHumanAvatar()
    30.     {
    31.         GameObject activeGameObject = Selection.activeGameObject;
    32.  
    33.         if (activeGameObject != null)
    34.         {
    35.             var numHumanBones = HUMAN_NAMES.Count;
    36.             HumanBone[] humanBones = new HumanBone[numHumanBones];
    37.             for (var i = 0; i < numHumanBones; i++)
    38.             {
    39.                 var humanName = HUMAN_NAMES[i];
    40.                 humanBones[i] = new HumanBone
    41.                 {
    42.                     boneName = humanName,
    43.                     humanName = humanName
    44.                 };
    45.                 humanBones[i].limit.useDefaultValues = true;
    46.             }
    47.  
    48.             var skeletonBones = new SkeletonBone[numHumanBones + 1];
    49.             skeletonBones[0] = new SkeletonBone
    50.             {
    51.                 name = "Root",
    52.                 position = Vector3.zero,
    53.                 rotation = Quaternion.identity,
    54.                 scale = Vector3.one
    55.             };
    56.  
    57.             for (var i = 0; i < numHumanBones; i++)
    58.             {
    59.                 var humanName = HUMAN_NAMES[i];
    60.                 BoneOffsetFromRoot(
    61.                     activeGameObject,
    62.                     humanName,
    63.                     out var position,
    64.                     out var rotation,
    65.                     out var scale
    66.                 );
    67.  
    68.                 skeletonBones[i + 1] = new SkeletonBone
    69.                 {
    70.                     name = humanName,
    71.                     position = position,
    72.                     rotation = rotation,
    73.                     scale = scale
    74.                 };
    75.             }
    76.  
    77.             var humanDescription = new HumanDescription
    78.             {
    79.                 upperArmTwist = 0.5f,
    80.                 lowerArmTwist = 0.5f,
    81.                 upperLegTwist = 0.5f,
    82.                 lowerLegTwist = 0.5f,
    83.                 armStretch = 0.5f,
    84.                 legStretch = 0.5f,
    85.                 feetSpacing = 0.0f,
    86.                 hasTranslationDoF = false,
    87.                 human = humanBones,
    88.                 skeleton = skeletonBones
    89.             };
    90.  
    91.             Avatar avatar = AvatarBuilder.BuildHumanAvatar(activeGameObject, humanDescription);
    92.             avatar.name = activeGameObject.name;
    93.             Debug.Log(avatar.isHuman ? "is human" : "is generic");
    94.  
    95.             var path = string.Format("Assets/{0}.ht", avatar.name.Replace(':', '_'));
    96.             AssetDatabase.CreateAsset(avatar, path);
    97.         }
    98.     }
    99.  
    100.     private static void BoneOffsetFromRoot(
    101.         GameObject rootGameObject,
    102.         string boneName,
    103.         out Vector3 position,
    104.         out Quaternion rotation,
    105.         out Vector3 scale
    106.     )
    107.     {
    108.         Debug.Log(boneName);
    109.         var boneTransform = RecursiveFindChild(rootGameObject.transform,boneName);
    110.         var boneLocalPosition = boneTransform.transform.localPosition;
    111.         var boneLocalRotation = boneTransform.transform.localRotation;
    112.         var boneLocalScale = boneTransform.transform.localScale;
    113.  
    114.  
    115.         GameObjectOffsetFrom(
    116.             rootGameObject.transform,
    117.             boneTransform,
    118.             in boneLocalPosition,
    119.             in boneLocalRotation,
    120.             in boneLocalScale,
    121.             out position,
    122.             out rotation,
    123.             out scale,
    124.             0
    125.         );
    126.     }
    127.  
    128.     private static void GameObjectOffsetFrom(
    129.         Transform ancestorTransform,
    130.         Transform gameObjectTransform,
    131.         in Vector3 inputPosition,
    132.         in Quaternion inputRotation,
    133.         in Vector3 inputScale,
    134.         out Vector3 position,
    135.         out Quaternion rotation,
    136.         out Vector3 scale,
    137.         int recursionDepth
    138.     )
    139.     {
    140.         if(recursionDepth > RECURSION_DEPTH_LIMIT)
    141.         {
    142.             throw new UnityException(
    143.                 "Making a human avatar failed due to incorrect" +
    144.                 " structure of the GameObject's hierarchy"
    145.             );
    146.         }
    147.  
    148.         if(ancestorTransform == gameObjectTransform)
    149.         {
    150.             position = inputPosition;
    151.             rotation = inputRotation;
    152.             scale = inputScale;
    153.             return;
    154.         }
    155.         else
    156.         {
    157.             var parentTransform = gameObjectTransform.parent;
    158.             var newPosition = inputPosition + parentTransform.localPosition;
    159.             var newRotation = inputRotation * parentTransform.localRotation;
    160.             var newScale = inputScale;
    161.             newScale.Scale(parentTransform.localScale);
    162.             GameObjectOffsetFrom(
    163.                 ancestorTransform,
    164.                 parentTransform,
    165.                 in newPosition,
    166.                 in newRotation,
    167.                 in newScale,
    168.                 out position,
    169.                 out rotation,
    170.                 out scale,
    171.                 recursionDepth
    172.             );
    173.             return;
    174.         }
    175.     }
    176.  
    177.     private static Transform RecursiveFindChild(Transform parent, string childName)
    178.     {
    179.         foreach (Transform child in parent)
    180.         {
    181.             if (child.name.Equals(childName))
    182.             {
    183.                 return child;
    184.             }
    185.             else
    186.             {
    187.                 Transform found = RecursiveFindChild(child, childName);
    188.                 if (found != null)
    189.                 {
    190.                     return found;
    191.                 }
    192.             }
    193.         }
    194.         return null;
    195.     }
    196. }
    197.  
     
    gamefish likes this.
  2. gamefish

    gamefish

    Joined:
    Jul 5, 2013
    Posts:
    14
    Great! Awsome!
     
  3. tantx

    tantx

    Joined:
    Jul 5, 2017
    Posts:
    19
    Super Cool!