Search Unity

Question Heisenbug with stack overflow

Discussion in 'Scripting' started by MaximN, Jul 11, 2020.

  1. MaximN

    MaximN

    Joined:
    Jan 18, 2020
    Posts:
    1
    Hi all!
    I have a problem with attached script. I dont understend this behavior and i can't debug this.
    In project I have terrain with collider, and object(box). On start, box have position(0,1,0). When my player have collision with this box, i destroy it box with timeout(Destroy(gameObject, 2.0f)). Before destroy I make instantiate. It's work fine, but i need check, that distance from box to terrain always eqaul 1 meter. This is make by recursive function void HeightCorrection(). And here i have "heisenbug", because sometime it's work fine, sometime i have stackoverflow error in recursive function. Debug.Log("...") not work for me - on stackoverflow Unity Editor fall.
    Please, help me - I read docs, forums, but I can't search resolve for this fail. Sorry for my bad english.

    Below is a simplified script:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.VFX;
    5. using UnityEditor;
    6.  
    7. public class LutScore : MonoBehaviour
    8. {
    9.     public int score = 1;
    10.     public int failedCounter = 0;
    11.  
    12.     public GameObject lutPrefab;
    13.  
    14.     private GameObject cloneInstance;
    15.     private Renderer rend;
    16.     private bool kludge = true;
    17.     private Ray lutRayNegative, lutRayPositive;
    18.  
    19.     // Start is called before the first frame update
    20.     void Awake()
    21.     {
    22.         rend = GetComponent<Renderer>();
    23.         if (rend == null) { Debug.LogError("rend fail"); }
    24.  
    25.         // kludge, needed because we Instantiate an object
    26.         kludge = true;
    27.         score = 1;
    28.     }
    29.  
    30.     void Start()
    31.     {
    32.         HeightCorrection();
    33.     }
    34.  
    35.     // Update is called once per frame
    36.     void Update()
    37.     {
    38.         if (score == 0 && kludge) {
    39.             kludge = false;
    40.             CreateInscance();
    41.             rend.enabled = false;
    42.             Destroy(gameObject, 2.0f);
    43.         }
    44.     }
    45.  
    46.     // Function for transform object position on 1 meter above terrain
    47.     void HeightCorrection()
    48.     {
    49.         RaycastHit lutHitN, lutHitP;
    50.         bool neg_f = false, pos_f = false;
    51.         float rayDistance = 1.0f;
    52.  
    53.         // Check distance to terrain
    54.         lutRayNegative = new Ray(gameObject.transform.position, gameObject.transform.up * (-1.0f));
    55.         lutRayPositive = new Ray(gameObject.transform.position, gameObject.transform.up);
    56.  
    57.         if (Physics.Raycast(lutRayNegative, out lutHitN))
    58.         {
    59.             if (lutHitN.collider.gameObject.CompareTag("Terrain"))
    60.             {
    61.                 if (!Mathf.Approximately(lutHitN.distance, rayDistance))
    62.                 {
    63.                     gameObject.transform.position += new Vector3(0.0f, (rayDistance - lutHitN.distance), 0.0f);
    64.                     neg_f = true;
    65.                 }
    66.             }
    67.         }
    68.         if (Physics.Raycast(lutRayPositive, out lutHitP))
    69.         {
    70.             if (lutHitP.collider.gameObject.CompareTag("Terrain"))
    71.             {
    72.                 if (!Mathf.Approximately(lutHitP.distance, rayDistance))
    73.                 {
    74.                     gameObject.transform.position += new Vector3(0.0f, (rayDistance + lutHitP.distance), 0.0f);
    75.                     pos_f = true;
    76.                 }
    77.             }
    78.         }
    79.  
    80.         //Collision not detected - Terrain collider inside object collider
    81.         if (neg_f == false && pos_f == false)
    82.         {
    83.             failedCounter += 1;
    84.             gameObject.transform.position += Vector3.up;
    85.  
    86.             //here is stackoverflow
    87.             HeightCorrection();
    88.         }
    89.     }
    90.  
    91.     // TODO: Maybe problem is here
    92.     void CreateInscance()
    93.     {
    94.         cloneInstance = Instantiate(lutPrefab, gameObject.transform.position, gameObject.transform.rotation) as GameObject;
    95.         //right function
    96.         //cloneInstance.transform.position += new Vector3(Random.Range(-6.0f, 6.0f), Random.Range(-6.0f, 6.0f), Random.Range(-6.0f, 6.0f));
    97.         //function for debug
    98.         cloneInstance.transform.position += new Vector3(1.0f, Random.Range(-6.0f, 6.0f), 0.0f);
    99.     }
    100. }
     

    Attached Files:

    Last edited: Jul 12, 2020
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,735
    MaximN likes this.
  3. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    I see you have a "failedCounter" variable that increments whenever you make the recursive call. To help you debug, what if you bail out with a simple "return" and log an error message if failedCounter reaches an unreasonably high number, like 200? (not sure how many iterations you are expecting)

    That will stop the StackOverflow and let you see your Debug.Log statements.
     
    MaximN likes this.