2
\$\begingroup\$

I am developing a top down twin stick shooter. I am running into a issue where if I change my character's rotation, the Unity Blend Tree animation does not play the correct animation that corresponds to that relative rotation. For example if my Character is facing north and I walk forward, the animation plays fine, but if I rotate my character 180 degrees (facing south), when I walk forward it will play the backwards animation.

https://media.giphy.com/media/cmx1aOm0UOjCed8MJT/giphy.gif

I believe this is because I am just sending the inputs from the analog stick, and not offsetting the values based on the rotation of the character. I am using 2 floats (horizontal and vertical) to control the blend tree. How can I offset the float values from the input based on the character's local rotation? Current code below,

 void Update()
{
    if (!ReInput.isReady) return; // Exit if Rewired isn't ready. This would only happen during a script recompile in the editor.
    if (player == null) return;
    GetInput();
    Move();
    Look();

}

private void GetInput()
{
    // Get the input from the Rewired Player. All controllers that the Player owns will contribute, so it doesn't matter
    // whether the input is coming from a joystick, the keyboard, mouse, or a custom controller.

    mhorizontal = player.GetAxis("Move Horizontal"); // get input by name or action id
    mvertical = player.GetAxis("Move Vertical");


    lHorizontal = player.GetAxis("Look Horizontal");
    lVertical = player.GetAxis("Look Vertical");
    //fire = player.GetButtonDown("Fire");
}

void Move()
{

    if (mhorizontal != 0 && mvertical != 0)
    {
        Vector3 rightMovement = right * moveSpeed * Time.deltaTime * mhorizontal;
        Vector3 upMovement = forward * moveSpeed * Time.deltaTime * mvertical;
        //Vector3 heading = Vector3.Normalize(rightMovement + upMovement);

        // transform.forward = heading;
        transform.position += rightMovement;
        transform.position += upMovement; animator.SetFloat("Vertical", mvertical, 0.1f, Time.deltaTime);
        animator.SetFloat("Horizontal", mhorizontal, 0.1f, Time.deltaTime);
    }

}

void Look()
{
    if (lVertical != 0 && lHorizontal != 0)
    {
        float cameraFacing = Camera.main.transform.eulerAngles.y;
        Vector3 inputVector = new Vector3(lHorizontal, 0, lVertical);
        Vector3 turnedInputVector = Quaternion.Euler(0, cameraFacing, 0) * inputVector;
        transform.LookAt(turnedInputVector + transform.position);


    }

}
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

Ok, I found a pretty simple solution. I just needed to rotate/offset the X,Y input with the X/Y values from the player's and Camera's Y rotation. Below is my solution:

    void Move()
{

    if (mhorizontal != 0 && mvertical != 0)
    {
        Vector3 rightMovement = right * moveSpeed * Time.deltaTime * mhorizontal;
        Vector3 upMovement = forward * moveSpeed * Time.deltaTime * mvertical;
        //Vector3 heading = Vector3.Normalize(rightMovement + upMovement);

        // transform.forward = heading;
        transform.position += rightMovement;
        transform.position += upMovement;

    }

    Direction.x = mhorizontal;
    Direction.y = mvertical;
    Direction = Rotate(Direction, transform.rotation.eulerAngles.y);
    //Direction =Quaternion.AngleAxis(-45, Vector3.up) * Direction;
    print("Direction is: " + Direction);
  //  Direction = Quaternion.Euler(0, transform.rotation.eulerAngles.y , 0) * Direction;

    animator.SetFloat("Vertical", Direction.y, animationDamp, Time.deltaTime);
    animator.SetFloat("Horizontal", Direction.x, animationDamp, Time.deltaTime);
}

public Vector2 Rotate(Vector2 v, float degrees)
{
    return Quaternion.Euler(0, 0, (degrees + -Camera.main.transform.rotation.eulerAngles.y)) * v;

}
\$\endgroup\$
0
\$\begingroup\$
var x = Input.GetAxisRaw("Horizontal");
var z = Input.GetAxisRaw("Vertical");
moveDir = new Vector3(x, 0, z).normalized;
Vector3 animationVector = transform.InverseTransformVector(moveDir);
anim.SetFloat("moveX", animationVector.x);
anim.SetFloat("moveZ", animationVector.z);
\$\endgroup\$
1
  • 2
    \$\begingroup\$ This answer would be clearer with some text explaining how these lines of code solve the problem. \$\endgroup\$
    – DMGregory
    Jul 14, 2022 at 1:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .