Help, with script

Hi,
I have some issues with the scripting in this project, so if anyone here using unity5 or higher version please share your script (specially for Brick.cs) for block breaker game.
Thanks.

Hi Vivek,

What is the problem you are having?

Hi ,
I’m uploading my project files here, (unable upload to drive),
It is not uploading full file in one zip so different file and put it together please (if possible),

Assets.zip (5.9 MB)

BloackBreaker.csproj.zip (2.8 KB)

BloackBreaker.sln.zip (519 Bytes)

BloackBreaker.userprefs.zip (447 Bytes)

etc.zip (142 Bytes)

Library.zip (4.7 MB)

ProjectSettings.zip (13.2 KB)
UnityPackageManager.zip (379 Bytes)

I have tried to change the code but failed, I want to get a popup of level complete after clearing each level for that I tried to use GUI canvas but failed.
Then I tried same as instructed in the tutorial but getting an error at brick destroyed in Brick.cs.

Go through my project see for the faults you can find and correct them.

And please tell me how can I get a level complete popup when breakable count is 0.

My script,

  1. Ball
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Ball : MonoBehaviour {


    private Rigidbody2D MyBall;
    private Paddle paddle;
    private bool hasStarted = false;
    private Vector3 paddleToBallVector;



	// Use this for initialization
	void Start () {
        paddle = GameObject.FindObjectOfType<Paddle>();
        paddleToBallVector = this.transform.position - paddle.transform.position;
        MyBall = GetComponent<Rigidbody2D>();
        

    }
	
	// Update is called once per frame
	void Update () {
        if (!hasStarted)
        {
            this.transform.position = paddle.transform.position + paddleToBallVector;

            if (Input.GetMouseButtonDown(0))
            {
                print("Mouse clicked, launch ball");
                hasStarted = true;
                MyBall.velocity = new Vector2(2f, 10f);
                GetComponent<AudioSource>().Play();
            }

        }

    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        Vector2 tweak = new Vector2(Random.Range(0f, 0.2f), Random.Range(0f, 0.2f));

        if (hasStarted)
            {
                 GetComponent<AudioSource>().Play();
                 GetComponent<Rigidbody2D>().velocity += tweak;
        }
    }


   
}

2)Brick

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

public class Brick : MonoBehaviour
{

    public AudioClip crack;
    public Sprite[] hitSprites;
    public static int breakableCount = 0;
    public GameObject Smoke;


    private int maxHits;
    private int timesHit;
    private bool isBeakable;
    private SceneManager sceneManager;



    // Use this for initialization
    void Start()
    {
        isBeakable = (this.tag == "Breakable");

        if (isBeakable)
        {
            breakableCount++;

            if (Brick.breakableCount <= 0)
            {
                SceneManager.LoadScene("Win");
            }

        }

        timesHit = 0;


    }

    // Update is called once per frame
    void Update()
    {


    }

    void OnCollisionEnter2D(Collision2D col)
    {
        AudioSource.PlayClipAtPoint(crack, transform.position, 0.8f);
        if (isBeakable)
        {
            HandleHits();
        }

    }

    void HandleHits()
    {
        timesHit++;
        maxHits = hitSprites.Length + 1;
        if (timesHit >= maxHits)
        {
            breakableCount--;

          

            PuffSmoke();
            Destroy(gameObject);
        }
        else
        {
            LoadSprites();
        }
    }

    void PuffSmoke()
    {
        GameObject smokePuff = Instantiate(Smoke, transform.position, Quaternion.identity) as GameObject;
        smokePuff.GetComponent<ParticleSystem>().startColor = gameObject.GetComponent<SpriteRenderer>().color;
    }



    void LoadSprites()
    {
        int spriteIndex = timesHit - 1;

        if (hitSprites[spriteIndex] != null)
        {
            this.GetComponent<SpriteRenderer>().sprite = hitSprites[spriteIndex];
        }
        else
        {
            Debug.LogError("Brick sprite missing");

        }
    }

  

}

3)LevelManager


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

public class LevelManager : MonoBehaviour
{


    public void MySwitchScenes(string MySwitchScenes)
    {
        Brick.breakableCount = 0;
        SceneManager.LoadScene(MySwitchScenes);

    }


    public void QuitRequest()
    {
        Debug.Log("I want to quit!");
        Application.Quit();
    }

        

    public void BrickDestroyed()
    {
        if (Brick.breakableCount <= 0)
        {
            
        }
    }
}

4)Loase Collider


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


public class LoseColllider : MonoBehaviour {

    private SceneManager sceneManager;

    void OnTriggerEnter2D(Collider2D trigger)
    {
               SceneManager.LoadScene("Lose");
    }

   void OnCollisionEnter2D(Collision2D collision)
    {
        print("Collision");
    }
}

5)Music Player

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

public class MusicPlayer : MonoBehaviour {
    static MusicPlayer instance = null;
    void Aswake()
    {
  
        if (instance != null)
        {
            Destroy(gameObject);
            print("Duplicate Music Player Self-Destructing!");
        }
        else
        {
            instance = this;
            GameObject.DontDestroyOnLoad(gameObject);

        }
    }
    
	void Update () {
		
	}
}

6)Paddle

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

public class Paddle : MonoBehaviour {

    public bool autoPlay = false;
    public float minX, maxX;

    private Ball ball;


    private void Start()
    {
        ball = GameObject.FindObjectOfType<Ball>();
    }

    // Update is called once per frame
    void Update () {
        if (autoPlay == false)
        {
            MoveWithMouse();
        }
        else
        {
            AutoPlay();
        }
		
	}

    void AutoPlay()
    {
        Vector3 paddlePos = new Vector3(0.5f, this.transform.position.y, 0f);
        Vector3 ballPos = ball.transform.position;
        paddlePos.x = Mathf.Clamp(ballPos.x, minX, maxX);
        this.transform.position = paddlePos;
    }

    void MoveWithMouse()
    {
        Vector3 paddlePos = new Vector3(0.5f, this.transform.position.y, 0f);
        float mousePosInBlocks = Input.mousePosition.x / Screen.width * 16;
        paddlePos.x = Mathf.Clamp(mousePosInBlocks, minX, maxX);
        this.transform.position = paddlePos;

    }
}

Hi Vivek,

So, the files above and the copy/paste of the scripts, this is what you currently have, correct?

Also, you mentioned that you have tried to have a message appear after each level is completed, I don’t see any code in the above that looks like it might do that, have you taken it back out?

What errors are you currently receiving?

I would suggest that we work through these first, get a stable version of the game working at this point before trying to add the additional feature.

If you could answer the above and in the mean time I will take a look at all the download files as promised.


Updated Mon Jan 08 2018 23:00

Observations from scripts pasted above

Brick.cs

This line is unnecessary;

private SceneManager sceneManager;

The LoadScene method of the SceneManager class is static, as such you do not need an instance of the SceneManager class to use it, you can just reference it via the class, as you are doing further down in your code in the Start method. Note that SceneManager is capitalised, the name of the class, not sceneManager, your variable.

LevelManager.cs

The BrickDestroyed method currently doesn’t do anything, as such, you will not progress to another level in the game, I’m not certain if you are aware of this, or if this is how far you have got in the course so far. I would suggest at the very least putting a Debug.Log statement in there so that something is output to the console when the method is called and your condition is met;

    public void BrickDestroyed()
    {
        if (Brick.breakableCount <= 0)
        {
            Debug.Log("Brick.breakableCount <= 0");    // add this line, just for now, for debugging purposes
        }
    }

LoseColllider.cs

The class name has an extra l character in it’s name, not a massive issue, as long as the filename is spelled the same way too.

Again, the following line is unnecessary and can be removed;

private SceneManager sceneManager;

You have both OnTriggerEnter2D and OnCollisionEnter2D. The latter is unnecessary and can be removed.

MusicPlayer.cs

You have misspelled the Awake method (Aswake), as such this will never be called by Unity, as it is unrecognised, remove the s in the method name.

General

You have a bit of a lack of consistency in some of the naming of variables and the placement of braces/brackets. Whilst this won’t prevent your code from running, it’s not really best practice and will invariably only make it harder for yourself to debug when things go wrong.

As a very loose set of a guidelines for now, I would recommend you ensure that the following use Pascal case (PascalCase);

  • Class names - example LevelManager
  • Method names - example LoadScene

and the following use camel case (camelCase)

  • variable names - example - autoPlay
  • parameters names - example - sceneName

When it comes to naming variables, properties, methods, parameters for methods, generally anything - give some consideration to what it actually is. For example, the method MySwitchScenes doesn’t really make a lot of sense, less so because it also has a parameter of the same name being passed into it (in PascalCase!).

If you think about exactly what this method is for, it’s simply to load another scene, so the term “My” is redundant. The terms “Switch” and “Scenes” less so, but still perhaps not as clear as they could be. I think in the course this method was called “LoadLevel”, that’s fairly simplistic, makes sense and everyone would know what it was for. Equally, you could perhaps call it “LoadScene”, just the actual SceneManager class does.

The parameter being passed in is the name of the scene to load, so why not simplify this and name it accordingly, levelName or sceneName.

With regards to the brackets / braces, at the moment you have a bit of a mixture between trailing and block style, e.g;

private void Start() {

}

and

private void Start()
{

}

Again, this wont make any difference from the perspective of the compiler, but when it comes to looking through your code for debugging purposes it is less easy on the eye. If you have been caught out at all by a missing closing brace for example, you may find it easier initially to adopt the block style approach;

private void Start()
{
    if(missingClosingBrace == true)
    {
        Debug.Log("Try the block style approach.");
    }
}

As you can see from the above, the brace line up with each either vertically, for both the method and the if statement. This can make it easier to read and also easier to spot missing brackets and braces.

These may seem like fairly minor/petty points, but when you get into bigger projects, the last thing you want is to be spending a lot of time trying to work out all of the different naming conventions, and meanings of things instead of just looking for the problem and fixing it.


Ok, now I will go and grab those files! :slight_smile:

1 Like

Thanks, Rob
First, the code I sent you is before the use of LoadNextlevel.

When I add brick destroyed it says the reference does not exist in the current context same with LoadNextLevel.

And about private SceneManager, so I was experimenting with the LoadScene and forgot to remove it before sending the code to you.

Now I will try to do same as in the tutorial for load next level and then again tell you what exactly the problem is.

With particle system, getting the error:

ParticleSystem.startColor’ is obsolete: 'startColor property is deprecated. Use main.startColor instead.

Again the next level is loading just after I destroy first brick.

1 Like

Then I add brick destroyed it says the reference does not exist in the current context same with LoadNextLevel.

This will because you do not have a reference to LevelManager in your Brick.cs script. As such, it doesn’t know what a “BrickDestroyed” is, once you add a reference for the LevelManager you will be able to access this method via;

levelManager.BrickDestroyed();

And about private SceneManager, so I was experimenting with the LoadScene and forgot to remove it before sending the code to you.

No worries, it was just a minor thing, always handy to keep things tidy :slight_smile:

With particle system, getting the error:

ParticleSystem.startColor’ is obsolete: 'startColor property is deprecated. Use main.startColor instead.

This is due to changes in the Unity API, you are obviously using a different version to that which the course used when created. If you look at lecture 8 you will see there is a link to a Google document which covers all of the changes/differences, the ParticleSystem changes are there also :slight_smile:

Again the next level is loading just after I destroy first brick.

Another playable level, or a Win / Lose scene?

Just as a quick test, add this to your LevelManager.cs script;

private void Start()
{
    Debug.Log("Number of breakable bricks : " + Brick.breakableCount);
}

This is only temporary, but let me know what the count is that it returns on your playable level and, how many actual bricks you have in your playable level.

Another playable level.

private void Start()
{
    Debug.Log("Number of breakable bricks : " + Brick.breakableCount);
}

it shows breakable bricks are 0.

So, your code is actually working correctly then, once there are effectively no breakableBricks your code loads the next level.

The issue is then perhaps, is that your bricks are not tagged as Breakable - go check :slight_smile:

They are. I already checked them twice yesterday.

Did you check the prefabs or the instances which are in the game scene?

yes, I checked all prefabs.
Let me rewrite the code for LoadNexLevel then.

Ok, so, have a look at one of the bricks in the scene, perhaps the one you have successfully hit before the game loads the next scene and check that one also. Is it set correctly?

What do you currently have in your BrickDestroyed method within LevelManager.cs also?


Updated Tue Jan 09 2018 13:57

Ok, so I’ve finally untangled all of those zipped files and put together a project I could open.

In your Brick.cs you had this;

private SceneManager sceneManager;

and it needs to be this;

private LevelManager levelManager;

additionally, you then need to actually initialise the levelManager variable, so in your Start method;

// Use this for initialization
void Start() {
    isBeakable = (this.tag == "Breakable");

    if (isBeakable)
    {
        breakableCount++;

    }

    timesHit = 0;
}

add the following after the linesHit = 0; line;

levelManager = GameObject.FindObjectOfType<LevelManager>();

and then finally, in your HandleHits method;

void HandleHits()
{
    timesHit++;
    maxHits = hitSprites.Length + 1;
    
    if (timesHit >= maxHits)
    {
        breakableCount--;

        sceneManager.BrickDestroyed();
            
        PuffSmoke();
        Destroy(gameObject);
    }
    else
    {
        LoadSprites();
    }
}

change this line;

sceneManager.BrickDestroyed();

to this;

levelManager.BrickDestroyed();

After making these changes I was able to run your game from the Start scene, pick level 1, and then hit several bricks without it jumping instantly to the next scene.#

Hope this helps :slight_smile:

1 Like

Still, the next level is loading immediately when I hit any brick even unbreakable, but I removed script component from unbreakable now except unbreakable when I hit any brick still loading the next level

here are my scripts,

Brick

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

public class Brick : MonoBehaviour
{

    public AudioClip crack;
    public Sprite[] hitSprites;
    public static int breakableCount = 0;
    public GameObject Smoke;
    public Color32 startColor;
    

    private int maxHits;
    private int timesHit;
    private bool isBreakable;
    private LevelManager levelManager;


    // Use this for initialization
    void Start()
    {
        isBreakable = (this.tag == "Breakable");

        if (isBreakable)
        {
            breakableCount++;
            print(breakableCount);

        }

        timesHit = 0;
        levelManager = GameObject.FindObjectOfType<LevelManager>();

    }

    // Update is called once per frame
    void Update()
    {


    }

    void OnCollisionEnter2D(Collision2D col)
    {
        AudioSource.PlayClipAtPoint(crack, transform.position, 0.8f);
        if (isBreakable)
        {
            HandleHits();
        }
        SimulateWin();  // comment out this line so that you don't keep jumping to the next level
    }

    void HandleHits()
    {
        timesHit++;
        maxHits = hitSprites.Length + 1;
        if (timesHit >= maxHits)
        {
            breakableCount--;
            levelManager.BrickDestroyed();
            PuffSmoke();
            Destroy(gameObject);
        }
        else
        {
            LoadSprites();
        }
    }

    void PuffSmoke()
    {
        GameObject smokePuff = Instantiate(Smoke, transform.position, Quaternion.identity) as GameObject;
        smokePuff.GetComponent<ParticleSystem>().startColor = gameObject.GetComponent<SpriteRenderer>().color;
    }



    void LoadSprites()
    {
        int spriteIndex = timesHit - 1;

        if (hitSprites[spriteIndex] != null)
        {
            this.GetComponent<SpriteRenderer>().sprite = hitSprites[spriteIndex];
        }
        else
        {
            Debug.LogError("Brick sprite missing");

        }
    }


    void SimulateWin()
    {
        levelManager.LoadNextLevel();
    }
}

LevelManager

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

public class LevelManager : MonoBehaviour
{

    private void Start()
    {
        Debug.Log("Number of breakable bricks : " + Brick.breakableCount);
    }


    public void MySwitchScenes(string MySwitchScenes)
    {
        Brick.breakableCount = 0;
        SceneManager.LoadScene(MySwitchScenes);

    }


    public void QuitRequest()
    {
        Debug.Log("I want to quit!");
        Application.Quit();
    }

    

       
    public void LoadNextLevel()
    {
        Application.LoadLevel(Application.loadedLevel + 1);
    }
   
    public void BrickDestroyed()
    {
        if (Brick.breakableCount <= 0)
        {
            LoadNextLevel();
        }
    }



}

You are still calling the SimulateWin method in the OnCollisionEnter2D method within Brick.cs, so it is executing before the rest of the fixes.

Also, you need to use the ` character for the code formatting, what you are entering at the moment isn’t working, e.g. ’’’ :slight_smile:

1 Like

Oh I thought I have to use ’ 3 times.
Yeah, now it works.

1 Like

Great.

So, with all of that fixed, are you ok to move forwards again now, can we close this topic?

1 Like

Thanks a lot,
now I can work for further improvements as you said.

Just can you please tell me what can I do to make a win screen popup after each level complete (any you tube tutorials or something similar).
And yes we can close this topic.

1 Like

You’re very welcome.

I’m a bit tied up for the next few hours, but if you like I can break off this new functionality into a separate topic and then reply later with some suggestions.

1 Like

Ok,
So where or when should i create a new topic.

1 Like

Privacy & Terms