Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Resolved Rotation causes stuttery behavoir

Discussion in 'Scripting' started by Slurgelman, Aug 25, 2022.

  1. Slurgelman

    Slurgelman

    Joined:
    Aug 25, 2022
    Posts:
    7
    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:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PlayerControllerDebug : MonoBehaviour
    6. {
    7.     private bool isSpacePressed = false;
    8.     private bool isRightPressed = false;
    9.     private bool isLeftPressed = false;
    10.     private bool isUpPressed = false;
    11.     private bool grounded = false;
    12.     private bool canUsePotShot = true;
    13.     private bool jumpsAvailable = true;
    14.     private bool rotateToNormalRotation;
    15.     private bool potShotRecoiling;
    16.     private bool usePotShot;
    17.     private bool freezePosition;
    18.     private bool freezePositionNeedsAdjusting;
    19.     private int potShooterOffset = 90;
    20.     private int maxJumps = 1;
    21.     private int jumpCount = 0;
    22.     private float maxChargeTime = 0.6f;
    23.     private float chargeTime = 0;
    24.     public float potShotSpeed;
    25.     private float potShotRecoil = 0.2f;
    26.     private float normalGravityScale;
    27.     public float jumpHeight = 5;
    28.     private Vector2 recoilVelocity;
    29.     private Animator animator;
    30.     private Vector3 difference;
    31.     private Vector3 emptyVector3 = Vector3.zero;
    32.     private SpriteRenderer potSpriteRenderer;
    33.     public GameObject potShotProjectile;
    34.     private Rigidbody2D rb;
    35.  
    36.     private void Start()
    37.     {
    38.         animator = GetComponent<Animator>();
    39.         potSpriteRenderer = transform.Find("Pot").gameObject.GetComponent<SpriteRenderer>();
    40.         rb = GetComponent<Rigidbody2D>();
    41.         normalGravityScale = rb.gravityScale;
    42.     }
    43.     private void Update()
    44.     {
    45.         Jump();
    46.         PotShooter();
    47.         if (rotateToNormalRotation)
    48.         {
    49.             transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 0f, 0f), 5f * Time.deltaTime);
    50.             //transform.rotation = Quaternion.Euler(0f, 0f, 0f);     debug to let it rotate back to normal instantly
    51.             if (transform.rotation == Quaternion.Euler(0f, 0f, 0f))
    52.             {
    53.                 rotateToNormalRotation = false; ;
    54.             }
    55.         }
    56.     }
    57.     private void Jump()
    58.     {
    59.         if (Input.GetKeyDown("space") && jumpsAvailable)
    60.         {
    61.             isSpacePressed = true;
    62.             animator.Play("Wilbur_Jump", -1, 0.0f);
    63.             if (grounded == false)
    64.             {
    65.                 jumpCount++;
    66.             }
    67.         }
    68.         isRightPressed = Input.GetKey("d");
    69.         isLeftPressed = Input.GetKey("a");
    70.         isUpPressed = Input.GetKey("w");
    71.     }
    72.     private void PotShooter()
    73.     {
    74.         if (Input.GetMouseButton(0) && grounded == false && canUsePotShot)
    75.         {
    76.             animator.Play("Wilbur_Pot_Shot_In");
    77.             freezePosition = true;
    78.             difference = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
    79.             float rotZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
    80.             transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 0f, rotZ + potShooterOffset), 4f * Time.deltaTime);
    81.             potSpriteRenderer.color = new Color(1.0f, 0.63f, 0.63f);
    82.             chargeTime += Time.deltaTime;
    83.             potShotSpeed = chargeTime * 5;
    84.             if (chargeTime > maxChargeTime)
    85.             {
    86.                 usePotShot = true;
    87.             }
    88.         }
    89.         if ((Input.GetMouseButtonUp(0) || usePotShot) && grounded == false && canUsePotShot)
    90.         {
    91.             animator.Play("Wilbur_Pot_Shot_Out");
    92.             Instantiate(potShotProjectile, transform.Find("Pot").position, transform.Find("Pot").rotation);
    93.             float angle = Mathf.Atan2(difference.y, difference.x);
    94.             recoilVelocity = new Vector2(-Mathf.Cos(angle) * Mathf.Rad2Deg * potShotRecoil, -Mathf.Sin(angle) * Mathf.Rad2Deg * potShotRecoil);
    95.             potShotRecoiling = true;
    96.             canUsePotShot = false;
    97.             freezePosition = false;
    98.             freezePositionNeedsAdjusting = true;
    99.             rotateToNormalRotation = true;
    100.             potSpriteRenderer.color = Color.white;
    101.             usePotShot = false;
    102.             chargeTime = 0;
    103.         }
    104.     }
    105.     private void FixedUpdate()
    106.     {
    107.         if (isSpacePressed)
    108.         {
    109.             JumpDicider();
    110.             isSpacePressed = false;
    111.         }
    112.  
    113.         if (freezePosition)
    114.         {
    115.             rb.velocity = emptyVector3;
    116.             rb.gravityScale = 0;
    117.         }
    118.         else if (freezePosition == false && freezePositionNeedsAdjusting)
    119.         {
    120.             rb.gravityScale = normalGravityScale;
    121.             freezePositionNeedsAdjusting = false;
    122.         }
    123.  
    124.         if (potShotRecoiling)
    125.         {
    126.             rb.velocity = recoilVelocity;
    127.             potShotRecoiling = false;
    128.         }
    129.  
    130.         if (jumpCount == maxJumps)
    131.         {
    132.             jumpsAvailable = false;
    133.         }
    134.         else
    135.         {
    136.             jumpsAvailable = true;
    137.         }
    138.     }
    139.     private void JumpDicider()
    140.     {
    141.         if (isRightPressed == false && isLeftPressed == false && isUpPressed == false)
    142.         {
    143.             rb.velocity = new Vector2(rb.velocity.x, jumpHeight);
    144.         }
    145.         else if (isRightPressed && isLeftPressed == false && isUpPressed == false)
    146.         {
    147.             rb.velocity = new Vector2(jumpHeight, jumpHeight / 1.8f);
    148.         }
    149.         else if (isRightPressed == false && isLeftPressed && isUpPressed == false)
    150.         {
    151.             rb.velocity = new Vector2(-jumpHeight, jumpHeight / 1.8f);
    152.         }
    153.         else if (isRightPressed == false && isLeftPressed == false && isUpPressed)
    154.         {
    155.             rb.velocity = new Vector2(rb.velocity.x, (jumpHeight + (jumpHeight / 3)));
    156.         }
    157.         else if (isRightPressed && isLeftPressed && isUpPressed)
    158.         {
    159.             rb.velocity = new Vector2(rb.velocity.x, (jumpHeight + (jumpHeight / 3)));
    160.         }
    161.         else if (isRightPressed && isLeftPressed == false && isUpPressed)
    162.         {
    163.             rb.velocity = new Vector2(jumpHeight / 1.8f, (jumpHeight + (jumpHeight / 3) / 1.8f));
    164.         }
    165.         else if (isRightPressed == false && isLeftPressed && isUpPressed)
    166.         {
    167.             rb.velocity = new Vector2(-jumpHeight / 1.8f, (jumpHeight + (jumpHeight / 3) / 1.8f));
    168.         }
    169.     }
    170.     private void OnTriggerEnter2D(Collider2D collision)
    171.     {
    172.         if (collision.gameObject.CompareTag("World"))
    173.         {
    174.             grounded = true;
    175.             canUsePotShot = true;
    176.             jumpCount = 0;
    177.         }
    178.     }
    179.     private void OnTriggerExit2D(Collider2D collision)
    180.     {
    181.         if (collision.gameObject.CompareTag("World"))
    182.         {
    183.             grounded = false;
    184.         }
    185.     }
    186. }

    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:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PlayerController : MonoBehaviour
    6. {
    7.     private bool isSpacePressed = false;
    8.     private bool isRightPressed = false;
    9.     private bool isLeftPressed = false;
    10.     private bool isUpPressed = false;
    11.     private bool isDownPressed = false;
    12.     private bool canFastfall = false;
    13.     private bool headbutting = false;
    14.     private bool directionLock = false;
    15.     private bool canUsePotShot = true;
    16.     private bool usePotShot = false;
    17.     private bool jumpsAvailable = true;
    18.     private bool grounded = false;
    19.     private bool facingLeft = false;
    20.     private bool facingRight = true;
    21.     private bool rotateToNormalRotation = false;
    22.     private bool shouldAnimationReset = true;
    23.     private bool potShotRecoiling = false;
    24.     private bool freezePosition;
    25.     private bool freezePositionNeedsAdjusting;
    26.     private int jumpCount = 0;
    27.     private int maxJumps = 2;
    28.     public int health = 3;
    29.     public float jumpHeight = 5;
    30.     private float fastfallSpeed = 2f;
    31.     private float knockback;
    32.     private float stunTime;
    33.     private float potShooterOffset = 90;
    34.     private float maxChargeTime = 0.6f;
    35.     private float chargeTime = 0;
    36.     private float potShotRecoil = 0.2f;
    37.     public float potShotSpeed;
    38.     private float normalGravityScale;
    39.     private Vector2 recoilVelocity;
    40.     private Vector3 emptyVector3 = Vector3.zero;
    41.     private Vector3 difference;
    42.     private Rigidbody2D rb;
    43.     private Animator animator;
    44.     private PlayerController playerController;
    45.     private GameObject[] bodyparts;
    46.     private SpriteRenderer[] srBodyparts;
    47.     private BoxCollider2D boxCollider2D;
    48.     private EffectsScript effectsScript;
    49.     public GameObject potShotProjectile;
    50.     private SpriteRenderer potSpriteRenderer;
    51.  
    52.     void Start()
    53.     {
    54.         rb = GetComponent<Rigidbody2D>();
    55.         animator = GetComponent<Animator>();
    56.         playerController = GetComponent<PlayerController>();
    57.         effectsScript = GameObject.FindGameObjectWithTag("Effects").GetComponent<EffectsScript>();
    58.         bodyparts = GameObject.FindGameObjectsWithTag("Player Bodypart");
    59.         potSpriteRenderer = transform.Find("Pot").gameObject.GetComponent<SpriteRenderer>();
    60.         srBodyparts = new SpriteRenderer[bodyparts.Length];
    61.         for(int i = 0; i < bodyparts.Length; i++)
    62.         {
    63.             srBodyparts[i] = bodyparts[i].GetComponent<SpriteRenderer>();
    64.         }
    65.         rb.interpolation = RigidbodyInterpolation2D.Interpolate;
    66.         maxJumps--;
    67.         boxCollider2D = gameObject.GetComponent<BoxCollider2D>();
    68.         normalGravityScale = rb.gravityScale;
    69.         //Application.targetFrameRate = 60;
    70.     }
    71.  
    72.     private void Update()
    73.     {
    74.         Jump();
    75.         PotShooter();
    76.         Headbutt();
    77.         Fastfall();
    78.         DirectionAdjuster();
    79.         if(animator.GetCurrentAnimatorStateInfo(0).IsName("Wilbur_Idle") == false && shouldAnimationReset)
    80.         {
    81.             StartCoroutine(AnimationResetter());
    82.         }
    83.         if (rotateToNormalRotation)
    84.         {
    85.             transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 0f, 0f), 5f * Time.deltaTime);
    86.             //transform.rotation = Quaternion.Euler(0f, 0f, 0f);
    87.             if(transform.rotation == Quaternion.Euler(0f, 0f, 0f))
    88.             {
    89.                 rotateToNormalRotation = false; ;
    90.             }
    91.         }
    92.     }
    93.     private void Jump()
    94.     {
    95.         if (Input.GetKeyDown("space") && jumpsAvailable)
    96.         {
    97.             isSpacePressed = true;
    98.             animator.Play("Wilbur_Jump", -1, 0.0f);
    99.             if (grounded == false)
    100.             {
    101.                 jumpCount++;
    102.             }
    103.         }
    104.         isRightPressed = Input.GetKey("d");
    105.         isLeftPressed = Input.GetKey("a");
    106.         isUpPressed = Input.GetKey("w");
    107.     }
    108.     private void PotShooter()
    109.     {
    110.         if (Input.GetMouseButton(0) && grounded == false && canUsePotShot)
    111.         {
    112.             animator.Play("Wilbur_Pot_Shot_In");
    113.             freezePosition = true;
    114.             difference = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
    115.             float rotZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
    116.             transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 0f, rotZ + potShooterOffset), 4f * Time.deltaTime);
    117.             potSpriteRenderer.color = new Color(1.0f, 0.63f, 0.63f);
    118.             chargeTime += Time.deltaTime;
    119.             potShotSpeed = chargeTime * 5;
    120.             if(chargeTime > maxChargeTime)
    121.             {
    122.                 usePotShot = true;
    123.             }
    124.             directionLock = true;
    125.         }
    126.         if((Input.GetMouseButtonUp(0) || usePotShot) && grounded == false && canUsePotShot)
    127.         {
    128.             animator.Play("Wilbur_Pot_Shot_Out");
    129.             Instantiate(potShotProjectile, transform.Find("Pot").position, transform.Find("Pot").rotation);
    130.             float angle = Mathf.Atan2(difference.y, difference.x);
    131.             recoilVelocity = new Vector2(-Mathf.Cos(angle) * Mathf.Rad2Deg * potShotRecoil, -Mathf.Sin(angle) * Mathf.Rad2Deg * potShotRecoil);
    132.             potShotRecoiling = true;
    133.             canUsePotShot = false;
    134.             freezePosition = false;
    135.             freezePositionNeedsAdjusting = true;
    136.             rotateToNormalRotation = true;
    137.             potSpriteRenderer.color = Color.white;
    138.             usePotShot = false;
    139.             chargeTime = 0;
    140.             directionLock = false;
    141.         }
    142.     }
    143.     private void Headbutt()
    144.     {
    145.         if (Input.GetMouseButtonDown(0) && grounded && headbutting == false)
    146.         {
    147.             StartCoroutine(HeadbuttRoutine());
    148.         }
    149.     }
    150.     private void Fastfall()
    151.     {
    152.         isDownPressed = Input.GetKeyDown("s");
    153.         if (isDownPressed && grounded == false && canFastfall && rb.velocity.y > -fastfallSpeed)
    154.         {
    155.             rb.velocity = new Vector2(rb.velocity.x, -fastfallSpeed);
    156.             canFastfall = false;
    157.         }
    158.     }
    159.     private void DirectionAdjuster()
    160.     {
    161.         if (isLeftPressed && directionLock == false)
    162.         {
    163.             facingLeft = true;
    164.         }
    165.         if (isRightPressed && directionLock == false)
    166.         {
    167.             facingRight = true;
    168.         }
    169.         if (facingLeft)
    170.         {
    171.             transform.localScale = new Vector2(-Mathf.Abs(transform.localScale.x), transform.localScale.y);
    172.             for(int i = 0; i < effectsScript.isFlipped.Length; i++)
    173.             {
    174.                 effectsScript.isFlipped[i] = true;
    175.             }
    176.             boxCollider2D.offset = new Vector2(Mathf.Abs(boxCollider2D.offset.x), boxCollider2D.offset.y);
    177.             facingLeft = false;
    178.         }
    179.         if (facingRight)
    180.         {
    181.             transform.localScale = new Vector2(Mathf.Abs(transform.localScale.x), transform.localScale.y);
    182.             for (int i = 0; i < effectsScript.isFlipped.Length; i++)
    183.             {
    184.                 effectsScript.isFlipped[i] = false;
    185.             }
    186.             boxCollider2D.offset = new Vector2(-Mathf.Abs(boxCollider2D.offset.x), boxCollider2D.offset.y);
    187.             facingRight = false;
    188.         }
    189.     }
    190.     void FixedUpdate()
    191.     {
    192.         if (isSpacePressed)
    193.         {
    194.             JumpDicider();
    195.             isSpacePressed = false;
    196.         }
    197.  
    198.         if (freezePosition)
    199.         {
    200.             rb.velocity = emptyVector3;
    201.             rb.gravityScale = 0;
    202.         }
    203.         else if(freezePosition == false && freezePositionNeedsAdjusting)
    204.         {
    205.             rb.gravityScale = normalGravityScale;
    206.             freezePositionNeedsAdjusting = false;
    207.         }
    208.  
    209.  
    210.         if (potShotRecoiling)
    211.         {
    212.             rb.velocity = recoilVelocity;
    213.             potShotRecoiling = false;
    214.         }
    215.  
    216.         if (jumpCount == maxJumps)
    217.         {
    218.             jumpsAvailable = false;
    219.         }
    220.         else
    221.         {
    222.             jumpsAvailable = true;
    223.         }
    224.     }
    225.     private void JumpDicider()
    226.     {
    227.         if (isRightPressed == false && isLeftPressed == false && isUpPressed == false)
    228.         {
    229.             rb.velocity = new Vector2(rb.velocity.x, jumpHeight);
    230.         }
    231.         else if (isRightPressed && isLeftPressed == false && isUpPressed == false)
    232.         {
    233.             rb.velocity = new Vector2(jumpHeight, jumpHeight / 1.8f);
    234.         }
    235.         else if (isRightPressed == false && isLeftPressed && isUpPressed == false)
    236.         {
    237.             rb.velocity = new Vector2(-jumpHeight, jumpHeight / 1.8f);
    238.         }
    239.         else if (isRightPressed == false && isLeftPressed == false && isUpPressed)
    240.         {
    241.             rb.velocity = new Vector2(rb.velocity.x, (jumpHeight + (jumpHeight / 3)));
    242.         }
    243.         else if (isRightPressed && isLeftPressed && isUpPressed)
    244.         {
    245.             rb.velocity = new Vector2(rb.velocity.x, (jumpHeight + (jumpHeight / 3)));
    246.         }
    247.         else if (isRightPressed && isLeftPressed == false && isUpPressed)
    248.         {
    249.             rb.velocity = new Vector2(jumpHeight / 1.8f, (jumpHeight + (jumpHeight / 3) / 1.8f));
    250.         }
    251.         else if (isRightPressed == false && isLeftPressed && isUpPressed)
    252.         {
    253.             rb.velocity = new Vector2(-jumpHeight / 1.8f, (jumpHeight + (jumpHeight / 3) / 1.8f));
    254.         }
    255.     }
    256.     private void OnTriggerEnter2D(Collider2D collision)
    257.     {
    258.         if (collision.gameObject.CompareTag("World"))
    259.         {
    260.             grounded = true;
    261.             if(transform.rotation != Quaternion.Euler(0f, 0f, 0f))
    262.             {
    263.                 transform.rotation = Quaternion.Euler(0f, 0f, 0f);
    264.             }
    265.             canUsePotShot = true;
    266.             rb.velocity = new Vector2(0, rb.velocity.y);
    267.             jumpCount = 0;
    268.             effectsScript.spawn[0] = true;
    269.         }
    270.     }
    271.     private void OnTriggerExit2D(Collider2D collision)
    272.     {
    273.         if (collision.gameObject.CompareTag("World"))
    274.         {
    275.             grounded = false;
    276.             canFastfall = true;
    277.         }
    278.     }
    279.     private void OnCollisionEnter2D(Collision2D collision)
    280.     {
    281.         if (collision.gameObject.CompareTag("Enemy"))
    282.         {
    283.             health -= collision.gameObject.GetComponent<EnemyScript>().damage;
    284.             knockback = collision.gameObject.GetComponent<EnemyScript>().knockback;
    285.             stunTime = Mathf.Abs(knockback / 20);
    286.             StartCoroutine(Knockback());
    287.         }
    288.        
    289.     }
    290.     IEnumerator Knockback()
    291.     {
    292.         rb.velocity = new Vector2(knockback, Mathf.Abs(knockback / 2));
    293.         playerController.enabled = false;
    294.         for(int i = 0; i < srBodyparts.Length; i++)
    295.         {
    296.             srBodyparts[i].color = new Color(0.97f, 0.49f, 0.49f, 1);
    297.         }
    298.         yield return new WaitForSeconds(stunTime);
    299.         for (int i = 0; i < srBodyparts.Length; i++)
    300.         {
    301.             srBodyparts[i].color = Color.white;
    302.         }
    303.         playerController.enabled = true;
    304.     }
    305.     IEnumerator HeadbuttRoutine()
    306.     {
    307.         headbutting = true;
    308.         directionLock = true;
    309.         animator.Play("Wilbur_Headbutt");
    310.         yield return new WaitForSeconds(7 / 60f);
    311.         effectsScript.spawn[1] = true;
    312.         yield return new WaitForSeconds(14 / 60f);
    313.         directionLock = false;
    314.         headbutting = false;
    315.     }
    316.     IEnumerator AnimationResetter()
    317.     {
    318.         shouldAnimationReset = false;
    319.         float currentAnimation = animator.GetCurrentAnimatorStateInfo(0).fullPathHash;
    320.         float animationTime = animator.GetCurrentAnimatorStateInfo(0).length;
    321.         yield return new WaitForSeconds(animationTime);
    322.         if(currentAnimation == animator.GetCurrentAnimatorStateInfo(0).fullPathHash) animator.Play("Wilbur_Idle");
    323.         shouldAnimationReset = true;
    324.     }
    325. }
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,947
    You have a lot of huge blocks of duplicated logic, but I'd start looking at lines 79 and 93: you probably do not want to set the rotation when difference is below a certain magnitude, for example less than 0.1 or so.

    There may also be physics interaction going on, as you are not using the physics properly to rotate: you are bypassing it by going straight to the transform. In a nutshell:

    With Physics (or Physics2D), never manipulate the Transform directly. If you manipulate the Transform directly, you are bypassing the physics system and you can reasonably expect glitching and missed collisions and other physics mayhem.

    Always use the .MovePosition() and .MoveRotation() methods on the Rigidbody (or Rigidbody2D) instance in order to move or rotate things. Doing this keeps the physics system informed about what is going on.

    https://forum.unity.com/threads/col...-unity-physic-rigidbody.1216875/#post-7763061

    https://forum.unity.com/threads/oncollisionenter2d-not-being-called.1266563/#post-8044121

    If that's not it, here's how to actually find out what your code is doing:

    What is often happening in these cases is one of the following:

    - the code you think is executing is not actually executing at all
    - the code is executing far EARLIER or LATER than you think
    - the code is executing far LESS OFTEN than you think
    - the code is executing far MORE OFTEN than you think
    - the code is executing on another GameObject than you think it is
    - you're getting an error or warning and you haven't noticed it in the console window

    To help gain more insight into your problem, I recommend liberally sprinkling
    Debug.Log()
    statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?
    - are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

    Knowing this information will help you reason about the behavior you are seeing.

    You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as
    Debug.Log("Problem!",this);


    If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

    You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

    You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer or iOS: https://forum.unity.com/threads/how-to-capturing-device-logs-on-ios.529920/ or this answer for Android: https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/

    Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494

    You must find a way to get the information you need in order to reason about what the problem is.
     
  3. Slurgelman

    Slurgelman

    Joined:
    Aug 25, 2022
    Posts:
    7
    Thanks a lot for your amazing in-depth reply Kurt-Dekker,

    Using
    Code (CSharp):
    1. rb.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 0f, rotZ + potShooterOffset), 4f * Time.fixedDeltaTime).eulerAngles.z;
    and
    Code (CSharp):
    1. if (rotateToNormalRotation)
    2.         {
    3.             rb.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 0f, 0f), 5f * Time.fixedDeltaTime).eulerAngles.z;
    4.             if (rb.rotation == 0)
    5.             {
    6.                 rotateToNormalRotation = false;
    7.             }
    8.         }
    then putting them in FixedUpdate() instead of using
    Code (CSharp):
    1. transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 0f, rotZ + potShooterOffset), 4f * Time.deltaTime);
    and
    Code (CSharp):
    1. if (rotateToNormalRotation)
    2.         {
    3.             transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 0f, 0f), 5f * Time.deltaTime);
    4.             if (transform.rotation == Quaternion.Euler(0f, 0f, 0f))
    5.             {
    6.                 rotateToNormalRotation = false;
    7.             }
    8.         }
    in Update() seemed to have fixed the stutter.