Flipping a 2D Sprite Animation in Unity 2D
Asked Answered
S

6

15

I've got a quick question regarding 2D Sprite animations that I haven't been able to find specifically answered anywhere:

I have a sprite with walk animations to the right. However, I obviously want to flip the animation to the left when he walks left (2D side-scroller).

I can easily flip the sprite itself, using transform.localscale.x, however, that only flips the sprite. Not the animation clip. (This no longer happens in Unity)

So, while the sprite flips, the minute the animation clip begins playing, it flips back right (as the only animation clip I have is for the right facing sprite).

Is the only way to do this to flip the sprites in Photoshop, or is there a way to do it in Unity?

Thanks!

UPDATE: With the actual versions of unity if you scale the transform by multiplying it by -1, the animation frames are also scaled.

Stiffler answered 26/10, 2014 at 0:10 Comment(0)
S
16

I finally figured it out by doing this:

void Flip()
{
    // Switch the way the player is labelled as facing
    facingRight = !facingRight;

    // Multiply the player's x local scale by -1
    Vector3 theScale = transform.localScale;
    theScale.x *= -1;
    transform.localScale = theScale;
}

This is from Unity's 2D Platformer example.

To implement some sort of checking which makes use of the Flip method, you can do something similar to the below example which is basic movement code. facingRight is set as a value on the class so that the other methods can use it, and it is defaulted to false.

void Update() 
{

    //On X axis: -1f is left, 1f is right

    //Player Movement. Check for horizontal movement
    if (Input.GetAxisRaw ("Horizontal") > 0.5f || Input.GetAxisRaw("Horizontal") < -0.5f) 
    {
        transform.Translate (new Vector3 (Input.GetAxisRaw ("Horizontal") * moveSpeed * Time.deltaTime, 0f, 0f));
        if (Input.GetAxisRaw ("Horizontal") > 0.5f && !facingRight) 
        {
            //If we're moving right but not facing right, flip the sprite and set     facingRight to true.
            Flip ();
            facingRight = true;
        } else if (Input.GetAxisRaw("Horizontal") < 0.5f && facingRight) 
        {
            //If we're moving left but not facing left, flip the sprite and set facingRight to false.
            Flip ();
            facingRight = false;
        }

    //If we're not moving horizontally, check for vertical movement. The "else if" stops diagonal movement. Change to "if" to allow diagonal movement.
    } else if (Input.GetAxisRaw ("Vertical") > 0.5f || Input.GetAxisRaw("Vertical") < -0.5f) 
    {
        transform.Translate (new Vector3 (0f, Input.GetAxisRaw ("Vertical") * moveSpeed * Time.deltaTime, 0f));
    }

    //Variables for the animator to use as params
    anim.SetFloat ("MoveX", Input.GetAxisRaw ("Horizontal"));
    anim.SetFloat ("MoveY", Input.GetAxisRaw ("Vertical"));

}
Stiffler answered 26/10, 2014 at 19:42 Comment(4)
I've edited in a late addition to this very helpful answer which I've implemented, which is to do a check when the key is pressed to determine which if the sprite needs to be flipped or not.Prouty
@Prouty - the change is so large, you probably should make that another answer.Cabotage
@Cabotage should I? I was really only building on Jestus' answer by providing a bit of basic code to show how the method can be implemented. If you still say so, then I'll revert the edit and post my own answer.Prouty
@Prouty - well, the edit got approved, so it's really your choice a this point.Cabotage
H
3
void FlipHorizontal()
{
    animator.transform.Rotate(0, 180, 0);
}

You could also do that on transform itself (without animator). But in that case rotation value can be overriden by animator

Howie answered 15/9, 2015 at 20:51 Comment(2)
I think the syntax is animator.transform.Rotate(new Vector3(0, 180, 0));Dirndl
transform.Rotate supports method overrode. So you can use both of params contains Rotate(float xAngle, float yAngle, float zAngle, Space relativeTo = Space.Self); and Rotate(Vector3 eulers, Space relativeTo = Space.Self); Check docs.unity3d.com/ScriptReference/Transform.Rotate.htmlDraggletailed
K
0

This is how I did it - almost the same as the other technique by Jestus with unity script.

var facing : String = "right";

function updateFacing(curr : String){
    if(curr != facing){
        facing = curr;
        var theScale : Vector3 = gameObject.transform.localScale;
        theScale.x *= -1;
        gameObject.transform.localScale = theScale;
    }
}

//put to use
function controls(){
    if(Input.GetKey (KeyCode.LeftArrow)){
        updateFacing("left");
    } else if(Input.GetKey (KeyCode.RightArrow)){
        updateFacing("right");
    }      
}
Koodoo answered 1/2, 2016 at 3:57 Comment(0)
V
0

If you're animating in Unity:

  1. Copy all frames (sprites) of the animation that you want to flip over.
  2. Paste those frames into your new animation and select everything on the first frame.
  3. Change the x scale of the first frame from 1 to -1.
  4. Do the same thing with the very last frame of your animation.

Now it should play facing the other direction!

Valaree answered 6/2, 2016 at 19:11 Comment(2)
Courtesy of EduLopez's suggested edit (which should have been posted as comment or alt ans): "You can also have one animation walking to the left and have a function just to face your sprite. Depending if isFscingRight == true, the x scale would be 1 or -1)"Humes
Its a good answer too. Its another way to do this in the animation gui view. Should'nt be a negative answer....Louth
M
0

This is my C# implementation. It uses a string as the direction facing to make it a little easier to debug.

public string facing = "right";
public string previousFacing;

private void Awake()
{
    previousFacing = facing;
}

void Update()
{
    // store movement from horizontal axis of controller
    Vector2 move = Vector2.zero;
    move.x = Input.GetAxis("Horizontal");
    // call function
    DetermineFacing(move);
}
// determine direction of character
void DetermineFacing(Vector2 move)
{
    if (move.x < -0.01f)
    {
        facing = "left";
    }
    else if (move.x > 0.01f)
    {
        facing = "right";
    }
    // if there is a change in direction
    if (previousFacing != facing)
    {
        // update direction
        previousFacing = facing;
        // change transform
        gameObject.transform.Rotate(0, 180, 0);
    }
}
Mccurdy answered 20/12, 2018 at 3:57 Comment(0)
N
0

if needed change horizontal > 0

Animator anim;
SpriteRenderer sr;
bool lastFlip;

horizontal = Input.GetAxis("Horizontal");
anim.SetFloat("Move_X", horizontal);
if(horizontal==0){
    sr.flipX = lastFlip;
}else{
    sr.flipX = horizontal < 0;
    lastFlip = sr.flipX;
}
Nobell answered 23/11, 2023 at 13:18 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Proceeding

© 2022 - 2024 — McMap. All rights reserved.