Caíck
Caíck

Reputation: 53

Flipping an enemy sprite when he turns around in Unity

I'm some hours already trying to solve this, I tried many ways but none of them worked...

So I have an enemy that follows the player using an AI and I need the sprite to flip when the enemy turn left or turn right.

Here's a part of my code (A lot of the code is about the AI so I'll post just part of it)

Vector3 dir = ( path.vectorPath[currentWaypoint] - transform.position ).normalized;
dir *= speed * Time.fixedDeltaTime;

//Move the AI
rb.AddForce (dir, fMode);

void Update () {

    if (rb.AddForce > 0) {
        sr.flipX = false;
    } else if (rb.AddForce < 0)
        sr.flipX = true;

    animate.SetFloat ("pMove", Mathf.Abs(rb.AddForce));   
}

Upvotes: 3

Views: 3610

Answers (2)

Serkan Pek&#231;etin
Serkan Pek&#231;etin

Reputation: 693

Assuming, sr is a SpriteRenderer component, sr.flipX approach is fine. However, your assessment of the force on the Rigidbody is not right. rb.AddForce has the return type of void, and a proper way of reading whether the Rigidbody had an applied force on it is to read rb.velocity.magnitude. Also, rb.velocity would give you the direction of the GameObject's velocity as a Vector3. Assuming that you are working on the X-axis, putting this in your LateUpdate method:

sr.flipX = rb.velocity.magnitude > 0 && rb.velocity.x < 0 ? true : false;

instead of the if-else block at your Update method would flip the sprite along the X-axis if the Rigidbody is moving (rb.velocity.magnitude > 0) and it is moving towards the left-hand side (rb.velocity.x < 0).

In your question, you have asked only to flip the sprite: As Unity documentation states, flipX only affects rendering, not the other components (such as colliders and animators).

Upvotes: 1

Ignacio Alorre
Ignacio Alorre

Reputation: 7605

The easiest way to flip a sprite is using localScale.x *= -1; And instead of checking the AddForce you should check the velocity of the rigidbody in the x axis (or y axis if you flip as well the sprite depending on if it is jumping or falling)

Basically in Update() you can do something like this: vx = rigidbody.velocity.x; to store the velocity in the x axis of the sprite. Then in LastUpdate() you check if it is necessary to flip the sprite or not:

if (vx > 0) {
    facingRight = true;
} else if (vx < 0) { 
    facingRight = false;
}

if (((facingRight) && (localScale.x<0)) || ((!facingRight) && (localScale.x>0))) {
    localScale.x *= -1;
}

Here you have a whole example where the sprite moves based on the player's inputs. You will need to addapt it for your AI.

//store references to components on the gameObject
Transform transform;
Rigidbody2D rigidbody;

public float MoveSpeed = 3f;

// hold player motion in this timestep
float vx;
float vy;

Awake () {
    // get a reference to the components we are going to be changing and store a reference for efficiency purposes
    transform = GetComponent<Transform> ();
    rigidbody = GetComponent<Rigidbody2D> ();

}


void Update()
{
    // determine horizontal velocity change based on the horizontal input
    vx = Input.GetAxisRaw ("Horizontal");

    //Change in case you are jumping or falling
    vy = rigidbody.velocity.y;

    // Change the actual velocity on the rigidbody
    rigidbody.velocity = new Vector2(_vx * MoveSpeed, _vy);

}

// Checking to see if the sprite should be flipped
// this is done in LateUpdate since the Animator may override the localScale
// this code will flip the player even if the animator is controlling scale
void LateUpdate()
{
    // get the current scale
    Vector3 localScale = transform.localScale;

    if (vx > 0) // moving right so face right
    {
        facingRight = true;
    } else if (vx < 0) { // moving left so face left
        facingRight = false;
    }

    // check to see if scale x is right for the player
    // if not, multiple by -1 which is an easy way to flip a sprite
    if (((facingRight) && (localScale.x<0)) || ((!facingRight) && (localScale.x>0))) {
        localScale.x *= -1;
    }   

    // update the scale
    transform.localScale = localScale;
}

Upvotes: 1

Related Questions