Tuesday, September 19, 2017

unity - Method causes OutOfMemory error


If a GameObject in my game has a special ability it triggers it, but I want all the special GameObjects that this GameObject affects to also trigger their abilities, for example if a bomb hits some objects, if these objects are also bombs, trigger them too. I though this would be easy by calling the method that handles all the special abilities recursively, but, as always, it wasn't. Basically what happened is a chain reaction of bullcrap that caused Unity to show an OurOfMemory error. Also makes my PC freeze completely while politely turning all the screens off.


The question is, how can I make it so it triggers all the affected cubes' special abilities, without everything going nuts?


Code:


     //Triggers the cube's special ability, if it has any
private void TriggerSpecialCubeAbility(GameObject specialCube) {
switch (specialCube.tag) {

//Destroy all cubes in a radius from the special cube
case "Bomb":

TriggerBombAbility(specialCube);
break;

//Destroy all cubes of the same color as the special cube
case "Lighting":
TriggerLightingAbility(specialCube);
break;
default:
break;
}

}

private void TriggerBombAbility(GameObject specialCube) {
var nearbyColliders = Physics2D.OverlapCircleAll(specialCube.transform.position, explosionRadius);
Instantiate(particles[0], specialCube.transform.position, specialCube.transform.rotation);
Instantiate(particles[1], specialCube.transform.position, specialCube.transform.rotation);

foreach (var collider in nearbyColliders) {
if (collider.tag == "Indestructible")
return;


var affectedCube = collider.gameObject;
TriggerSpecialCubeAbility(affectedCube);
Destroy(affectedCube);
}

destroySelectedCubes = true;
// Physics2D.gravity *= -1;
// Physics.gravity *= -1;
}


Answer



First of all, you seem to have a bug in TriggerBombAbility(): that return should be a continue.


Now a quick way to fix your issue of infinite recursion is to devise a way to mark a GameObject as no longer triggerable. For instance you could have a hasBeenTriggered boolean, defaulting to false, and you set it to true before triggering abilities:


       case "Bomb":
specialCube.hasBeenTriggered = true;
TriggerBombAbility(specialCube);
break;

Then you only call TriggerSpecialCubeAbility() if the ability hasn’t already been triggered:


        var affectedCube = collider.gameObject;

if (!affectedCube.hasBeenTriggered)
{
TriggerSpecialCubeAbility(affectedCube);
Destroy(affectedCube);
}

Alternatively, you could put that check in TriggerSpecialCubeAbility() itself and do an early exit: Nevermind; this would require a check around Destroy(), too, and is therefore more complicated.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...