Reputation: 53
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
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
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