Unity 2D Arkanoid Tutorial

Foreword

Let's make an Arkanoid clone with only 37 lines of code! The original Arkanoid was released a long time ago in 1986, but is still highly addictive and thanks to its arcade style nature it's very easy to develop in Unity.

As usual, everything will be explained as easy as possible so everyone can understand it.

Here is a preview of the final game:



Requirements

Knowledge

This is a beginner Tutorial where no advanced skills are required. Only the Unity basics are somewhat useful to know. If you don't know the Unity basics, feel free to either try and see how far you get or read one of our easier Unity Tutorials like Unity 2D Pong Game first.

Unity Version

Our 2D Arkanoid Tutorial will use Unity 2018.3.14f1. Newer versions should work fine as well, however please note that older versions of Unity may not work as described in this tutorial. For best results, keep to the 2018.3 versions.

If you have not already installed Unity 2018.3 via the Unity Hub, please follow the About the Unity Engine portion of the 2D Pong Game guide and return after installing Unity Hub and Unity 2018.3.

Project Initialization

Note: The screenshots shown in the Unity Hub are from 2.x version. Older versions will look different, but it is mostly the same. Some elements in older versions are drop-down menus instead of the new visual layout.

Let's make a game! We will start the Unity Hub and select New Project:



We will name it arkanoid, select any location like C:\GameDev, select 2D and click Create Project:



Note: It is always recommended to make sure you have write access to your project's folder. Due to system protection (and/or restrictions) Windows will sometimes cause refuse to create folders in your hard disk root folder causing Unity to throw Access Denied errors. If you get such an error, try a different folder - for example, C:\Users\YourUserName\GameDev usually works, or a folder on a dedicated disk drive.

It is not recommended to put the Unity Project in a folder that will be backed up to the cloud as that can cause unexpected errors during development (such as locked files and other random errors)!

Project Setup

Now we can adjust the Camera to our needs. At first we select the Main Camera GameObject in the Hierarchy, afterwards we adjust the Background Color to something dark and modify the Size like shown in the following image:



Note: the size is pretty much the zoom factor of the camera. We modified it so the overall game will look just about right later on.

The Hexagon Background Pattern

The original Arkanoid game uses a blue hexagon pattern as background. We can create a similar pattern with our drawing tool of choice:



Note: right click on the image, select Save As..., navigate to the project's Assets folder and save it in a new Sprites folder.

Let's select the Hexagon Pattern Image in the Project Area:



And then modify the Import Settings in the Inspector:



Note: this tells Unity how to load the image, which compression to use (none in our case), use Point filtering (this avoids weirdness) and how big it should be in the final game (exact same size in our case).

Now we can drag the Hexagon Image from the Project Area into the Hierarchy in order to make it part of the game world:



Note: Make sure the Hexagon Pattern is not part of the Main Camera. Try to drag and drop it into a empty part of the Inspector.

So far, so good, but we're not done yet. Get ready for the next mission!

The Sorting Layer

We are making a 2D game and there will be situations where several images are drawn on top of each other, for example when the ball and the hexagon pattern are both drawn.

Let's tell Unity that our hexagon pattern is supposed to be in the background to make sure that the ball is always drawn on top of it (hence visible).

We can use a Sorting Layer for this. We can change the hexagon pattern's Sorting Layer if we take a look at the Sprite Renderer component in the Inspector:



Let's select Add Sorting Layer.. from the Sorting Layer list, then add a Background layer and move it to the first position like shown below:



Note: Unity draws the layers from top to bottom, hence whatever should be in the background will be at the top of the list.

Now we can select the hexagon pattern again and assign our new Background Sorting Layer to it:



Save your work. A good game developer will regularly save their work to prevent data loss. You can go to File -> Save or press Control + S together (Command + S on Mac OS) to save the scene.

Adding the Borders

The Border Images

We will add borders to make sure that the ball won't just fly out of the game. We will need one image for each border:



Note: right click each image, select Save As... and save them all in the project's Assets/Sprites folder.

Border ImportSettings

We will use the same Import Settings that we used before:



Now we can drag the borders from the Project Area into the Hierarchy and then position them in the Scene so that they are outside of the hexagon image:



Border Physics

At the moment our borders are only images. In order to make the ball collide with them we will have to add a Collider to each border. We can do this by first selecting them in the Hierarchy:



Afterwards we can take a look over to the Inspector and select Add Component -> Physics 2D -> Box Collider 2D:



Now the borders are part of the physics world. They still look exactly the same, but instead of being just an image they are now physical walls, too (because of the Collider).

The Racket

The Racket Image

Let's create the racket (called Vaus in the original game). The player will be able to move the racket horizontally to prevent the ball from falling out of the game.

As usual we will begin by drawing a racket image:



Note: right click on the image, select Save As... and save it in the project's Assets/Sprites folder.

Importing the Racket

We will use the same Import Settings that we used for all other images in our Arkanoid Tutorial:



Now we can drag the Racket from the Project Area into the Hierarchy and position it on the bottom of our game:



Note: You can also set the Transform XYZ Values directly by using the Position set of values in the Rackets' inspector if you're having trouble aligning it up. A suggested value for those are: X 0, Y -95, Z 0.

Save your work.

Racket Physics

Like before, we do want the racket to be part of the physics world because the ball is supposed to collide with it later on. Let's select the racket in the Hierarchy and then press Add Component -> Physics 2D -> Box Collider 2D in the Inspector:



There are some more physics to do. The player should be able to move the racket to the left and to the right, and everything in the physics world that is supposed to move around will need a Rigidbody. A Rigidbody takes care of all kinds of things like velocity and gravity, but for now it's enough to remember that everything physical that moves through the game world will need a Rigidbody.

We can add a Rigidbody to the racket by selecting Add Component -> Physics 2D -> Rigidbody 2D in the Inspector. Afterwards, we set the following settings:

- Gravity Scale: 0 (prevents the racket from falling out of bounds)

- Collision Detection: Continuous (prevents glitches where the ball might clip through the racket due to Physics 2D engine quirks)

- Freeze Rotation on the Z Axis: this makes the racket freeze its angle. Leaving this unticked can cause the racket to spin on the Z axis when the ball collides with the racket, which can be quite amusing at first but it would soon become very annoying.



Congratulations on making it this far! Don't forget to save your work. We're just over halfway there.

Racket Movement

The player should be able to move the racket horizontally. This kind of feature can be added with Scripting. Let's select Add Component -> New Script in the Inspector, name it Racket and click the "Create and Add" button:



Unity then creates the new Script and automatically adds it to our racket. Let's also take a look at our Project Area and move the Script into a new Scripts folder, just to keep things clean:



Let's open the Script by double clicking it. This should bring up Visual Studio or another code editor if you are on a different platform. Here is how it looks:



using UnityEngine ;

using System.Collections ;



public class Racket : MonoBehaviour {



// Use this for initialization

void Start ( ) {



}



// Update is called once per frame

void Update ( ) {



}

}

Our Start function is automatically called by Unity when starting the game. Our Update function is automatically called over and over again, roughly tied to the game frame rate which is set to 60 by default.

There is yet another type of Update function, it's called FixedUpdate. It's also called over and over again, but in a fixed time interval. Unity's Physics are calculated in the exact same time interval, so it's always a good idea to use FixedUpdate when doing Physics-related calculations, as our Racket is a Physics object (since it has a Rigidbody).

We can remove the Start and Update functions and create a FixedUpdate function now:



using UnityEngine ;

using System.Collections ;



public class Racket : MonoBehaviour {



void FixedUpdate ( ) {



}

}

We will use the Rigidbody's velocity property to make the racket move. The velocity is always the movement direction multiplied by the movement speed. It is of type Vector2, and here are some Vector2 examples:



Let's add a Speed variable to our Script:



using UnityEngine ;

using System.Collections ;



public class Racket : MonoBehaviour {

// Movement Speed

public float speed = 150 ;



void FixedUpdate ( ) {



}

}

The player should be able to move the racket by pressing either the right/left arrow keys, or the A/D keys, or perhaps even a gamepad's stick. We could either check all of those keys manually, or we could use Unity's GetAxisRaw function to get the Horizontal input. It will return -1 for Left, 0 for no direction, also known as netural position and 1 for right:



void FixedUpdate ( ) {

// Get Horizontal Input

float h = Input . GetAxisRaw ( "Horizontal" ) ;

}

Now we can set the velocity to the movement direction multiplied by the speed:



void FixedUpdate ( ) {

// Get Horizontal Input

float h = Input . GetAxisRaw ( "Horizontal" ) ;



// Set Velocity (movement direction * speed)

GetComponent < Rigidbody2D > ( ) . velocity = Vector2 . right * h * speed ;

}

This is all we had to do to make the racket move. If we press play then we can now move the racket:



Let's move on to making the ball move.

The Ball

The Ball Image

It's time to add the Ball. Like before, we will begin by drawing some kind of ball imaginable:

Note: right click on the image, select Save As... and save it in the project's Assets/Sprites folder.

We will use the following Import Settings for the ball image:



Afterwards we can drag the ball from the Project Area into the Hierarchy in order to add it to our game world. We will position it slightly above the racket:



The Ball Collider

The ball should be part of the physics world, so let's select it in the Hierarchy and then press Add Component -> Physics 2D -> Box Collider 2D to add a Collider:



The ball should also bounce off walls. If it flies directly towards a wall then it should bounce off into the opposite direction. If it hits the wall in a 45° angle then it should bounce off in a -45° angle (and so on). The math behind this is rather easy and could be done with a Script, but we will do it the easiest way possible by assigning a Physics Material to the Ball Collider. Physics Materials contain information about the physical aspects of Colliders like Friction and Bounciness.

Let's right click in the Project Area, choose Create -> Physics Material 2D and name it BallMaterial:



Afterwards we can take a look in the Inspector and adjust the material properties in order to make it bounce off:



Now we just have to drag the material from the Project Area into the Material slot of the Ball's Collider:



Now the ball will bounce off when it hits a wall.

The Ball Rigidbody

The ball is already part of the physics world, but everything moving should always have a Rigidbody attached to it. We can add one to our ball by selecting Add Component -> Physics 2D -> Rigidbody 2D in the Inspector.

We'll make the following changes as shown below:



Mass: 0.0001 (this will help prevent the ball from pushing away the racket)

0.0001 (this will help prevent the ball from pushing away the racket) Gravity Scale: 0 (this will prevent the ball from using gravity)

0 (this will prevent the ball from using gravity) Interpolation: Interpolate (in order to make the Physics as exact as possible)

Interpolate (in order to make the Physics as exact as possible) Collision Detection: Continuous (helps prevent collision errors due to Unity Physics 2D engine quirks)



Note: the modifications may look like advanced physics stuff, but no worries. The common way to find out these settings is by testing the game and then modifying the Rigidbody step by step to get the effects that we want.

If we would press Play now then the ball wouldn't move at all, because it has no default velocity. Let's select Add Component -> New Script in the Inspector, name it Ball and select the Create and Add button. We will also move it into our Scripts folder in the Project Area and then open it:



using UnityEngine ;

using System.Collections ;



public class Ball : MonoBehaviour {



// Use this for initialization

void Start ( ) {



}



// Update is called once per frame

void Update ( ) {



}

}

We won't need the Update function, so let's remove it:



using UnityEngine ;

using System.Collections ;



public class Ball : MonoBehaviour {



// Use this for initialization

void Start ( ) {



}

}

Let's use the Rigidbody's velocity property to make it move upwards by a certain speed:



using UnityEngine ;

using System.Collections ;



public class Ball : MonoBehaviour {

// Movement Speed

public float speed = 100 . 0f ;



// Use this for initialization

void Start ( ) {

GetComponent < Rigidbody2D > ( ) . velocity = Vector2 . up * speed ;

}

}

We can press play to see the Ball bounce off the borders:



The Ball Racket Collision Angle

We are getting closer to the finish line already. We will now add a cool game play feature to the ball vs. racket collision. We want the player to be able to have some control about the ball's outgoing angle when it hits the racket:



Let's open the ball script so we can implement the outgoing angle feature. We will use Unity's OnCollisionEnter2D function that is automatically called by Unity whenever the ball collides with something else:

using UnityEngine ;

using System.Collections ;



public class Ball : MonoBehaviour {

// Movement Speed

public float speed = 100 . 0f ;



// Use this for initialization

void Start ( ) {

GetComponent < Rigidbody2D > ( ) . velocity = Vector2 . up * speed ;

}



void OnCollisionEnter2D ( Collision2D col ) {

// This function is called whenever the ball

// collides with something

}

}

We will need some kind of code that calculates the ball's velocity depending on where it hit the racket.

The value of y will always be 1, because we want it to fly towards the top and not towards the bottom. The value of x requires some thought. It will be somewhere between -1 and 1, pretty much like this:



1 -0.5 0 0.5 1 <- x value depending on where it was hit

=================== <- this is the racket

All we really have to do is find out where the ball is, in relation to the racket. We can do so by simply dividing the ball's x coordinate by the racket's width. Here is our function for it:



float hitFactor ( Vector2 ballPos, Vector2 racketPos,

float racketWidth ) {

// ascii art:

//

// 1 -0.5 0 0.5 1 <- x value

// =================== <- racket

//

return ( ballPos . x - racketPos . x ) / racketWidth ;

}

Here is our final OnCollisionEnter2D function:



void OnCollisionEnter2D ( Collision2D col ) {

// Hit the Racket?

if ( col . gameObject . name == "racket" ) {

// Calculate hit Factor

float x = hitFactor ( transform . position ,

col . transform . position ,

col . collider . bounds . size . x ) ;



// Calculate direction, set length to 1

Vector2 dir = new Vector2 ( x, 1 ) . normalized ;



// Set Velocity with dir * speed

GetComponent < Rigidbody2D > ( ) . velocity = dir * speed ;

}

}

If we press play, then we can now influence the ball's bouncing direction depending on where it hit the racket.

Adding Blocks

It's time for some blocks. After all, Arkanoid is boring without something to destroy.

We will use the following images for our blocks:



Blue:

Green:

Pink:

Red:

Yellow:

Note: right click each image, select Save As... and save them all in the project's Assets/Sprites folder.

Let's select the red block image in our Project Area and then use these Import Settings in the Inspector:1



Note: Use the same values as shown here for the Green, Pink, Yellow and Blue block sprites.

Like before, we can now drag it from the Project Area into the Hierarchy and then position it at the top left of our game:



In order for the block to be part of the physics world, we will select Add Component -> Physics 2D -> Box Collider 2D in the Inspector:



We want the block to be destroyed after it was hit by the ball. This kind of behavior is always implemented with a Script. Let's select Add Component -> New Script in the Inspector, name it Block and click the "Create and Add" button. We will move it into our Scripts folder again as shown previously and then open it:



using UnityEngine ;

using System.Collections ;



public class Block : MonoBehaviour {



// Use this for initialization

void Start ( ) {



}



// Update is called once per frame

void Update ( ) {



}

}

using UnityEngine ;

using System.Collections ;



public class Block : MonoBehaviour {



void OnCollisionEnter2D ( Collision2D collisionInfo ) {

// Destroy the whole Block

Destroy ( gameObject ) ;

}

}

Afterwards we can duplicate the block a few times (select it in the Hierarchy and then press Ctrl + D or right click -> Duplicate) and then position the copies somewhere else in the Scene:



We will repeat this process for each of the different block color images in our Project:



Note: we can reuse our Block Script for the other Blocks, too.

And that's it! If we press play then we can enjoy the awesome result of our Unity 2D Arkanoid Tutorial:



Save your work. You don't want your hard work being undone by a sudden Unity crash or some other failure.

Congratulations, you've completed your own 2D Arkanoid Game!

Summary

We just learned how to make a nice little Arkanoid Clone in Unity. We created a project that is fast, clean and state of the art. As usual, now it's up to you to make the game more fun. Here are some improvement ideas:



A collision Sound

More Levels

Undestroyable Blocks

Racket size upgrades

A Score

A Win and Lose Screen

A Menu

Arcade games are just about the best way to learn how to develop a game and how to make it fun. Take your time, play around with it and make it awesome!