Problems with BlockBreaker HandleHit()

Hi everybody,
I’m struggling a bit with the BlockBreaker project.
Whenever I test the game the hit counter goes up when a block is hit and i have set a maxhit (the sprite also cylces) but the block never actually gets deleted. The counter just goes on and on.
The destroy method has worked before but I’ve got the feeling I might have missed something really small.
Thanks in advance for any help :slight_smile:

code :

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Block : MonoBehaviour
{
//Configuration parameters
[SerializeField] AudioClip breakSound;
[SerializeField] GameObject blockSparklesVFX;
// [SerializeField] int maxHits;
[SerializeField] Sprite hitSprites;

//Cached reference
Level level;

//State variables
[SerializeField] int timesHit; //TODO serialized for debug 

private void Start()
{
    CountBreakableBlocks();
}

private void CountBreakableBlocks()
{
    level = FindObjectOfType<Level>();
    if (tag == "Breakable")
    {
        level.CountBlocks();
    }
}

private void OnCollisionEnter2D(Collision2D collision)
{
    if (tag == "Breakable")
    {
        HandleHit();
    }
}

private void HandleHit()
{
    timesHit++;
    int maxHits = hitSprites.Length + 1;
    if (timesHit >= maxHits)
    {
        DestroyBlock();
    }
    else
    {
        ShowNextHitSprite();
    }
}

private void ShowNextHitSprite()
{
    int spriteIndex = timesHit - 1;
    if(hitSprites[spriteIndex] != null)
    {
        GetComponent<SpriteRenderer>().sprite = hitSprites[spriteIndex];
    }
    else
    {
        Debug.LogError("Block sprite is missing from array" + gameObject.name);
    }
}

private void DestroyBlock()
{
    PlayBlockDestroySFX();
    Destroy(gameObject);
    level.BlockDestroyed();
    TriggerSparklesVFX();
}

private void PlayBlockDestroySFX()
{
    FindObjectOfType<GameSession>().AddToScore();
    AudioSource.PlayClipAtPoint(breakSound, Camera.main.transform.position);
}

private void TriggerSparklesVFX() 
{
    GameObject sparkles = Instantiate(blockSparklesVFX, transform.position, transform.rotation);
    Destroy(sparkles,1f);
}

}

Hi,

Have you already compared your code to the Lecture Project Changes which can be found in the Resources of this lecture? Have you already tried to add Debug.Logs to your code to see what is going on during runtime? Maybe DestroyBlock never gets called.

Yeah I’ve tried comparing my code to the files in the git and didn’t see any problems there.
I put a debug in the if condition in HandleHit() and it never slips into the true condition to activate DestroyBlock()

That’s good. Now you know that the problem is that the condition never gets evaluated to true. Now check the value of timesHit and maxHits.

Okay so I’ve been looking around a bit more.
It turns out it does slip into the true condition, the timesHit and maxHits variables are counting correctly. It seems the problem is calling the method DestroyBlock().
It tries to start it and then returns this error:

NullReferenceException: Object reference not set to an instance of an object
Block.PlayBlockDestroySFX () (at Assets/Scripts/Block.cs:84)
Block.DestroyBlock () (at Assets/Scripts/Block.cs:76)
Block.HandleHit () (at Assets/Scripts/Block.cs:52)
Block.OnCollisionEnter2D (UnityEngine.Collision2D collision) (at Assets/Scripts/Block.cs:38)

Awesome. Error messages are usually great because they make it easier to find the root of a problem. Double click on the error message. To which line in your code does it refer?

According to your error message, the NullReferenceException got thrown when PlayBlockDestroySFX() got called. For testing purposes, comment the method call out and play your game again. If the issue is gone, the PlayBlockDestroySFX() method was “stopping” the execution of the rest of the method code block of the DestroyBlock method.

okay so I’ve tracked down the culprit i think

private void PlayBlockDestroySFX()
{
    //FindObjectOfType<GameSession>().AddToScore();
    AudioSource.PlayClipAtPoint(breakSound, Camera.main.transform.position);
}

the line that’s commented is the cause of the problem
i went back to unity instead of checking in the code itself
the problem was that the game object for GameSession was missing and it had no where to send the score information

thank you so much for your help! :slight_smile:

Does that mean, you fixed the issue?

If not, I assume that GameSession is a “singleton”. Check if gameObject.SetActive(false); gets called in the same if-block as Destroy(gameObject);. If there isn’t that line of code, add it.