Making a recursive "chain reaction" method inside a subclass

Hello,

I’m a beginner and currently trying to work out classes, inheritance, and overrides while making a breakout-type game.

My goal is to have the BombBick to explode all nearby bricks, and if the nearby bricks are bombs, continue the reaction. My BombBrick has an ExplosionLogic method that calls the ExplodeBrick method of any Brick nearby.

I can’t get it to work the way I intend to, and right now Unity just crashes when ball collides with a bomb.

I would appreciate any advice. Also lmk if there is a better way to do this, I’m eager to learn.

public class Brick : MonoBehaviour
{
    public Vector2 brickSize = new Vector2(1, 1);
    public int hitPoints;
    public int scoreValue;

    public ParticleSystem explosionParticle;
    public System.Action onBrickHP0;

    void Start()
    {
        transform.localScale = brickSize;
        onBrickHP0 += IncreaseScore;
    }

    protected virtual void Update()
    {
        if (hitPoints == 0)
        {
            DestroyBrick();
        }
    }

    protected virtual void OnCollisionEnter2D(Collision2D collision)
    {
        switch(collision.gameObject.tag)
        {
            case "Ball":
                {
                    hitPoints -= 1;
                    break;
                }
        }
    }

    private void IncreaseScore()
    {
        GameLogic.score += scoreValue;
    }

    public void DestroyBrick(float waitTime = 0)
    {
        onBrickHP0?.Invoke();
        Destroy(gameObject, waitTime);
    }

    public virtual void ExplodeBrick()
    {
        ParticleSystem explosionEffect = Instantiate(explosionParticle, transform.position, Quaternion.identity);
        explosionEffect.transform.localScale = brickSize;
        explosionEffect.Play();

        DestroyBrick();
        Destroy(explosionEffect.gameObject, .5f);
    }
}

public class BombBrick : Brick
{
    public bool explosive;
    public Vector2 explosionSize = new Vector2(2.5f, 2.5f);
    public System.Action onBombHP0;

    void Start()
    {
        hitPoints = 1;
        scoreValue = 10;
        explosive = true;

        onBombHP0 += ExplosionLogic;
    }

    protected override void Update()
    {
        if (hitPoints == 0)
        {
            onBombHP0?.Invoke();
            explosive = false;
        }
    }

    private void ExplosionLogic()
    {
        if (explosive)
        {
            int brickCount = 0;

            Collider2D[] nearbyObjects = Physics2D.OverlapBoxAll(transform.position, explosionSize, 0f);
            foreach (Collider2D nearbyCollider in nearbyObjects)
            {
                Brick nearbyBrick = nearbyCollider.gameObject.GetComponent<Brick>();
                if (nearbyBrick != null)
                {
                    nearbyBrick.ExplodeBrick();
                    brickCount += 1;
                }
            }
            Debug.Log(brickCount + " bricks found nearby");
        }
    }


    public override void ExplodeBrick()
    {
        ExplosionLogic();
        base.ExplodeBrick();
    }
}

you can use

if(nearbyCollider.gameObject.TryGetComponent<Brick>(out Brick nearbyBrick )) {
nearbyBrick.ExplodeBrick();
brickCount += 1;
}

Instead of

Brick nearbyBrick = nearbyCollider.gameObject.GetComponent<Brick>();
                if (nearbyBrick != null){
                    nearbyBrick.ExplodeBrick();
                    brickCount += 1;
                }

This looks much better and easy to understand. If you don’t know how is it working let me know.

Have you made a breakout game before? You might want to just make one without confusing yourself with recursion and inheritance and overriding. There’s just no need for that for a breakout game.

ALSO: Unity isn’t really geared for inheritance. The underlying core of Unity is composition using components that each bring something to the table. YES you can use inheritance. Now you’ve got more things to contend with. I wouldn’t recommend it for breakout!

Start with tutorials. Do several small ones. When you do them, follow these…

Two steps to tutorials and / or example code:

  1. do them perfectly, to the letter (zero typos, including punctuation and capitalization)
  2. stop and understand each step to understand what is going on.

If you go past anything that you don’t understand, then you’re just mimicking what you saw without actually learning, essentially wasting your own time. It’s only two steps. Don’t skip either step.

Unity will lock up 100% of the time EVERY millisecond your scripting code is running.

Nothing will render, no input will be processed, no Debug.Log() will come out, no GameObjects or transforms will appear to update.

Absolutely NOTHING will happen… until your code either:

  • returns from whatever function it is running

  • yields from whatever coroutine it is running

As long as your code is looping, Unity isn’t going to do even a single frame of change. Nothing.

No exceptions.

“Yield early, yield often, yield like your game depends on it… it does!” - Kurt Dekker

1 Like

Have you made a breakout game before? You might want to just make one without confusing yourself with recursion and inheritance and overriding. There’s just no need for that for a breakout game.

I’ve followed a couple very basic tutorials, including a breakout one. I’m already a few mini-games past exactly replicating tutorials and am onto the “understanding it” part. I wanted to see if I could create bomb chain reaction logic by myself. Obviously there’s “no need” for more complicated concepts here, but I thought having various brick behaviors all be part of a Brick class would serve as good practice for those concepts for the future.

Unity will lock up 100% of the time EVERY millisecond your scripting code is running.

I understand this, but I can’t figure out where I’m causing it to infinitely loop.

Find out with a breakpoint!

Sounds like you wrote a bug… and that means… time to start debugging!

By debugging you can find out exactly what your program is doing so you can fix it.

Use the above techniques to get the information you need in order to reason about what the problem is.

You can also use Debug.Log(...); statements to find out if any of your code is even running. Don’t assume it is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

1 Like

Its because of BombBrick.ExplosionLogic() calls Brick.ExplodeBrick() on all bricks in an overlapped box. That overlap is including ITSELF. and BombBrick.ExplodeBrick() calls ExplosionLogic(), which does it all again. The “explosive” variable is only set false at the END of the call chain, but that end is never reached since the infinite loop is happening right before it.

Just set explosive to false right after you made its if() check.

edit: also you should add an “exploded” flag for bricks that have just exploded and brick that have exploded should not explode when ExplodeBrick() is called. As it is now if a brick is inside an overlaps of several explosive bricks its gonna explode several times, spawning several particle prefabs per brick. so if you have 4 bomb bricks chain 20 bricks thats upward bound of 80 particle prefabs on 20 bricks.

1 Like

in other words,

“To understand recursion, you must understand recursion.”

I actually prefer chain reaction type things where you set off a bunch of explosions, then AFTER spinning everything you apply fresh damage and deal with it next turn, so you can watch it all propagate out over several frames. No recursion needed… it’s sorta self-spreading… although I can’t imagine what breakout game mechanic would recursively explode a bunch of stuff… that’s not my daddy’s breakout. :slight_smile:

Thanks, this worked!

1 Like