How to connect the AutoPlay with a brick?

Hey everyone…
I came up with the idea to make a brick that when it takes a hit it triggers the
AutoPlay function…
I have been stuck on this for days now…
Thanks in advance.

Give your Brick a type, you could use an Enum.

In your HandleHits() method check for the type before determining what action to take.

If the brick is of the relevant type, set the autoplay boolean to true.

You will need to give some thought as to what will turn it back off… a duration of time would make sense perhaps…

1 Like

Hi Rob,
thank you for the solution…
the thing is that i am a complete noob in programming…
so how do I do it?
Create an enum and store the boolean into it?
why the use of enum?

Hi,

More of a suggestion overview than a solution :slight_smile:

Ok, so you could use a boolean, perhaps naming it something like;

public bool isAutoPlayPowerUp = false;

…you could then tick the box in the Inspector for the specific brick and off you go.

By using an ENUM you could extend your power-up mechanic a little further, for example, you may have other power-ups such as;

  • autoplay
  • fast ball
  • slow ball
  • multi ball
  • lasers

Once you have more than one power up having lots of booleans to set for each brick is going to become a lot less fun… you could of course create different block prefabs which are set as being a specific power-up, but what if you then want a red one, and a blue one, and a green one and so on. Often games like this would have a random effect which would make a specific block a power-up without the player knowing it was until it was broken. Of course, these are design considerations you would want to make yourself.

To continue with the suggestion however;


Brick.cs

Your enum might look like this;

private enum PowerUp { AutoPlay, FastBall, SlowBall, MultiBall, Lasers }

You might add a local variable to hold the type of power-up that the brick is;

private PowerUp powerUpType = null;

Note, I’ve set it to null so that you could add this to a brick and it would just be a normal brick, without a powerUp at all.

You’ll want something in the Start() method to determine if the brick is a power-up or not, you don’t want every brick to be a power-up, so you’ll need to determine some kind of probably/likelihood of a brick being a power-up.

void Start() 
{

    // existing code is also in here
    
    // note - you could end up with every, none, some, many bricks being set up as power-ups using the above as-is
    
    // represents 33% chance each brick could be a power-up - crude!    
    float powerUpChance = 0.33f;

    // determine if brick is a power-up
    if (Random.Range(0.01f, 1.0f) <= powerUpChance)    // 0.01f, 1.0f represent a value between 1 and 100
    {
        // set brick as power-up
        powerUpType = PowerUp.AutoPlay;    // specifically set AutoPlay power-up, you could randomise which they get        
    }
}

If you were to develop this further and add additional functionality and power-ups it would probably be worth separating the power-up code / logic out to a separate class in it’s own right.

You would probably want to determine a maximum number of possible power-up bricks per scene also, and keep a track of the number of those which have been created, skipping over the code to determine if the brick is a power-up or not in the Start() method.

It would also be a good idea to move the powerUpChance variable out of the Start() method, you could make it a public variable for the Brick class to start with, so that you could tweak it easily in the Inspector.

When it comes to determining whether the brick that was destroyed was a powerUp or not, you’d want something along the lines of this;

private void HandleHits()
{
    int maxHits = hitSprites.Length + 1;

    timesHit++;

    if (timesHit >= maxHits)
    {
        breakableCount--;
        levelManager.BrickDestroyed();
        PuffSmoke();

        // determine if brick was power-up
        if(powerUpType != null)    // could use if(powerUpType) as short-hand  
        {
            // determine which type of power-up
            switch(powerUpType)
            {
                case PowerUp.AutoPlay:
                    Debug.Log("PowerUp Active : AutoPlay");
                    break;
                case PowerUp.FastBall:
                    Debug.Log("PowerUp Active : FastBall");
                    break;
                case PowerUp.SlowBall:
                    Debug.Log("PowerUp Active : SlowBall");
                    break;
                case PowerUp.MultiBall:
                    Debug.Log("PowerUp Active : MultiBall");
                    break;
                case PowerUp.Lasers:
                    Debug.Log("PowerUp Active : Lasers");
                    break;
                default:
                    Debug.Log("PowerUp Active : One I have an ENUM for but no logic to catch");
                    break;               
            }
        }

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

As you can see from the above, it gets a bit messy approaching it this way, but this is a quick response to your question to get you started. I haven’t tested the above but I would expect the outcome to write to the console based on the power-up associated with the brick. As mentioned in the code for determining the chance of a brick being set as a power-up, you may get all, many, some or none :slight_smile: You could set the powerUpType on the Brick to be public so you can see it in the Inspector, pausing your game and clicking on each brick (just have a few in the scene for testing).

Hopefully the above gives you a bit of help getting started and I’m sure once you have you will find ways to improve on it. Depending on what your desired outcome is will really determine the approach you use, for example, if you wanted something to fall from the brick to indicate there was a power-up to “collect” (rather than just instantly get), you might want to instantiate another game object under the brick in the hierarchy and then move it and so on.

Assuming the above works (as I said, not tested) you can just activate the autoplay rather than writing to the console for the specific power-up (or both).


See also;

1 Like

I dont know who you are, but i just want to hug you! :laughing:
that is so helpful for me…
so much feedback :ocean:
Thank you for all the explanations with details!
And great ideas you have there!!!
One thing though, the variable for the powerUptype needs to declare what type of variable is… what should i put?

Hi,

You’re very welcome.

Apologies for the typo, I have amended my post, it should be of type PowerUp, e.g. the enum…

1 Like

Hey, i tried to do my best to try and guess why an error still pops up, but I feel so stupid asking you again… the error says (Cannot convert null to ‘Brick.PowerUp’ because it is a value type)
Thank you again…

Hi,

Hey, i tried to do my best to try and guess why an error still pops up

Ok, lets take a look (and well done for having a go yourself!)

but I feel so stupid asking you again…

Imagine how I feel having given you bug riddled code :wink: Joking aside, it’s 100% ok to ask for help, its exactly what this community is for and good at :slight_smile:

the error says (Cannot convert null to ‘Brick.PowerUp’ because it is a value type)

Ok, so our enum is effectively an integer under the hood, so my error was trying to set our variable powerUpType to null.

So, we can try two approaches…


The first would be to not set our variable to null in the first place, that would get rid of the error but we then have to check a couple of things.

Change this line;

    private PowerUp powerUpType = null;

to

    private PowerUp powerUpType;

What we are doing there is declaring a variable of type PowerUp but not initialising it with a value.

Because our enum is integer based, the values start at 0, so AutoPlay = 0, FastBall = 1 and so on.

The problem we will now have is that without initialising powerUpType it will equal 0 - the default value for an integer.

This is the same value as our PowerUp.AutoPlay enumeration, meaning we will always get AutoPlay as the power up.

We could change the values of our power up enumerations like this;

    public enum PowerUp { AutoPlay =1, FastBall = 2, SlowBall = 3, MultiBall = 4, Lasers = 5};

This would mean that the un-initialised variable powerUpType would equal 0, and therefore not match one of our power-ups. For clarity you could also specifically set it;

    private PowerUp powerUpType = 0;

We would then however need to handle that scenario in our HandleHits() method, changing this;

        // determine if brick was power-up
        if(powerUpType != null)    // could use if(powerUpType) as short-hand 

to this;

        // determine if brick was power-up
        if(powerUpType > 0)    // not the default integer value of 0 (zero)  

This requires only the smallest of changes to your existing code, but does mean that you will need to consciously set the value of each power-up in the enumeration.


The second way would be to include an item in the enumeration which is used to indicate the brick is not a power-up, for example;

    public enum PowerUp { None, AutoPlay, FastBall, SlowBall, MultiBall, Lasers};

Again, because it is integer based under the hood, None = 0, AutoPlay = 1, FastBall = 2 etc

You now do not need to set the values in the enumeration - BUT - you do need to ensure that None is the first in the list.

You still also need to update the HandleHits() method, this time however you could use the enumeration to make it nicer to read, for example;

        // determine if brick was power-up
        if(powerUpType > PowerUp.None)    // not the default integer value of 0 (zero)  

It exactly the same as using the value of 0 (zero) but is more consistant with the following code.


Any problems let me know - happy to help :slight_smile:







The following is a quick test I put together to demonstrate the output for you;

using UnityEngine;

public class Test : MonoBehaviour
{

    // power-ip enumeration
    public enum PowerUp { None, AutoPlay, FastBall, SlowBall, MultiBall, Lasers };

    // initialised member variable
    private PowerUp powerUpType = PowerUp.None;
    // private PowerUp powerUpType; // this would work also

    // Use this for initialization
    void Start()
    {
        // output member variable before setting the power-up
        Debug.Log(powerUpType.ToString());

        // set the power-up
        powerUpType = PowerUp.AutoPlay;

        // output member variable after setting the power-up
        Debug.Log(powerUpType.ToString());
    }
}

Console

1 Like

I am really thankful that you help me…
I am sorry of being late, and not check that its solved…
finally the code is fine, but there is an error

(Object reference not set to an instance of an object)
and its pointing to the
Paddle.cs --> AutoPlay function --> Vector3 ballPos = ball.transform.position;

I tried to connect objects to the script but nothing’s happening…

Hi,

Ok, so this indicates that something hasn’t been initialised. Can you post your current version of the Paddle.cs script here alone with a screenshot showing the Paddle selected in the Hierarchy with it’s details expanded and visible in the Inspector please.

1 Like

HI! :grin:

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

public class Paddle : MonoBehaviour {
    
    public bool autoPlay = false;
    public float minX, maxX;

    public Ball ball;

    

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


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

    }

   public void AutoPlay() {
        Vector3 paddlePos = new Vector3(0.5f, this.transform.position.y, 0f);
        Vector3 ballPos = ball.transform.position;//<---- here is the error pointing
        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;

    }


}

Do you have a ball in the scene?

If so, can you .zip the whole project up and uploaded it here or share a link to DropBox / GoogleDrive etc so that I can grab it and take a look.

Ta

1 Like

You are a god sent!
https://drive.google.com/open?id=0B8s3pCnw8Pd5MUcxUUZMR0NtVGc

Ok, I can see what is happening now, there’s two things that need to happen.


Something I missed is that you will need to set the autoPlay bool in your Paddle script as static. (I will explain why below)

    public static bool autoPlay = false;

In your HandleHits() method you are actually calling the AutoPlay() method on the Paddle object, instead, set the autoPlay bool to true, e.g.; (again I will explain why below)

(excerpt from your code);

            if (powerUpType > PowerUp.None )
                    {
                Debug.Log("lol");
                switch (powerUpType)
                {
                    case PowerUp.AutoPlayy:
                        Debug.Log("yeshhh");
                        //paddle.AutoPlay();
                        Paddle.autoPlay = true;  // set the autoPlay bool to true and let the existing code manage the rest
                        break;
                    default:
                        Debug.Log("PowerUp Active : One I have an ENUM for but no logic to catch");
                        break;

                }

Explanations…

You need to set the autoPlay bool as static so that it’s value of true or false is held against the type (the class) rather than the instance of the paddle. The reason for this is because in your Brick class you getting an instance of the paddle, even if we set the autoPlay to true, because the brick is then destroyed, the instance of the paddle is also destroyed. By setting the autoPlay bool as static it will persist.

If you call the AutoPlay() method, as you were, you will only call it once. If you check the Update() method on the Paddle script you will see that the decision to play via mouse control or autoplay is checked every frame. At the very best, even without the other issue above, you would have only autoplayed for one frame. :slight_smile:

One thing to be aware of in the HandleHits() method, you need to make sure that you set the autoPlay bool to true on the type, not the instance. Your instance is “paddle”, the type is “Paddle”, so ensure that line starts with a capital P, see image below highlight in red.

1 Like

You cant imagine how much i appreciate you helping me sir…
I now get why we use static,and I finally understand the the type and the instance, and its so simple!
Thank you again :slight_smile:

1 Like

You are more than welcome :slight_smile:

I hope you enjoy making the rest of your game.

1 Like

Privacy & Terms