Weedosaurus
Weedosaurus

Reputation: 164

Character is not changing animation state with script

I have set up the animator for a character in a 3D game. I then set some conditions to change the animation. In this case, I want the character to change from attack=0 (running) to attack=3 (attacking). It works sometimes, oddly, but most of the times the character is stuck in running animation. There are some extras on the code, for example, reducing the speed to 0 and checking for a certain script. But I'd like to focus the help on the animation changing part.

I tried enlarging the condition to change the animation but it is not working so far.

if (anim.GetInteger("attack") == 0)
        {
            if (transform.position.x > 2f && transform.position.x < 3.5f && transform.position.z == 0 ||
            transform.position.z > -3.5f && transform.position.z < -2f && transform.position.x == 0 ||
            transform.position.x > -3.5f && transform.position.x < -2f && transform.position.z == 0 ||
            transform.position.z > 2f && transform.position.z < 3.5f && transform.position.x == 0)
            {
                if (gameObject.GetComponent<LeftNPCmove>() != null)
                {
                    var go = this.gameObject;
                    var com = go.GetComponent<LeftNPCmove>();
                    com.speed -= com.speed;
                    anim.SetInteger("attack", 3);

                }

With the first conditions clause I intend to make the character change animation between the interval specified. In the second conditions clause I tell it to change the condition in the animator from 0 to 3, thus attacking. Thanks in advance.

Upvotes: 0

Views: 86

Answers (2)

YellowAfterlife
YellowAfterlife

Reputation: 3192

Based on your description, it sounds like your positions are not precisely 0.

Try swapping out your

transform.position.z == 0 

for

Mathf.Abs(transform.position.z) < 0.01f 

and same for X.

Upvotes: 0

derHugo
derHugo

Reputation: 90639

transform.position.z == 0

etc. are float values → never compare float values directly for equality! The issue you get here is floating-point precision.

Due to the limited precision there can always be rounding errors making two float values that mathematically actually should be equal still different by a tiny value called epsilon (also see Mathf.Approximately and Mathf.Epsilon).

Floating point imprecision makes comparing floats using the equals operator inaccurate. For example, 1.0 == 10.0 / 10.0 might not return true every time.

You should rather use Mathf.Approximately to compare supposed to be exact values

Mathf.Approximately(transform.position.z, 0)

which basically equals

Mathf.Abs(transform.position.z) < Mathf.Epsilon

However, for comparing positions: For moving objects in 3D space it is usually pretty much never the case that they have exact positions in one certain frame. Therefore you might rather want to use a broader range like

Mathf.Abs(transform.position.z) < 0.1f

Btw you can then shrink your code a little:

// avoid repeated API calls and calculations
var position = transform.position;
var posXAbs = Mathf.Abs(position.x);
var posZAbs = Mathf.Abs(position.z);

if (posZAbs < 0.1f && posXAbs > 2f && posXAbs < 3.5f
    || posXAbs < 0.1f && posZAbs > 2f && posZAbs < 3.5f)
{
    // avoid repeated and redundant GetComponent call
    var com = GetComponent<LeftNPCmove>();
    if (com)
    {
        // here also could appear floating point imprecision
        // so rather set a fixed value 0
        com.speed = 0; // or e.g. Vector2.zero depending what `speed` is
        anim.SetInteger("attack", 3);
    }
}

Upvotes: 1

Related Questions