Hello,
My playable character seems to stutter every time it rotates back to normal.
Here’s a video that shows the issue(the playtest is at 0:25):
Here’s the main part of my code that I think causes the issue:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControllerDebug : MonoBehaviour
{
private bool isSpacePressed = false;
private bool isRightPressed = false;
private bool isLeftPressed = false;
private bool isUpPressed = false;
private bool grounded = false;
private bool canUsePotShot = true;
private bool jumpsAvailable = true;
private bool rotateToNormalRotation;
private bool potShotRecoiling;
private bool usePotShot;
private bool freezePosition;
private bool freezePositionNeedsAdjusting;
private int potShooterOffset = 90;
private int maxJumps = 1;
private int jumpCount = 0;
private float maxChargeTime = 0.6f;
private float chargeTime = 0;
public float potShotSpeed;
private float potShotRecoil = 0.2f;
private float normalGravityScale;
public float jumpHeight = 5;
private Vector2 recoilVelocity;
private Animator animator;
private Vector3 difference;
private Vector3 emptyVector3 = Vector3.zero;
private SpriteRenderer potSpriteRenderer;
public GameObject potShotProjectile;
private Rigidbody2D rb;
private void Start()
{
animator = GetComponent<Animator>();
potSpriteRenderer = transform.Find("Pot").gameObject.GetComponent<SpriteRenderer>();
rb = GetComponent<Rigidbody2D>();
normalGravityScale = rb.gravityScale;
}
private void Update()
{
Jump();
PotShooter();
if (rotateToNormalRotation)
{
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 0f, 0f), 5f * Time.deltaTime);
//transform.rotation = Quaternion.Euler(0f, 0f, 0f); debug to let it rotate back to normal instantly
if (transform.rotation == Quaternion.Euler(0f, 0f, 0f))
{
rotateToNormalRotation = false; ;
}
}
}
private void Jump()
{
if (Input.GetKeyDown("space") && jumpsAvailable)
{
isSpacePressed = true;
animator.Play("Wilbur_Jump", -1, 0.0f);
if (grounded == false)
{
jumpCount++;
}
}
isRightPressed = Input.GetKey("d");
isLeftPressed = Input.GetKey("a");
isUpPressed = Input.GetKey("w");
}
private void PotShooter()
{
if (Input.GetMouseButton(0) && grounded == false && canUsePotShot)
{
animator.Play("Wilbur_Pot_Shot_In");
freezePosition = true;
difference = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
float rotZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 0f, rotZ + potShooterOffset), 4f * Time.deltaTime);
potSpriteRenderer.color = new Color(1.0f, 0.63f, 0.63f);
chargeTime += Time.deltaTime;
potShotSpeed = chargeTime * 5;
if (chargeTime > maxChargeTime)
{
usePotShot = true;
}
}
if ((Input.GetMouseButtonUp(0) || usePotShot) && grounded == false && canUsePotShot)
{
animator.Play("Wilbur_Pot_Shot_Out");
Instantiate(potShotProjectile, transform.Find("Pot").position, transform.Find("Pot").rotation);
float angle = Mathf.Atan2(difference.y, difference.x);
recoilVelocity = new Vector2(-Mathf.Cos(angle) * Mathf.Rad2Deg * potShotRecoil, -Mathf.Sin(angle) * Mathf.Rad2Deg * potShotRecoil);
potShotRecoiling = true;
canUsePotShot = false;
freezePosition = false;
freezePositionNeedsAdjusting = true;
rotateToNormalRotation = true;
potSpriteRenderer.color = Color.white;
usePotShot = false;
chargeTime = 0;
}
}
private void FixedUpdate()
{
if (isSpacePressed)
{
JumpDicider();
isSpacePressed = false;
}
if (freezePosition)
{
rb.velocity = emptyVector3;
rb.gravityScale = 0;
}
else if (freezePosition == false && freezePositionNeedsAdjusting)
{
rb.gravityScale = normalGravityScale;
freezePositionNeedsAdjusting = false;
}
if (potShotRecoiling)
{
rb.velocity = recoilVelocity;
potShotRecoiling = false;
}
if (jumpCount == maxJumps)
{
jumpsAvailable = false;
}
else
{
jumpsAvailable = true;
}
}
private void JumpDicider()
{
if (isRightPressed == false && isLeftPressed == false && isUpPressed == false)
{
rb.velocity = new Vector2(rb.velocity.x, jumpHeight);
}
else if (isRightPressed && isLeftPressed == false && isUpPressed == false)
{
rb.velocity = new Vector2(jumpHeight, jumpHeight / 1.8f);
}
else if (isRightPressed == false && isLeftPressed && isUpPressed == false)
{
rb.velocity = new Vector2(-jumpHeight, jumpHeight / 1.8f);
}
else if (isRightPressed == false && isLeftPressed == false && isUpPressed)
{
rb.velocity = new Vector2(rb.velocity.x, (jumpHeight + (jumpHeight / 3)));
}
else if (isRightPressed && isLeftPressed && isUpPressed)
{
rb.velocity = new Vector2(rb.velocity.x, (jumpHeight + (jumpHeight / 3)));
}
else if (isRightPressed && isLeftPressed == false && isUpPressed)
{
rb.velocity = new Vector2(jumpHeight / 1.8f, (jumpHeight + (jumpHeight / 3) / 1.8f));
}
else if (isRightPressed == false && isLeftPressed && isUpPressed)
{
rb.velocity = new Vector2(-jumpHeight / 1.8f, (jumpHeight + (jumpHeight / 3) / 1.8f));
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.CompareTag("World"))
{
grounded = true;
canUsePotShot = true;
jumpCount = 0;
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.gameObject.CompareTag("World"))
{
grounded = false;
}
}
}
The weird thing is that it only happens when it tries to rotate back to normal and not when it is rotating towards my mouse. I’ve tried to rotate it back to normal instantly(line 50 on the shorter version, line 86 on the longer one) and it is not having any issues if I do that, but I’m really trying to make the transition look smooth.
There are a couple of variables that are used in other scripts, so not every variable in this script is used in this script.
Does anyone know what’s causing the stutter and/or how to fix it? I would really appreciate any kind of help.
I know the script is pretty long to be asking a question about it, but I am not experienced enough with coding to know what people need to be able to answer my question. Also I am sorry if I made any grammer/spelling errors or if anything isn’t proper, English is not my main language.
Here’s the full script just in case it’s necessary:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private bool isSpacePressed = false;
private bool isRightPressed = false;
private bool isLeftPressed = false;
private bool isUpPressed = false;
private bool isDownPressed = false;
private bool canFastfall = false;
private bool headbutting = false;
private bool directionLock = false;
private bool canUsePotShot = true;
private bool usePotShot = false;
private bool jumpsAvailable = true;
private bool grounded = false;
private bool facingLeft = false;
private bool facingRight = true;
private bool rotateToNormalRotation = false;
private bool shouldAnimationReset = true;
private bool potShotRecoiling = false;
private bool freezePosition;
private bool freezePositionNeedsAdjusting;
private int jumpCount = 0;
private int maxJumps = 2;
public int health = 3;
public float jumpHeight = 5;
private float fastfallSpeed = 2f;
private float knockback;
private float stunTime;
private float potShooterOffset = 90;
private float maxChargeTime = 0.6f;
private float chargeTime = 0;
private float potShotRecoil = 0.2f;
public float potShotSpeed;
private float normalGravityScale;
private Vector2 recoilVelocity;
private Vector3 emptyVector3 = Vector3.zero;
private Vector3 difference;
private Rigidbody2D rb;
private Animator animator;
private PlayerController playerController;
private GameObject[] bodyparts;
private SpriteRenderer[] srBodyparts;
private BoxCollider2D boxCollider2D;
private EffectsScript effectsScript;
public GameObject potShotProjectile;
private SpriteRenderer potSpriteRenderer;
void Start()
{
rb = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
playerController = GetComponent<PlayerController>();
effectsScript = GameObject.FindGameObjectWithTag("Effects").GetComponent<EffectsScript>();
bodyparts = GameObject.FindGameObjectsWithTag("Player Bodypart");
potSpriteRenderer = transform.Find("Pot").gameObject.GetComponent<SpriteRenderer>();
srBodyparts = new SpriteRenderer[bodyparts.Length];
for(int i = 0; i < bodyparts.Length; i++)
{
srBodyparts[i] = bodyparts[i].GetComponent<SpriteRenderer>();
}
rb.interpolation = RigidbodyInterpolation2D.Interpolate;
maxJumps--;
boxCollider2D = gameObject.GetComponent<BoxCollider2D>();
normalGravityScale = rb.gravityScale;
//Application.targetFrameRate = 60;
}
private void Update()
{
Jump();
PotShooter();
Headbutt();
Fastfall();
DirectionAdjuster();
if(animator.GetCurrentAnimatorStateInfo(0).IsName("Wilbur_Idle") == false && shouldAnimationReset)
{
StartCoroutine(AnimationResetter());
}
if (rotateToNormalRotation)
{
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 0f, 0f), 5f * Time.deltaTime);
//transform.rotation = Quaternion.Euler(0f, 0f, 0f);
if(transform.rotation == Quaternion.Euler(0f, 0f, 0f))
{
rotateToNormalRotation = false; ;
}
}
}
private void Jump()
{
if (Input.GetKeyDown("space") && jumpsAvailable)
{
isSpacePressed = true;
animator.Play("Wilbur_Jump", -1, 0.0f);
if (grounded == false)
{
jumpCount++;
}
}
isRightPressed = Input.GetKey("d");
isLeftPressed = Input.GetKey("a");
isUpPressed = Input.GetKey("w");
}
private void PotShooter()
{
if (Input.GetMouseButton(0) && grounded == false && canUsePotShot)
{
animator.Play("Wilbur_Pot_Shot_In");
freezePosition = true;
difference = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
float rotZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 0f, rotZ + potShooterOffset), 4f * Time.deltaTime);
potSpriteRenderer.color = new Color(1.0f, 0.63f, 0.63f);
chargeTime += Time.deltaTime;
potShotSpeed = chargeTime * 5;
if(chargeTime > maxChargeTime)
{
usePotShot = true;
}
directionLock = true;
}
if((Input.GetMouseButtonUp(0) || usePotShot) && grounded == false && canUsePotShot)
{
animator.Play("Wilbur_Pot_Shot_Out");
Instantiate(potShotProjectile, transform.Find("Pot").position, transform.Find("Pot").rotation);
float angle = Mathf.Atan2(difference.y, difference.x);
recoilVelocity = new Vector2(-Mathf.Cos(angle) * Mathf.Rad2Deg * potShotRecoil, -Mathf.Sin(angle) * Mathf.Rad2Deg * potShotRecoil);
potShotRecoiling = true;
canUsePotShot = false;
freezePosition = false;
freezePositionNeedsAdjusting = true;
rotateToNormalRotation = true;
potSpriteRenderer.color = Color.white;
usePotShot = false;
chargeTime = 0;
directionLock = false;
}
}
private void Headbutt()
{
if (Input.GetMouseButtonDown(0) && grounded && headbutting == false)
{
StartCoroutine(HeadbuttRoutine());
}
}
private void Fastfall()
{
isDownPressed = Input.GetKeyDown("s");
if (isDownPressed && grounded == false && canFastfall && rb.velocity.y > -fastfallSpeed)
{
rb.velocity = new Vector2(rb.velocity.x, -fastfallSpeed);
canFastfall = false;
}
}
private void DirectionAdjuster()
{
if (isLeftPressed && directionLock == false)
{
facingLeft = true;
}
if (isRightPressed && directionLock == false)
{
facingRight = true;
}
if (facingLeft)
{
transform.localScale = new Vector2(-Mathf.Abs(transform.localScale.x), transform.localScale.y);
for(int i = 0; i < effectsScript.isFlipped.Length; i++)
{
effectsScript.isFlipped[i] = true;
}
boxCollider2D.offset = new Vector2(Mathf.Abs(boxCollider2D.offset.x), boxCollider2D.offset.y);
facingLeft = false;
}
if (facingRight)
{
transform.localScale = new Vector2(Mathf.Abs(transform.localScale.x), transform.localScale.y);
for (int i = 0; i < effectsScript.isFlipped.Length; i++)
{
effectsScript.isFlipped[i] = false;
}
boxCollider2D.offset = new Vector2(-Mathf.Abs(boxCollider2D.offset.x), boxCollider2D.offset.y);
facingRight = false;
}
}
void FixedUpdate()
{
if (isSpacePressed)
{
JumpDicider();
isSpacePressed = false;
}
if (freezePosition)
{
rb.velocity = emptyVector3;
rb.gravityScale = 0;
}
else if(freezePosition == false && freezePositionNeedsAdjusting)
{
rb.gravityScale = normalGravityScale;
freezePositionNeedsAdjusting = false;
}
if (potShotRecoiling)
{
rb.velocity = recoilVelocity;
potShotRecoiling = false;
}
if (jumpCount == maxJumps)
{
jumpsAvailable = false;
}
else
{
jumpsAvailable = true;
}
}
private void JumpDicider()
{
if (isRightPressed == false && isLeftPressed == false && isUpPressed == false)
{
rb.velocity = new Vector2(rb.velocity.x, jumpHeight);
}
else if (isRightPressed && isLeftPressed == false && isUpPressed == false)
{
rb.velocity = new Vector2(jumpHeight, jumpHeight / 1.8f);
}
else if (isRightPressed == false && isLeftPressed && isUpPressed == false)
{
rb.velocity = new Vector2(-jumpHeight, jumpHeight / 1.8f);
}
else if (isRightPressed == false && isLeftPressed == false && isUpPressed)
{
rb.velocity = new Vector2(rb.velocity.x, (jumpHeight + (jumpHeight / 3)));
}
else if (isRightPressed && isLeftPressed && isUpPressed)
{
rb.velocity = new Vector2(rb.velocity.x, (jumpHeight + (jumpHeight / 3)));
}
else if (isRightPressed && isLeftPressed == false && isUpPressed)
{
rb.velocity = new Vector2(jumpHeight / 1.8f, (jumpHeight + (jumpHeight / 3) / 1.8f));
}
else if (isRightPressed == false && isLeftPressed && isUpPressed)
{
rb.velocity = new Vector2(-jumpHeight / 1.8f, (jumpHeight + (jumpHeight / 3) / 1.8f));
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.CompareTag("World"))
{
grounded = true;
if(transform.rotation != Quaternion.Euler(0f, 0f, 0f))
{
transform.rotation = Quaternion.Euler(0f, 0f, 0f);
}
canUsePotShot = true;
rb.velocity = new Vector2(0, rb.velocity.y);
jumpCount = 0;
effectsScript.spawn[0] = true;
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.gameObject.CompareTag("World"))
{
grounded = false;
canFastfall = true;
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Enemy"))
{
health -= collision.gameObject.GetComponent<EnemyScript>().damage;
knockback = collision.gameObject.GetComponent<EnemyScript>().knockback;
stunTime = Mathf.Abs(knockback / 20);
StartCoroutine(Knockback());
}
}
IEnumerator Knockback()
{
rb.velocity = new Vector2(knockback, Mathf.Abs(knockback / 2));
playerController.enabled = false;
for(int i = 0; i < srBodyparts.Length; i++)
{
srBodyparts[i].color = new Color(0.97f, 0.49f, 0.49f, 1);
}
yield return new WaitForSeconds(stunTime);
for (int i = 0; i < srBodyparts.Length; i++)
{
srBodyparts[i].color = Color.white;
}
playerController.enabled = true;
}
IEnumerator HeadbuttRoutine()
{
headbutting = true;
directionLock = true;
animator.Play("Wilbur_Headbutt");
yield return new WaitForSeconds(7 / 60f);
effectsScript.spawn[1] = true;
yield return new WaitForSeconds(14 / 60f);
directionLock = false;
headbutting = false;
}
IEnumerator AnimationResetter()
{
shouldAnimationReset = false;
float currentAnimation = animator.GetCurrentAnimatorStateInfo(0).fullPathHash;
float animationTime = animator.GetCurrentAnimatorStateInfo(0).length;
yield return new WaitForSeconds(animationTime);
if(currentAnimation == animator.GetCurrentAnimatorStateInfo(0).fullPathHash) animator.Play("Wilbur_Idle");
shouldAnimationReset = true;
}
}