Reputation: 164
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
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
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 returntrue
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