JoRouss
JoRouss

Reputation: 2884

Unity3d - How to get Animator's Layer -->Sub-State --> State namehash?

I'm using the following structure:

(Layer) "Base Layer" --> (Sub-State) "Jump_Fall_Roll" --> (State) "Roll"

static int rollState = Animator.StringToHash("What to put here??");

private Animator anim;
private AnimatorStateInfo currentBaseState;

void Start ()
{
    anim = GetComponent<Animator>();
}

void FixedUpdate ()
{
    currentBaseState = anim.GetCurrentAnimatorStateInfo(0);

    if (currentBaseState.nameHash == rollState) {
        Debug.Log ("ROLL nameHash worked"); //Not working
    }
    if (currentBaseState.IsName("Roll")) {
        Debug.Log ("ROLL IsName worked"); //Working.......
    }
}

I tryed every possible combinaison of parents/states for the nameHash, but it never worked...

The name should be in the form Layer.Name, for example "Base.Idle".

AnimatorStateInfo.IsName doc from Unity

So, why is my first case not working? And how can the second case work??

I'm really confused.

EDIT

Screenshot of my Animator view Screenshot of my Animator view

I did try static int rollState = Animator.StringToHash("Base Layer.Roll");

Then Debug.Log (currentBaseState.nameHash + ", " + rollState);

Will output

1094782407, -1476868190

When I'm in the roll state. rollState NEVER = currentBaseState.nameHash.

I did test this with the Idle state, which works perfectly like this :

static int rollState = Animator.StringToHash("Base Layer.Idle");

I can't see what the structure is for sub-states, really frustrating.

Upvotes: 2

Views: 13798

Answers (3)

user5280911
user5280911

Reputation: 763

In the most up-to-date version of 5.3.4 at time of writing, the question can be partially answered as follows.

First of all, there is no nameHash any more. The closest variable to it is shortNameHash. It is recommended to use fullPathHash instead as will be explained shortly. shortNameHash is like the bare file name in OS, while fullPathHash, as its name suggests, contains layer name as path before the state name. Here is an example to use both of them to identify the current state:

int baseState = Animator.StringToHash("Base Layer.Idle");
int short_baseState = Animator.StringToHash("Idle");
int subState = Animator.StringToHash("Base Layer.Jump_Fall_Roll.Roll");
int short_subState = Animator.StringToHash("Roll");

...

AnimatorStateInfo s = myAnimator.GetCurrentAnimatorStateInfo(0);
Debug.Log(s.fullPathHash + ", " + baseState);   //they are equal at Idle state in base layer
Debug.Log(s.shortNameHash + ", " + short_baseState);   //they are equal at Idle state in base layer
Debug.Log(s.fullPathHash + ", " + subState);   //they are equal at Roll state in sub-state machine
Debug.Log(s.shortNameHash + ", " + short_subState);   //they are equal at Roll state in sub-state machine

From the above example we can see that shortNameHash works for bare state name, no matter the state is regular one in base layer, or a state in the sub-state machine. But fullPathHash works only when layer path is properly prefixed before the state name. If we are sure there is no duplicate state names in different state machines, shortNameHash is good because it is short, but this assumption does not always hold in a large complex animator controller, so I would like to recommend using fullPathHash all the time.

I call this answer "partial" because we have to make sure the layer id passed to GetCurrentAnimatorStateInfo is 0, i.e., the "current working layer" (like the pwd command in linux) should be the base layer. The above path name convention fails if we pass 1 to it. I don't have time to guess what the path name should be in layer 1. Any complement in this regard is welcomed.

Upvotes: 6

JoRouss
JoRouss

Reputation: 2884

I seriously have no Idea what changed in my project, but I tryed

static int rollState = Animator.StringToHash ("Jump_Fall_Roll.Roll");

again (I had tested it before I post this question and spend hours trying to resolve it) and it managed to work..........

So, for Sub-States, do not include the Layer name in the hash, only the parent Sub-State of your State.

I did not test for nested Sub-States.

Thank you to those who tryed to help me

Upvotes: 2

letiagoalves
letiagoalves

Reputation: 11302

The string to pass in Animator.StringToHash should include layer's name and state's name.

So to correctly generate the hash it should be:

int rollState = Animator.StringToHash("Base Layer.Roll");

Upvotes: 1

Related Questions