Home > OS >  How can I refactor my 2d unity movement script to resolve the behavioral issues I have?
How can I refactor my 2d unity movement script to resolve the behavioral issues I have?

Time:02-16

Below is the code I've written for my 2D movement:

void HandleInput()
{
    float verticalMoveAmount = Input.GetAxis("Vertical") * playerSpeed * Time.deltaTime;
    float horizontalMoveAmount = Input.GetAxis("Horizontal") * playerSpeed * Time.deltaTime;

    if (facingRight)
    {
        transform.Translate(horizontalMoveAmount, verticalMoveAmount, 0);
    }
    else
    {
        transform.Translate(-horizontalMoveAmount, verticalMoveAmount, 0);
    }

    if (horizontalMoveAmount > 0 && !facingRight)
    {
        Flip();
    }
    else if (horizontalMoveAmount < 0 && facingRight)
    {
        Flip();
    }

    if (Input.GetKeyDown(KeyCode.Space) && hasBall)
    {
        Shoot();
    }   
}

void Flip()
{
    facingRight = !facingRight;
    transform.Rotate(0f, 180f, 0f);
}

I have the below problems though:

  1. I have a Cinemachine virtual camera following the player around. However, whenever the player changes direction they vanish from the camera view. I think this is something to do with the Flip(), but I don't know why or how to fix it.
  2. The if statement for if facingRight where I have to use negative movement on the horizontal axis, this feels like a really poor way to handle it, but if I don't do that I can't move left when the player changes directions to the left. Is there a better way I can do this?

Thank you in advance.

CodePudding user response:

To 1) my guess is that since you rotate the object by 180° you are looking at the backface of it -> it is not being rendered due to backface culling.

To 2) since you rotate the object by 180° it's local coordinate system is now pointing in the other direction. Note that by default Transform.Translate works in the local coordinate system. If you want to rather use global axes then simply pass in

transform.Translate(horizontalMoveAmount, verticalMoveAmount, 0, Space.World);

In general simply assuming you are using a SpriteRenderer which is the most common thing for 2D games you should rather use the property SpriteRenderer.flipX and not rotate your object at all. This would solve both issues at the same time


So together your code could be simply

public SpriteRenderer spriteRenderer;

void HandleInput()
{
    var input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
    // ensure that diagonal movement isn't faster
    input = Vector2.ClampMagnitude(input, 1f);

    var movement = input * playerSpeed * Time.deltaTime;

    transform.Translate(movement, Space.World);
    // basically the same now as
    //transform.position  = movement;
    
    if (input.x != 0)
    {
        spriteRenderer.flipX = input.x < 0;
    }

    if (hasBall && Input.GetKeyDown(KeyCode.Space))
    {
        Shoot();
    }   
}
  • Related