- 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