Search code examples
c#unity-game-engineanimationvector

Unity - Calculate movement vector relative to aim in order to make strafe animations


I am making 3D top down shooter in Unity and I am facing a problem. Camera is fixed and is not rotating, so when you press left button it will rotate the player and move forwards to left. It is working well, but problem is when player is aiming. In my game player has ability to aim while holding right mouse button. I want to make strafe animations while aiming. I have created this blend tree in animator:

Blend tree

I have two parameters there: AimingWalkHorizontal and AimingWalkVertical. When the values are [1,0] it will play strafe right animation.

I have two Vectors. One for movement and one for aiming:

Vector3 movementVector = new Vector3(_movementVector.x, 0, _movementVector.y);
Vector3 aimingDirection = new Vector3((MouseWorldPosition - PlayerController.PlayerObj.transform.position).x, 0, (MouseWorldPosition - PlayerController.PlayerObj.transform.position).z);

And I want to achieve this:

enter image description here

How can I get this relative movement Vector in order to feed it to animator?

PlayerController.Animator.SetFloat("AimingWalkHorizontal", /* ??? */);
PlayerController.Animator.SetFloat("AimingWalkVertical", /* ??? */);

Thank you


Solution

  • I have finally solved it by calculating clockwise angle between movement and aim vector. Than I am converting angle to normalized vector that is pushed to animator.

    Vector3 movementVector = new Vector3(_movementVector.x, 0, _movementVector.y).normalized;
    Vector3 aimingDirection = new Vector3((MouseWorldPosition - PlayerController.PlayerObj.transform.position).x, 0, (MouseWorldPosition - PlayerController.PlayerObj.transform.position).z).normalized;
    
    // Calculate clockwise angle between movement and aiming direction
    float dotProduct = Vector3.Dot(movementVector, aimingDirection);
    float crossProductMagnitude = Vector3.Cross(movementVector, aimingDirection).y;
    float clockwiseAngle = Mathf.Atan2(crossProductMagnitude, dotProduct) * Mathf.Rad2Deg;
    
    // In my game I have ability to rotate camera with middle mouse button, so I have to decrease angle by camera rotation
    // If you have fixed camera rotation do not use this line
    clockwiseAngle -= CameraController.Instance.CameraObj.transform.eulerAngles.y;
    
    // Adjust the angle to be positive (0 to 360 degrees)
    clockwiseAngle = (clockwiseAngle + 360) % 360;
    
    // Convert angle to normalized vector
    
    // Convert to radians
    float radians = clockwiseAngle * Mathf.Deg2Rad;
    
    // Calculate vector axis
    float x = Mathf.Cos(radians);
    float z = Mathf.Sin(radians);
    
    // Create normalized vector
    Vector3 relativeMovement = new Vector3(x, 0f, z).normalized;
    
    // Set values to animator
    PlayerController.Animator.SetFloat("AimingWalkHorizontal", relativeMovement.z * -1f);
    PlayerController.Animator.SetFloat("AimingWalkVertical", relativeMovement.x);