Fliping dosen't work
Hi, I added animation and fliping into my game but then it suddenly extra flips. Please help here is my code.
using System.Collections;
using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class PlayerController : MonoBehaviour { public bool hitEdge; public float speed; public float jumpForce; private float moveInput; private bool facingRight = true;
private Rigidbody2D rb;
private bool isGrounded;
public Transform groundCheck;
public float checkRadius;
public LayerMask whatIsGround;
private int extraJumps;
public int extraJumpsValue;
private int nextSceneToLoad;
private bool hi;
public Animator animator;
private GameMaster gm;
GameObject Player;
void Flip()
{
facingRight = !facingRight;
Vector3 Scaler = transform.localScale;
Scaler.x *= -1;
transform.localScale = Scaler;
}
void Start()
{
gm = GameObject.FindGameObjectWithTag("GM").GetComponent<GameMaster>();
transform.position = gm.lastCheckPointPos;
extraJumps = extraJumpsValue;
rb = GetComponent<Rigidbody2D>();
nextSceneToLoad = SceneManager.GetActiveScene().buildIndex + 1;
}
void FixedUpdate()
{
if (facingRight == false && moveInput > 0)
{
Flip();
}else if (facingRight = true && moveInput < 0)
{
Flip();
}
isGrounded = Physics2D.OverlapCircle(groundCheck.position, checkRadius, whatIsGround);
moveInput = Input.GetAxis("Horizontal");
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
}
private void Update()
{
animator.SetFloat("Speed", Mathf.Abs(moveInput));
if (isGrounded == true)
{
animator.SetBool("IsJumping", false);
extraJumps = extraJumpsValue;
}
else if (isGrounded == false)
{
animator.SetBool("IsJumping", true);
}
if (Input.GetKeyDown(KeyCode.UpArrow) && extraJumps > 0)
{
rb.velocity = Vector2.up * jumpForce;
extraJumps--;
}
if (Input.GetKeyDown(KeyCode.Space) && extraJumps > 0)
{
rb.velocity = Vector2.up * jumpForce;
extraJumps--;
}
else if (Input.GetKeyDown(KeyCode.UpArrow) && extraJumps == 0 && isGrounded == true)
{
rb.velocity = Vector2.up * jumpForce;
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.tag == "Danger")
{
Scene scene;
scene = SceneManager.GetActiveScene();
SceneManager.LoadScene(scene.name);
FindObjectOfType<AudioManager>().Play("Death");
}
if (collision.collider.tag == "Door")
{
hi = true;
SceneManager.LoadScene(nextSceneToLoad);
}
}
} Thank you for advance.
When does the extra flip happens? -one time at the beginning of the game? - when you are moving right? - when you are moving left? - other case?
It is when I move left and right. Also when I am also jumping and moving it happens. But when I stop and jump it is fine.
I am not sure but maybe try to either do moveInput before the flip conditions or move the flip conditions to Update() ins$$anonymous$$d.
Answer by Bunny83 · Jan 21, 2020 at 12:49 PM
This approach is in general bad. You track your facingRight variable just in parallel of your actual local scale setting. If they ever get out of sync (and they do) you have just a big mess. Your concrete issue is that in your second if statement when you do the "Flip" you did not check the variable if it's true but you set it to true. You have to use == for comparison and = for assignment.
That means your observations are not quite right. Whenever you move to the left you would call Flip every frame so you're flipping every physics frame as long as you move to the left. That's because if moveInput is less then 0 the first ifstatement can never be entered so you always go down to the else if. Here the first thing you do is setting facingRight to true, every time. So your first condition is always true. As I said if moveInput is negative you would call Flip. Flip just flips the scale and also flips the facingRight to false. However the next physics iteration you again set facingRight to true and Flip again.
I would highly recommend to not do such a blind "relative" flipping and also don't use several variables / states to store the same information. Either set the scale based on your facingRight variable, of just get rid of your facingRight variable and just store the scale as variable. You can simply test if the x scale is positive of negative.
There's also no reason for any of your code that you have in FixedUpdate to be in FixedUpdate. You should move all that code into Update. Also you should set your moveInput before you check it. Otherwise you always get a one frame delay.
Your jumping and moving code is also a bit strange. You completely replace the current velocity when you jump. So you loose the sideways speed for one frame.
You also have some conditions which don't make any sense. Especially your last if statement in Update. This can only be entered if your "extraJumpsValue" is 0 or 1. In the case of 1 it has no effect at all. In the case of 0 it would essentially do the only jumping possible. This is also a horrible approach. If you want to allow extra jumps you should just use a variable which holds the amount of jumps you can actually do. So when grounded you set your remainingJumps count variable to 1 + your desired extra jumps. Also you should combine your two jumping key handling.
Finally use the CompareTag method instead of the tag property. The tag property produces garbage since it has to allocate the string on the heap each time you read that property. CompareTag doesn't suffer from that since it works the other way round. The tag check is done on the native code side.
So you could highly simplify your code:
// [ ... ]
Vector3 scale;
int remainingJumps;
private void Start()
{
gm = GameObject.FindGameObjectWithTag("GM").GetComponent<GameMaster>();
transform.position = gm.lastCheckPointPos;
scale = transform.localScale;
scale.x = Mathf.Abs(scale.x);
rb = GetComponent<Rigidbody2D>();
nextSceneToLoad = SceneManager.GetActiveScene().buildIndex + 1;
}
private void Update()
{
isGrounded = Physics2D.OverlapCircle(groundCheck.position, checkRadius, whatIsGround);
moveInput = Input.GetAxis("Horizontal");
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
animator.SetFloat("Speed", Mathf.Abs(moveInput));
transform.localScale = new Vector3(scale.x * Mathf.Sign(moveInput), scale.y, scale.z);
if (isGrounded)
{
remainingJumps = 1 + extraJumpsValue;
}
animator.SetBool("IsJumping", !isGrounded);
bool jumpKey = Input.GetKeyDown(KeyCode.UpArrow);
jumpKey |= Input.GetKeyDown(KeyCode.Space);
if(jumpKey && remainingJumps > 0)
{
remainingJumps--;
rb.velocity = new Vector2(moveInput * speed, jumpForce);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.CompareTag("Danger"))
{
Scene scene = SceneManager.GetActiveScene();
SceneManager.LoadScene(scene.name);
FindObjectOfType<AudioManager>().Play("Death");
}
else if (collision.collider.CompareTag("Door"))
{
hi = true;
SceneManager.LoadScene(nextSceneToLoad);
}
}
Thank you for using your time for me. I have never got a long and amazing answer before but this is amazing. It is working now and the code is shorter than before. Thanks for all this support!
Your answer
Follow this Question
Related Questions
Why flipping triangles, not normals 1 Answer
make flipX also flip rotation 0 Answers
2D Sprite doesn't flip across pivot point. 0 Answers
SpriteRenderer FlipX too much?! 0 Answers
How can I rotate a Sprite with the mouse? Like terraria or Starbound 0 Answers