Breakout: Ball

Unity has already enabled us to easily accomplish a ton of milestones, such as rendering sprites on screen, and making objects move and collide with each other. At some point, you will always find that some of the features you want to use require the use of a script. In this lesson we will create our first script and show how it is used like a custom Component. We will use the script to control some of the behavior of our Ball.

Continue following along with your existing “Breakout” project. Otherwise, you can start from this sample project here.

Create A Script

In the Project window, right-click on the “Scripts” folder. In the pop-up, choose “Create -> C# Script”.

Create a C# Script

The script will be created and its name will be highlighted so that you can give it a name. Name the script “Ball”.

Tip:
Make sure to rename the script immediately, or the code within the file will use the wrong name – “NewBehaviourScript”. If your class name and file name do not match, you wont be able to add the script as a Component.

 

Right-click on the Script, and choose “Open” to open your script for editing. If your script was created and named correctly, the code template will look like this:

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

public class Ball : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

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

Replace the contents of the script to this:

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

public class Ball : MonoBehaviour
{
    [SerializeField] float speed = 3;

    // Start is called before the first frame update
    void Start()
    {
        var rb = GetComponent<Rigidbody2D>();
        rb.velocity = Vector2.one.normalized * speed;
    }
}

Save your script.

About the Script

If you are completely new to Programming, there will be a lot to learn. For now we will just take a few baby-steps. If you already know C# feel free to skip ahead to the next section.

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

These first three lines are called “using” statements. Occasionally you might need to add another “using” statement, but often times, the ones included by default are enough. “Using” statements provide “context” with which the computer will understand the words that are typed in. Even humans need “context” to know how to interpret words they hear. For example, if I spoke “see”, “sea”, or “si”, even though they all sound the same, they mean different things. One refers to what my eyes can do, another to a body of water, and the last means yes in Spanish.

Following the using statements there is an empty line called “white space”. Technically, you can add additional spaces, tabs, and new lines all you want. It makes no difference to the computer. The purpose of white space is to visually group or separate code to make it easier to look at and read.

public class Ball : MonoBehaviour
{
    // ...
}

Next we have a “class definition”. It uses a specific set of words, in a specific order. You can tell the words are special because they appear in special colors.

The “public” keyword allows the script to be used by code outside of this file. The “class” keyword indicates that we are defining something new. For now, think of a class as a custom component that you can add to your game objects.

The word “Ball” is the name of the class, and it must match the name of the script file that we created.

There is a colon followed by the key word “MonoBehaviour”. This means that our class “inherits” from another class named “MonoBehaviour”. Inheritance means that any property or ability that the parent class has, our class will also have.

Tip:
Check out the official documentation for a complete overview of the properties and methods MonoBehaviour provides.

 

A class has a “body” which begins with an open bracket ‘{‘ and ends at a close bracket ‘}’. Anything between these brackets is “inside” the class. Note that there are other bracket pairs inside of the class body. By convention, white space (indentation) is used to help indicate which pairs belong together. It is the outer-most bracket pair which mark the class.

[SerializeField] float speed = 3;

This line is called a “field”, it allows instances of our class to hold data. The type of data is called a “float” and it holds numerical values such as ‘3’ or even ‘3.14’. In this example, I provided a default value of ‘3’ though the value held by the field could change over time. The name of the field is “speed” and is how we will refer to the value within the script. By marking the field with ‘[SerializeField]’, we allow Unity to show the field within the Inspector window.

// Start is called before the first frame update

This is called a comment. It begins with the double forward slash ‘//’ and continues until the end of the line. Comments are just notes to the programmer, and the computer will ignore them.

void Start()
{
    // ...
}

This is a “method definition”. A method is a block of code that does something. For example, you could modify data, such as the location of an object.

Like the class, a method also has a special set of words. The first word, “void” is a data type that is returned by the method. Think of it like asking a question and getting an answer. In this case, “void” actually means “nothing”.

Next is the name of the method, “Start”. This is a special method that will be “invoked” automatically by Unity, thanks to the inheritance from MonoBehaviour.

The method definition ends with open and close parenthesis. Some methods will list “parameters” between these parenthesis, which are information that the method may need to do its job. For example a method that knows how to move an object may want a parameter indicating how far to move it. The method here does not accept any parameters.

A method also has a body made of open and close braces just like our class did.

var rb = GetComponent<Rigidbody2D>();
rb.velocity = Vector2.one.normalized * speed;

Inside the Start method, we provided two “statements”. On the first added line, we create a locally scoped variable. This is sort of like the field we added earlier, except it only “exists” inside this method. The name of the variable is “rb” which is an abbreviation for RigidBody. We assign the variable a reference to the Rigidbody2D Component that exists on the same object as the Ball Script. We were able to obtain that by using the “GetComponent” method.

On the second added line, we modify some data of the RigidBody. It held a data type of “Vector2” named “velocity” which indicates the speed and direction that the object should move. We assign to it a new Vector2 that moves equally fast in the positive X and Y axis, at a speed which is controlled by our script’s field.

Attach The Script

Return to Unity. Select the “Ball” in the Hierarchy window. Then at the bottom of the Inspector window, click the “Add Component” button. Type “Ball” into the search field, and select your script when you see it.

Add Ball Script as a component

If everything has gone correctly so far, you should now see your script as a Component on your “Ball” GameObject, and you should see an editable field named “Speed”.

Ball Script added

Press Play and you can watch that the Ball now has some initial velocity – it moves a little bit up and to the right before gravity starts pulling it back down. It is more interesting, but it doesn’t match the look of a Breakout ball just yet.

Stop the simulation. Next look in the Inspector window of the “Ball”‘s Rigidbody 2D. Set “Gravity Scale” to 0.

Set Gravity Scale

Play once again and note how the ball will just continue moving in whatever direction it was going, until it bounces off whatever it collides with. Much better!

Extra Polish

The ball is a bit large, and is not located in an ideal starting location. Let’s adjust it so that it starts at “Position” X: 0, Y: -4.25, Z: 0, and with Scale of X: 0.2, Y: 0.2, Z: 0.2.

Starting position and scale

In order to help the user keep track of the ball, we can add a Trail Renderer. Right-click the “Ball” in the Hierarchy window. From the pop-up choose “Effects -> Trail”.

Add a trail

In the Inspector for the Trail Renderer, drag the first keyframe down to about 0.2. Then double click to add another keyframe, positioned at 1 on the horizontal axis and at 0 on the vertical axis. This causes the trail to start out about the same size as the ball and taper off to a small point.

Trail width

Set the “Time” to 0.25.

Set the Color gradient so that it ramps the alpha down from 100 to 0.

Trail color

Play the scene once again, and look how the trail follows behind the Ball making it easier to keep track of.

Summary

In this lesson, we created our first script, which we used to set the initial velocity of our Ball. We introduced a lot of new programming terms like class, field, method, statement, and inheritance. Then we further updated the ball so it was a better size, ignores gravity, and includes a trail renderer.

If you’d like you can also download the completed project for this lesson here.

If you find value in my blog, you can support its continued development by becoming my patron. Visit my Patreon page here. Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *