How can I set a default pose for my character?

I want my character to stay on T-Pose on the scene, by default they assume the last pose keyed on my modelling application when I grabbed them from the project window to the scene. I know that the UT use different files for different clips but I’m putting everything together because I don’t like to work that way. No workarounds - there are any way to do this? … A default character pose option?

I've been having this exact same problem on some of my characters, most of them I have the animations split before importing but for a few I need to have the animations all in one long take and split them in unity or they freak out with mechanim. I'd just like to be able to see the characters in T-pose during scene view. It'd make life much easier.

For me, my character is always in his t-pose. I believe it is the pose that I exported him in (the pose that isn't an animation) from Blender.

Hyperion, are you setting the t-pose character as the avatar in mechanim? Thanks for the quick reply!

The buttons I press are: Configure-->Enforce T-Pose--> Done.

I'm not sure if I'm explaining the issue well enough, it's the same thing that Rodolfo was having issues with. The pose the character assumes in the scene view is the last keyframe. Mine happens to be the characters death. So in the scene view he's always slumped on the ground. I guess I could set the last key to be the t-pose and just cut it out within mechanim. Though that seems really dirty. I was wondering if there was a cleaner way to do it.

7 Answers

7

enter play mode

perform expected pose

pause play mode

copy character object in hierarchy

exit play mode

in hierarchy, delete old character object

paste copied character object in hierarchy, it will work

attention: ctrl+z and undo delete if you regret

saved my butt dude

thank you so much!

wow cant believe thats eazy my dude thanks!

create an animation file with your t-pose / default position you want the character in, and then name it so that it is alphabetically FIRST in your list of animations. Then, if the model doesn’t get positioned to your liking immediately, re-drag in its prefab into the scene , and it should be posed as the first alphabetized animation you have on the fbx.

I love this solution. Solved my having no default pose problem in a few seconds

This seems to be the one correct solution between all the hacks and tricks. Simply make sure the default animation name starts with a "0". In Blender, that would be the name of the action - not the NLA track or strip, but the action - which is displayed on the title bar of the Action Editor panel.

If you want the character to have the pose seen in the scene view, then while you’re in there, drag the character from the scene and into a folder to transform it into a prefab. Now when you drag the prefab into the scene, the character should have the desired pose.

1 Like

The method I know uses a state machine. First, animate a default pose (needs at least 1 keyframe). Next, import into Unity. After that, add an Animator Controller to your character. Open that AC (animatorcontroller/state machine) and drag your pose ‘animation’ in there (it should appear like an orange block. If it’s not orange, then it’s not default). You might want to configure an avatar for Mecanim while at it, but you don’t have to.

Once you’ve followed those steps, every time you play, the character will start with your ‘default pose’. Feel free to ask questions.

Actually, I want a default pose for when the game is not playing, instead, that static pose that the character assumes on the scene view.

Hmm... That's quite interesting, because my character always assumes his tpose in scene view no matter what animations were playing. Are you using Mecanim or are you manipulating animations through code? Because that might be the difference.

I was having a similiar problem, i needed my character in a t pose when dragged onto the scene, I changed his Animation type from Humanoid to None under the Rig tab in the model import settings. dont know if this helps

Just change the character pose you want to use for the Scene View simply in Animation Timeslider.
First select the character in the scene → then in the animation window the corresponding clip which contains the desired pose select → and if necessary, move the Timeslider to the desired frame/pose.
If you have the character in view, you can see the pose live changed. Now you can continue your work on it.

I ran into a similar issue, so I wrote a script to copy the T post from one instance of a model to the one that was stuck in the weird pose. This makes nasty use of OnDrawGizmos to affect something in the Editor, and I should have written it as an Editor Extension instead, but it got the job done very nicely.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// <para>Clones all the localPositions, localRotations, and localScales
/// of the children of a GameObject so that they can be applied to another
/// GameObject. This can be used to copy the current pose from one 
/// humanoid character to another.</para>
/// 
/// <para>When working on this project, I ran into an issue where the 
/// player character (called Player in my scene) got stuck in a really 
/// bizarre pose, and looking online, there really wasn't an easy way to 
/// reset her to a T pose. So I wrote this script.</para>
/// 
/// <para>To use this, I dragged a second copy of the player character 
/// model into the scene and dragged its Skeleton child GameObject into 
/// the activeGO field. Then, I checked the checkToCopy bool. Because this
/// is handled in OnDrawGizmos, the game does not need to be running, and 
/// it can make changes to the scene that are saved.</para>
/// 
/// <para>Then, I dragged the Skeleton child GameObject of Player into the
/// activeGO field and checked checkToPaste. This applied the T pose back 
/// to Player. </para>
/// 
/// <para>NOTE: The copy and paste is based on the names of all the 
/// GameObjects in the hierarchy, so if something is named differently or 
/// doesn't exist in one of the models, it is ignored.</para>
/// 
/// <para>NOTE: You should be very careful with this kind of use of 
/// OnDrawGizmos. I shoudl have written an Editor Editor Extension script 
/// to do this, but I haven't had the time yet.</para>
/// 
/// <para>FINAL NOTE: When you paste the pose, it won't immediately update
/// in the Scene window, but if you click on another object or do anything
/// else to update the Scene pane, you will see that the paste happened 
/// properly.</para>
/// </summary>
public class PoseCloner : MonoBehaviour {
    public struct TransRec {
        public Vector3      pos;
        public Quaternion   rot;
        public Vector3      scale;

        public TransRec(Transform transform) {
            pos = transform.localPosition;
            rot = transform.localRotation;
            scale = transform.localScale;
        }

        public void SetTransform(Transform t) {
            t.localPosition = pos;
            t.localRotation = rot;
            t.localScale = scale;
        }
    }

    static public Dictionary<string, TransRec> poseDict;

    public GameObject   activeGO;
    public bool         checkToCopy, checkToPaste;

    private void OnDrawGizmos()
    {
        if (checkToCopy) {
            Copy();
            checkToCopy = false;
        }

        if (checkToPaste) {
            Paste();
            checkToPaste = false;
        }
    }

    // Use this for initialization
    void Copy() {
        if (activeGO == null) return;
        Transform[] tforms = activeGO.GetComponentsInChildren<Transform>();

        poseDict = new Dictionary<string, TransRec>();

        string str;
        foreach (Transform t in tforms) {
            str = GetPathName(t);
            poseDict.Add(str, new TransRec(t));
        }

        Debug.Log("PoseCloner:Copy() - Copied "+tforms.Length+" transforms.");
    }

    void Paste() {
        if (activeGO == null) return;
        if (poseDict == null || poseDict.Count == 0) {
            Debug.Log("PoseCloner:Paste() - No copied data exists to paste.");
            return;
        }
        Transform[] tforms = activeGO.GetComponentsInChildren<Transform>();
        int pasteCount = 0;
        List<string> pasted = new List<string>();
        List<string> skipped = new List<string>();
        List<string> notFound = new List<string>();

        string str;
        foreach (Transform t in tforms) {
            str = GetPathName(t);
            if (poseDict.ContainsKey(str)) {
                poseDict[str].SetTransform(t);
                pasteCount++;
                pasted.Add(str);
            } else {
                notFound.Add(str);
            }
        }

        foreach (string s in poseDict.Keys) {
            if (pasted.IndexOf(s) == -1) {
                skipped.Add(s);
            }
        }

        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        sb.Append("PoseCloner:Paste() -");
        sb.Append(" Pasted:"+pasted.Count);
        sb.Append(" Skipped:"+skipped.Count);
        sb.AppendLine(" NotFoundInPoseDict:"+notFound.Count);
        sb.AppendLine();

        sb.AppendLine("Pasted:");
        foreach (string s in pasted) {
            sb.Append("	");
            sb.AppendLine(s);
        }
        sb.AppendLine();

        sb.AppendLine("Skipped:");
        foreach (string s in skipped) {
            sb.Append("	");
            sb.AppendLine(s);
        }
        sb.AppendLine();

        sb.AppendLine("NotFoundInPoseDict:");
        foreach (string s in notFound) {
            sb.Append("	");
            sb.AppendLine(s);
        }

        Debug.Log(sb.ToString());
    }


    string GetPathName(Transform t) {
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        sb.Append(t.gameObject.name);
        while (t != activeGO.transform) {
            t = t.parent;
            if (t == null) {
                break;
            }
            sb.Insert(0,":");
            sb.Insert(0, t.gameObject.name);
        }
        return sb.ToString();
    }

}