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:
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 Gamefirst.
Our 2D Arkanoid Tutorial will use Unity 5.0.0f4. Newer versions should work fine as well, older versions may or may not work. The free version of Unity 5 now comes with all the engine features, which makes it the recommended version.
Let's make a game! We will start Unity and select New Project:
We will name it arkanoid, select any location like C:\, select 2D and click Create Project:
Now we can adjust the Camera to our needs. At first we select theMain 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 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 Assetsfolder 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) 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 theHierarchy in order to make it part of the game world:
So far, so good.
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 Renderercomponent in the Inspector:
Let's select Add Sorting Layer.. from the Sorting Layer list, then add aBackground 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 newBackground Sorting Layer to it:
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'sAssets/Sprites folder.
We will use the same Import Settings that we used before:
Now we can drag the borders from the Project Area into theHierarchy and then position them in the Scene so that they are outside of the hexagon image:
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).
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'sAssets/Sprites folder.
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 Hierarchyand position it on the bottom of our game:
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. ARigidbody 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 can modify the Rigidbody 2D to disable Gravity (otherwise the racket would fall out of the game) and make it always have a Fixed Angle (so that it never rotates):
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 select CSharp for the language:
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. 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 60 times per second.
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 stuff (our racket has a RigidBody and a Collider, which makes it Physics stuff).
We can remove the Start and Update functions and create aFixedUpdate 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 theright/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 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:
It's time to add the Ball. Like before, we will begin by drawing some kind of ball imagine:
We will use the following Import Settings for the ball image:
Afterwards we can drag the ball from the Project Area into theHierarchy in order to add it to our game world. We will position it slightly above the racket:
The ball should be part of the physics world, so let's select it in theHierarchy 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 Materialto 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->Physics2D Material 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 theMaterial slot of the Ball's Collider:
Now the ball will bounce off when it hits a wall.
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 theInspector.
A few Rigidbody modifications are required:
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 CSharp for the language. 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 upwardsby 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:
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.
It's time for some blocks. After all, Arkanoid is boring without something to destroy.
We will use the following images for our blocks:
Note: right click each image, select Save As... and save them all in the project'sAssets/Sprites folder.
Let's select the red block image in our Project Area and then use theseImport Settings in the Inspector:
Like before, we can now drag it from the Project Area into theHierarchy 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 selectAdd 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 selectCSharp for the language. We will move it into our Scripts folder again 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:
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:
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!