- Home /
 
Unity crashing... For some reason
I do know a few details about it. I am trying to instantiate a prefab which creates an overlap sphere and when the overlapsphere hits a player, that's when everything crashes.
So the problem is, how do I debug this? My code always looks perfectly fine to me but I know it isn't lol. I might not be the best coder but with a few hours I can usually debug my problems. Also, can this damage my project in any way? Should I create a backup?
Here's the code if anyone's interested:
 using UnityEngine;
 using System.Collections;
 
 public class Turret : MonoBehaviour {
 
     private int expireTime = 10;
     private int projectileDamage = 20;
     private float cooldown = 2;
     private float cooldownBetweenProjectiles = 0.1f;
     public GameObject explosion;
     public string creator;
     private PlayerStats statsScript;
     
     public int health = 50;
     private int radius = 100;
     private Collider [] hitObjects;
     private bool aquireTarget = true;
     private bool fire = true;
     private float fireUntil = 0;
     private float fireDuration = 1;
     private bool fireNextProjectile = true;
     
     public GameObject projectile;
     private float randomRotationX = 25;
     private float randomRotationY = 25;
     private Transform target;
     private Vector3 firePosition;
     private Quaternion fireRotation;
     
     // Use this for initialization
     void Start ()
     {
         //Destroy the object after a while
         StartCoroutine(expire());
         target = null;
     }
     
     // Update is called once per frame
     void Update ()
     {
         if(health <= 0)
         {
             //Destroy the object if it loses all it's HP
             destroy();
         }
         
         if(aquireTarget == true)
         {
             //If a target needs to be aquired, create an overlap sphere and call the chooseTarget function
             hitObjects = Physics.OverlapSphere(transform.position, radius);
             chooseTarget();
             aquireTarget = false;
         }
 
         if(target != null)
         {
             //If there is a target, rotate towards it
             transform.LookAt(target.position);
             
             if(fire == true)
             {
                 //If the turret is allowed to fire, do so
                 fireProjectiles();
                 fire = false;
             }
         }
     }
     
     void chooseTarget()
     {
         //Reset the target first
         target = null;
         
         for(int i = 0; i < hitObjects.Length; i++)
         {
             //If the target is a player, the function is finished.
             if((hitObjects[i].transform.tag == "Player1" && creator == "Player2") ||
                 (hitObjects[i].transform.tag == "Player2" && creator == "Player1"))
             {
                 target = hitObjects[i].transform;
                 break;
             }
             
             //If there's no player in range pick the closest enemy turret.
             else if(hitObjects[i].transform.tag == "Turret" &&
                     ((hitObjects[i].GetComponent<Turret>().creator == "Player1" && creator == "Player2") ||
                     (hitObjects[i].GetComponent<Turret>().creator == "Player2" && creator == "Player1")))
             {
                 target = hitObjects[i].transform;
                 //Going to put distance code and sorting here later on...
             }
         }
     }
     
     IEnumerator CD()
     {
         //Cooldown until next burst of projecetiles
         yield return new WaitForSeconds(cooldown);
         fire = true;
     }
     
     IEnumerator smallCD()
     {
         //Cooldown between every projectile fired
         yield return new WaitForSeconds(cooldownBetweenProjectiles);
         fireNextProjectile = true;
     }
     
     void fireProjectiles()
     {
         //Start cooldown until next burst
         StartCoroutine(CD());
         //Set an amount of time for which the turret is allowed to fire
         fireUntil = Time.time + fireDuration;
         
         //Fire for the duration of time
         while(Time.time < fireUntil)
         {
             //This is set to true after a small amount of time
             if(fireNextProjectile == true)
             {
                 //Start projectile cooldown
                 StartCoroutine(smallCD ());
                 fireNextProjectile = false;
                 
                 //Fire position in front of the turret and a slightly randomized aim
                 firePosition = transform.TransformPoint(0, 0, 1);
                 fireRotation = randomize(Quaternion.Euler(new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, 0)));
                 
                 //Instantiate the projectile for all players
                 networkView.RPC("fireProjectile", RPCMode.All, firePosition, fireRotation, creator);
             }
         }
     }
     
     IEnumerator expire()
     {
         //Destroy the object after an amount of seconds
         yield return new WaitForSeconds(expireTime);
         destroy();
     }
     
     void destroy()
     {
         //Create an explosion and destroy the object
         Instantiate(explosion, transform.position, transform.rotation);
         Destroy(gameObject);
     }
     
     [RPC]
     void fireProjectile(Vector3 position, Quaternion rotation, string createdBy)
     {
         //Instantiate projectile and set damage and creator in it's script
         GameObject p = Instantiate(projectile, position, rotation) as GameObject;
         p.GetComponent<TurretProjectile>().setDamage(projectileDamage);
         p.GetComponent<TurretProjectile>().setCreator(createdBy);
     }
     
     Quaternion randomize(Quaternion rot)
     {
         //Modify the rotation slightly
         float randomX = Random.Range(-randomRotationX / 2, randomRotationX / 2);
         float randomY = Random.Range(-randomRotationY / 2, randomRotationY / 2);
         return Quaternion.Euler(new Vector3(rot.eulerAngles.x + randomX, rot.eulerAngles.y + randomY, rot.eulerAngles.z));
     }
 }
 
              Answer by rutter · Oct 11, 2012 at 12:46 AM
In `fireProjectiles()`, you have this while loop:
 while(Time.time < fireUntil)
 
               From a (very) quick read, it looks to me like `Time.time` isn't advancing during this loop, which could imply an infinite loop. Worth checking out?
If that is the problem, you could quickly fix the problem by making that function a coroutine which waits one frame before re-checking the loop condition, or otherwise refactoring so that you're running those checks once per frame, instead of all at once.
Answer by Latedi · Oct 11, 2012 at 01:16 AM
So I'm not entirely sure what created the crash but I narrowed it down to the while-loop in the fireProjectiles() function. I removed the IENumerator and bool controlling the firerate and instead put a for loop in a IENumerator which then called the function to fire projectiles. A lot less messy and appearantly non-crashing.
Here's the working code if anyone's going to need this:
 using UnityEngine;
 using System.Collections;
 
 public class Turret : MonoBehaviour {
 
     private int expireTime = 10;
     private int projectileDamage = 20;
     private int amountOfProjectiles = 10;
     private float cooldown = 2;
     private float cooldownBetweenfiring = 0.1f;
     public GameObject explosion;
     public string creator;
     private PlayerStats statsScript;
     
     public int health = 50;
     private int radius = 100;
     private Collider [] hitObjects;
     private bool aquireTarget = true;
     private bool fireNow = true;
     
     public GameObject projectile;
     private float randomRotationX = 7.5f;
     private float randomRotationY = 7.5f;
     private Transform target;
     private Vector3 firePosition;
     private Quaternion fireRotation;
     
     // Use this for initialization
     void Start ()
     {
         //Destroy the object after a while
         StartCoroutine(expire());
         target = null;
         transform.parent = GameObject.Find("Creatures").transform;
     }
     
     // Update is called once per frame
     void Update ()
     {
         if(health <= 0)
         {
             //Destroy the object if it loses all it's HP
             destroy();
         }
         
         if(aquireTarget == true)
         {
             //If a target needs to be aquired, create an overlap sphere and call the chooseTarget function
             hitObjects = Physics.OverlapSphere(transform.position, radius);
             chooseTarget();
             aquireTarget = false;
         }
 
         if(target != null)
         {
             //If there is a target, rotate towards it
             transform.LookAt(target.position);
             
             if(fireNow == true)
             {
                 //If the turret is allowed to fire, do so
                 StartCoroutine(fire ());
                 fireNow = false;
             }
         }
         else if(target == null && fireNow == true)
         {
             aquireTarget = true;
         }
     }
     
     void chooseTarget()
     {
         //Reset the target first
         target = null;
         
         for(int i = 0; i < hitObjects.Length; i++)
         {
             //If the target is a player, the function is finished.
             if((hitObjects[i].transform.tag == "Player1" && creator == "Player2") ||
                 (hitObjects[i].transform.tag == "Player2" && creator == "Player1"))
             {
                 target = hitObjects[i].transform;
                 break;
             }
             
             //If there's no player in range pick the closest enemy turret.
             else if(hitObjects[i].transform.tag == "Turret" &&
                     ((hitObjects[i].GetComponent<Turret>().creator == "Player1" && creator == "Player2") ||
                     (hitObjects[i].GetComponent<Turret>().creator == "Player2" && creator == "Player1")))
             {
                 target = hitObjects[i].transform;
                 //Going to put distance code and sorting here later on...
             }
         }
     }
     
     IEnumerator CD()
     {
         //Cooldown until next burst of projecetiles
         yield return new WaitForSeconds(cooldown);
         aquireTarget = true;
         fireNow = true;
     }
     
     IEnumerator fire()
     {
         //Start cooldown
         StartCoroutine(CD ());
         
         //Loop for amount of projectiles to fire
         for(int i = 0; i < amountOfProjectiles; i++)
         {
             //Cooldown between every projectile fired
             yield return new WaitForSeconds(cooldownBetweenfiring);
             fireProjectiles();
         }
         
         target = null;
     }
     
     void fireProjectiles()
     {
         //Fire position in front of the turret and a slightly randomized aim
         firePosition = transform.TransformPoint(0, 0, 1);
         fireRotation = randomize(Quaternion.Euler(new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, 0)));
         
         //Instantiate the projectile for all players
         networkView.RPC("fireProjectile", RPCMode.All, firePosition, fireRotation, creator);
     }
     
     IEnumerator expire()
     {
         //Destroy the object after an amount of seconds
         yield return new WaitForSeconds(expireTime);
         destroy();
     }
     
     void destroy()
     {
         //Create an explosion and destroy the object
         Instantiate(explosion, transform.position, transform.rotation);
         Destroy(gameObject);
     }
     
     [RPC]
     void fireProjectile(Vector3 position, Quaternion rotation, string createdBy)
     {
         //Instantiate projectile and set damage and creator in it's script
         GameObject p = Instantiate(projectile, position, rotation) as GameObject;
         p.GetComponent<TurretProjectile>().setDamage(projectileDamage);
         p.GetComponent<TurretProjectile>().setCreator(createdBy);
     }
     
     Quaternion randomize(Quaternion rot)
     {
         //Modify the rotation slightly
         float randomX = Random.Range(-randomRotationX / 2, randomRotationX / 2);
         float randomY = Random.Range(-randomRotationY / 2, randomRotationY / 2);
         return Quaternion.Euler(new Vector3(rot.eulerAngles.x + randomX, rot.eulerAngles.y + randomY, rot.eulerAngles.z));
     }
 }
 
              Your answer
 
             Follow this Question
Related Questions
Unity3d Crash error (Mono.dll) with NetworkView 0 Answers
A node in a childnode? 1 Answer
Unity + dk2 compilation problem 1 Answer
Profiler crashes unity 0 Answers
Making an Online Multiplayer Game in Unity's 'Free' Version. 4 Answers