Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Bug stack overflow exception, have no idea what and where!!

Discussion in 'Scripting' started by wanglash2007tv, Nov 10, 2022.

  1. wanglash2007tv

    wanglash2007tv

    Joined:
    Jan 27, 2022
    Posts:
    3
    i am fairly new to unity, and have been making a basic soulslike movement system. however, upon trying to add rolling mechanics, when i press play it crashes. every now and then for a split second i can see that it has created a stack overflow exception, yet the place it tells me is unreadable!!

    im sure i look very stupid rn and of course it is readable, but i have never seen this ever. any ideas? thanks.

    upload_2022-11-10_23-22-15.png
     
  2. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    5,204
    Share the script that causes the error
     
  3. wanglash2007tv

    wanglash2007tv

    Joined:
    Jan 27, 2022
    Posts:
    3
    thats the thing, i cant. what i sent is the error message, but it doesnt even point me in the direction as far as i can see.
    i'll send a few possible scripts that i *think* might house the error but these are nothing more than best guesses

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace EJ
    6. {
    7.     public class PlayerLocomotion : MonoBehaviour
    8.     {
    9.         Transform CameraObject;
    10.         InputHandler inputHandler;
    11.         Vector3 MoveDirection;
    12.  
    13.         [HideInInspector]
    14.         public Transform _transform;
    15.         [HideInInspector]
    16.         public AnimatorHandler animatorHandler;
    17.  
    18.         public new Rigidbody rigidbody;
    19.         public GameObject NormalCamera;
    20.  
    21.         [Header("Stats")]
    22.         [SerializeField]
    23.         float MovementSpeed = 5f;
    24.         [SerializeField]
    25.         float RotationSpeed = 10f;
    26.  
    27.  
    28.  
    29.         // Start is called before the first frame update
    30.         void Start()
    31.         {
    32.             rigidbody = GetComponent<Rigidbody>();
    33.             inputHandler = GetComponent<InputHandler>();
    34.             animatorHandler = GetComponentInChildren<AnimatorHandler>();
    35.             CameraObject = Camera.main.transform;
    36.             _transform = transform;
    37.             animatorHandler.Initialize();
    38.         }
    39.  
    40.         public void Update()
    41.         {
    42.             float delta = Time.deltaTime;
    43.             inputHandler.TickInput(delta);
    44.  
    45.             HandleMovement(delta);
    46.             HandleRollingAndSprinting(delta);
    47.         }
    48.  
    49.         #region Movement
    50.         Vector3 NormalVector;
    51.         Vector3 TargetPosition;
    52.  
    53.         private void handleRotation(float delta)
    54.         {
    55.             Vector3 TargetDir = Vector3.zero;
    56.             float MoveOverride = inputHandler.MoveAmount;
    57.  
    58.             HandleMovement(delta);
    59.         }
    60.  
    61.         public void HandleMovement(float delta)
    62.         {
    63.             MoveDirection = CameraObject.forward * inputHandler.Vertical;
    64.             MoveDirection += CameraObject.right * inputHandler.Horizontal;
    65.             MoveDirection.Normalize();
    66.             MoveDirection.y = 0;
    67.  
    68.             float speed = MovementSpeed;
    69.             MoveDirection *= speed;
    70.  
    71.             Vector3 ProjectedVelocity = Vector3.ProjectOnPlane(MoveDirection, NormalVector);
    72.             rigidbody.velocity = ProjectedVelocity;
    73.  
    74.             animatorHandler.UpdateAnimatorValues(inputHandler.MoveAmount, 0);
    75.  
    76.             if (animatorHandler.canRotate)
    77.             {
    78.                 handleRotation(delta);
    79.             }
    80.         }
    81.  
    82.         public void HandleRollingAndSprinting(float delta)
    83.         {
    84.             if (animatorHandler.anim.GetBool("IsInteracting"))
    85.                 return;
    86.  
    87.             if (inputHandler.RollFlag)
    88.             {
    89.                 MoveDirection = CameraObject.forward * inputHandler.Vertical;
    90.                 MoveDirection += CameraObject.right * inputHandler.Horizontal;
    91.  
    92.                 if (inputHandler.MoveAmount > 0)
    93.                 {
    94.                     animatorHandler.PlayTargetAnimation("RollForward", true);
    95.                     MoveDirection.y = 0;
    96.                     Quaternion RollRotation = Quaternion.LookRotation(MoveDirection);
    97.                     _transform.rotation = RollRotation;
    98.                 }
    99.                 else
    100.                 {
    101.                     animatorHandler.PlayTargetAnimation("RollBackward", true);
    102.                 }
    103.             }
    104.         }
    105.         #endregion
    106.     }
    107. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace EJ
    6. {
    7.     public class AnimatorHandler : MonoBehaviour
    8.     {
    9.         public Animator anim;
    10.         int vertical;
    11.         int horizontal;
    12.  
    13.         public bool canRotate;
    14.  
    15.         public void Initialize()
    16.         {
    17.             anim = GetComponent<Animator>();
    18.             vertical = Animator.StringToHash("vertical");
    19.             horizontal = Animator.StringToHash("horizontal");
    20.         }
    21.  
    22.         public void UpdateAnimatorValues(float VerticalMovement, float HorizontalMovement)
    23.         {
    24.             #region Vertical
    25.  
    26.             float v = 0;
    27.  
    28.             if (VerticalMovement > 0 && VerticalMovement < 0.55f)
    29.             {
    30.                 v = 0.55f;
    31.             }
    32.             else if (VerticalMovement > 0.55f)
    33.             {
    34.                 v = 1;
    35.             }
    36.             else if (VerticalMovement < 0 && VerticalMovement > -0.55f)
    37.             {
    38.                 v = -0.5f;
    39.             }
    40.             else if (VerticalMovement < -0.55f)
    41.             {
    42.                 v = -1;
    43.             }
    44.             else
    45.             {
    46.                 v = 0;
    47.             }
    48.  
    49.             #endregion
    50.  
    51.             #region Horizontal
    52.  
    53.             float h = 0;
    54.  
    55.             if (HorizontalMovement > 0 && HorizontalMovement < 0.55f)
    56.             {
    57.                 h = 0.55f;
    58.             }
    59.             else if (HorizontalMovement > 0.55f)
    60.             {
    61.                 h = 1;
    62.             }
    63.             else if (HorizontalMovement < 0 && HorizontalMovement> -0.55f)
    64.             {
    65.                 h = -0.5f;
    66.             }
    67.             else if (HorizontalMovement < -0.55f)
    68.             {
    69.                 h = -1;
    70.             }
    71.             else
    72.             {
    73.                 h = 0;
    74.             }
    75.  
    76.             #endregion
    77.  
    78.             anim.SetFloat(vertical, v, 0.1f, Time.deltaTime);
    79.             anim.SetFloat(horizontal, h, 0.1f, Time.deltaTime);
    80.         }
    81.  
    82.         public void PlayTargetAnimation(string TargetAnim, bool IsInteracting)
    83.         {
    84.             anim.applyRootMotion = IsInteracting;
    85.             anim.SetBool("IsInteracting", IsInteracting);
    86.             anim.CrossFade(TargetAnim, 0.2f);
    87.  
    88.         }
    89.  
    90.         public void CanRotate()
    91.         {
    92.             canRotate = true;
    93.         }
    94.  
    95.         public void StopRotation()
    96.         {
    97.             canRotate = false;
    98.         }
    99.     }
    100. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5.  
    6. namespace EJ
    7. {
    8.     public class InputHandler : MonoBehaviour
    9.     {
    10.         public float Horizontal;
    11.         public float Vertical;
    12.         public float MoveAmount;
    13.         public float MouseX;
    14.         public float MouseY;
    15.  
    16.         public bool B_Input;
    17.         public bool RollFlag;
    18.  
    19.         PlayerControls InputActions;
    20.         CameraHandler cameraHandler;
    21.  
    22.         Vector2 MovementInput;
    23.         Vector2 CameraInput;
    24.  
    25.         private void Awake()
    26.         {
    27.             cameraHandler = CameraHandler.singleton;
    28.         }
    29.  
    30.         private void FixedUpdate()
    31.         {
    32.             float delta = Time.fixedDeltaTime;
    33.  
    34.             if(cameraHandler != null)
    35.             {
    36.                 cameraHandler.FollowTarget(delta);
    37.                 cameraHandler.HandleCameraRotation(delta, MouseX, MouseY);
    38.             }
    39.         }
    40.  
    41.         public void OnEnable()
    42.         {
    43.             if (InputActions == null)
    44.             {
    45.                 InputActions = new PlayerControls();
    46.                 InputActions.PlayerMovement.Movement.performed += InputActions => MovementInput = InputActions.ReadValue<Vector2>();
    47.                 InputActions.PlayerMovement.Camera.performed += i => CameraInput = i.ReadValue<Vector2>();
    48.             }
    49.  
    50.             InputActions.Enable();
    51.         }
    52.  
    53.         private void OnDisable()
    54.         {
    55.             InputActions.Disable();
    56.         }
    57.  
    58.         public void TickInput(float delta)
    59.         {
    60.             MoveInput(delta);
    61.             HandleRollingInput(delta);
    62.         }
    63.  
    64.         private void MoveInput(float delta)
    65.         {
    66.             Horizontal = MovementInput.x;
    67.             Vertical = MovementInput.y;
    68.  
    69.             MoveAmount = Mathf.Clamp01(Mathf.Abs(Horizontal) + Mathf.Abs(Vertical));
    70.             MouseX = CameraInput.x;
    71.             MouseY = CameraInput.y;
    72.         }
    73.  
    74.         private void HandleRollingInput(float delta)
    75.         {
    76.             B_Input = InputActions.PlayerActions.Roll.phase == UnityEngine.InputSystem.InputActionPhase.Started;
    77.  
    78.             if (B_Input)
    79.             {
    80.                 RollFlag = true;
    81.             }
    82.         }
    83.     }
    84. }
    85.  
    86.  
    (im fully aware i suck ass at coding but in my defense ive been doing this for a month)
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,371
    I see handle rotation calling handle movement calling handle rotation calling ... *BOOM*
     
    Dommm95, Ryiah, Yoreki and 3 others like this.
  5. Nad_B

    Nad_B

    Joined:
    Aug 1, 2021
    Posts:
    730
    A StackOverflow exception generally means you have a method that calls itself indefinitely, thus exhausting the stack. for eg:


    Code (CSharp):
    1. public void CheckHealth()
    2. {
    3.     if (health < 20)
    4.     {
    5.         CheckHealth(); // this will cause a StackOverflow exception...
    6.     }
    7. }
    The easiest way to fix it, is to attach a Debugger and put a breakpoint in the beginning of the script (Awake method for eg.) then stepping into your code (F11 key), after some time you'll see the method that gets called forever and all the trail/history of calls (called the "call stack")
     
    Last edited: Nov 12, 2022
  6. TzuriTeshuba

    TzuriTeshuba

    Joined:
    Aug 6, 2019
    Posts:
    186
    every time you call a function, you add values to what is called "the stack", when you exit a function, these values are removed. the stack is limitted in its capacity (it can store a lot, but not infinity). you have mutual recursion occurring between HandleMovement() and HandleRotation(). each of those function calls is adding values to the stack each time they call one another. the only way your code will exit its recursive loop is when one of its base conditions are met. you only have 1 base condition which is if animator.canRotate=false. this condition is likely never met, causing your code to run forever until the stack just cant store what is necesary for another function call. So its throws the exception.

    It looks like your StopRotation() function is never called, your text editor should inform you of unreferenced variables and function, so give those a look before you say "finally done! lets run it!".
    Another tip, regarding recursion, is not just to check that the base condition CAN be met, but that it WILL be met at some point.

    Another similar bug to look out for is an endless while loop (outside coroutines). That bug is less forgiving than stack overflow as no error will be thrown and your game will "freeze" and you will just need to quit Unity. Cheers mate, Happy devving.