Scene visibility weirdness

So before moving onto lesson 26 I tested out the game and noticed that upon ball falling to the lose collider in Level 1, the scene shifts to Level 2 instead of Game over. So I started investigating. The code on LoseCollider is:

    private void OnTriggerEnter2D(Collider2D collision)
    {        
        SceneManager.LoadScene("Game Over");
    }

and Scenes are like this
image
and in Build Settings
image

So I decided to do some investigating and I’ve added a piece of code to SceneLoader script that lists available scenes in each scene

    private void Start()
    {
        Debug.Log($"Available scenes in: {SceneManager.GetActiveScene().name}");
        foreach(Scene scene in SceneManager.GetAllScenes())
        {
            Debug.Log($"Scene: {scene.name}, path: {scene.path}");
        }
    }

And that resulted in this really puzzling output:
image

Also, not sure if related but this has started showing up in my hierarchy yesterday
image

I usually see one ore more scenes where one is loading and others are loaded. I can remove the loaded scenes but the loading one isn’t going away nor is it getting loaded…

I am totally confused here, if anyone has any idea what I’ve messed up or what to try please help.

Hi Matija,

First of all, good job on analysing the problem. Please check if your code also loads the “next” scene. Add a Debug.Log to figure that out.

I’ve added more debug logs to scene loader methods

    public void LoadNextScene()
    {
        Debug.Log("LoadNextScene called");
        int nextSceneIndex = SceneManager.GetActiveScene().buildIndex + 1;
        Debug.Log($"Loading scene with index: " + nextSceneIndex);
        SceneManager.LoadScene(nextSceneIndex);
    }

    public void LoadStartScene()
    {
        Debug.Log("LoadStartScene called");
        SceneManager.LoadScene(0);
    }

    public void LoadGameOverScene()
    {
        Debug.Log("LoadGameOverScene called");
        SceneManager.LoadScene("Game Over");
    }

and updated the LoseCollider a bit

public class LoseCollider : MonoBehaviour
{    

    private void OnTriggerEnter2D(Collider2D collision)
    {
        FindObjectOfType<SceneLoader>().LoadGameOverScene();
    }
}

and here is the result:

It seems that when the ball hits the LoseCollider it calls the LoadGameOverScene correctly, but then it also calls LoadNextScene for some reason even though that function is not mentioned in the LoseCollider nor the SceneLoader.LoadGameOverScene()

I’ll look into this some more… really puzzling

Where else is LoadNextScene called? Select LoadNextScene and press shift + F12, alternatively, select “Find All References” in the context menu.

https://docs.microsoft.com/en-gb/visualstudio/ide/finding-references?view=vs-2019

I’ve taken a look and I think I’ve found the issue.
In Level class I have the following code:

    public void decrementBlockCount()
    {
        if (--breakableBlocks == 0)
        {
            sceneLoader.LoadNextScene();            
        }
    }

And decrementBlockCount() is called in Block's OnDestroy() method

    private void OnDestroy()
    {
        level.decrementBlockCount();
        gameStatus.addToScore(scorePoints);
    }

So here’s what I’m guessing was the issue. The ball goes out of bounds, hits the LoseCollider and triggers the scene change to Game Over scene, but as the scene is changing the level scene I assume has some sort of cleanup performed as it’s being swapped and that cleanup called OnDestroy on all Block entities and as it was being destroyed it kept calling the level.decrementBlockCount() so when the last Block entity got destroyed it triggered another scene change, this time to next level as if we destroyed all blocks.

I’ve since gone and refactored the code so now in my Breakable script (I’ve deviated a bit from the course in regards that I’ve already been using Tags before the tags lesson for tagging entities such as Ball, Block and Paddle so instead of Breakable tag I’ve created a Breakable script that I attach to breakable blocks) I’ve got the following code:

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (++hitCount >= hits)
        {            
            DestroyBlock();
        }
    }

    private void DestroyBlock()
    {
        AudioSource.PlayClipAtPoint(RandomUtils.getRandomElement(blockDestroySounds), Camera.main.transform.position, 0.3f);
        Destroy(gameObject);
        TriggerExplosionVFX();
        level.onBlockDestroy();
        gameStatus.addToScore(points);
    }

so the Level is being notified of block destruction in OnCollisionEnter2D and onBlockDestroy doesn’t actually change scenes it sets the level state like this

    public void onBlockDestroy()
    {
        --breakableBlocks;
        if(breakableBlocks <= 0 && Status == LevelStatus.PLAYING)
        {
            Status = LevelStatus.COMPLETED;
        }
    }

and the same for out of bounds

    public void onOutOfBounds()
    {
        Status = LevelStatus.FAILED;
    }

which then gets checked each Update iteration and routes to the appropriate level accordingly

    private void Update()
    {
        if(Status == LevelStatus.PLAYING)
        {
            return;
        } 
        else if (Status == LevelStatus.COMPLETED)
        {
            sceneLoader.LoadNextScene();
        } 
        else if (Status == LevelStatus.FAILED)
        {
            sceneLoader.LoadGameOverScene();
        }
    }

Not sure if the ifology within the update method is generally frowned upon, might refactor this later.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms