[2D] Rotation flips back to the right side for 1 frame after rotation
To briefly explain my issue, I have a 2D character who can shoot arrows from his bow. The aiming (rotation) starts when the left click is held down, and ends when it is let go. When it is let go, if the character is facing the right side, it smoothly returns to it's idle animation. But when it is facing the left side, for ONE frame, the arms and bow will flip to the right side. To better demonstrate the issue, here is a video clip of it.
Here's some of the code that's probably related to the issue:
Bow class:
Rotation:
void RotateBow(Vector3 firstPos, Vector3 secondPos) {
Vector3 difference = firstPos - secondPos;
// Sets the rotation of the very first click/hold (not dragging) to look at the initial position
if (firstPos.Equals(secondPos)) {
difference = firstPos - player.transform.position;
}
// Rotate Bow \\
// Calculates the angle
float angle = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
// sets the initial rotation
pivot.localRotation = Quaternion.AngleAxis(angle, Vector3.forward);
// uses ^ to check if the player is looking right or left
bool isLookingRight = RotatePlayer();
// fixes the inverted controls once player is flipped
angle = (isLookingRight) ? angle : -angle;
// sets the final rotation
pivot.localRotation = Quaternion.AngleAxis(angle, Vector3.forward);
// Rotate Arm \\
if (playerBowHoldShoulder != null) {
playerBowHoldShoulder.localRotation = Quaternion.AngleAxis(angle - 5.78f, Vector3.forward);
playerBowDrawShoulder.localRotation = Quaternion.AngleAxis(angle, Vector3.forward);
}
}
Player Flipping:
/**
* Rotates the player depending on the bow aim direction
* Returns true when looking right, else returns false
*/
bool RotatePlayer() {
if (player != null) {
// Checks if the bow's position is to the right or to the left of the player.
float difference = transform.position.x - player.transform.position.x;
if (difference >= 0) {
player.LookRight();
return true;
} else {
player.LookLeft();
return false;
}
}
return true;
}
Shooting (called when mouse up):
void ShootArrow() {
// Instantiate the arrow and store reference into an object
GameObject shotArrow = Instantiate(arrow, transform.position, transform.rotation);
// Set the shooter so they don't kill themselves
shotArrow.GetComponent<Arrow>().SetShooter(playerObj);
// Apply force to the shot arrow
Rigidbody2D rb = shotArrow.GetComponent<Rigidbody2D>();
Vector3 dir = GetAimDirection();
rb.AddForce(dir * GetCurrentForce(dir.magnitude), ForceMode2D.Impulse);
// Reset Bow Draw Visual thing
bowAnimator.SetFloat("Blend", 0f);
// Reset player arm rotation
if (player != null) {
player.ResetArms();
}
}
Player class:
Functions being called from the Bow object:
public void LookLeft() {
Look(180f);
}
public void LookRight() {
Look(0.0f);
}
private void Look(float angle) {
// Flippy
transform.rotation = Quaternion.AngleAxis(angle, Vector3.up);
// To flip the arm and bow
if (isDrawing) {
shouldersPivot.eulerAngles = new Vector3(angle, 0f, 0f);
}
}
// Resets the shouldersPivot to it's original rotation
public void ResetArms() {
shouldersPivot.eulerAngles = transform.eulerAngles;
}
And the hierarchy of the player game object in the scene:
Other notes:
If I disable the animator and the ResetArms() function, it doesn't do that annoying flip.
With everything enabled again, when aiming on the left side, the rotation flips to the right and then back to the left, but very quickly. Disabling the ResetArms() fixes this, but then look at this.
Maybe it has something to do with the animator? But none of my animations are modifying the rotation and position of the shoulders_pivot, which is what I am flipping.
Any help or ideas would be appreciated, thanks!
EDIT: I disabled the ResetArms() function, and instead created another animation that holds it on the left side. The image below is the affected body parts. The arms still flip, but now it blends smoothly from the right side to the left. You can see in this gif here. Just note that I changed the game speed to 0.25 just for debugging reasons. Still have the issue but this seems like a step closer.