Recreating Pong with Unity -Part 1
A simple tutorial on re-creating a classic game with Unity
This is part 1 of a series of posts in which I will talk about recreating the classic game Pong with Unity. I undertook this project mainly to learn Unity’s basics and to start creating a portfolio of simple games. More games of the same kind will come in the future, so if you are interested stay tuned.
For now, however, let’s stay focused on the task at hand. The first thing we need to do is to set our goal. Let’s then take a look a the original game from 1972 , which you can see in the video below:
For our project we will just use this a basis and develop some things differently, but it’s good to keep the basic gameplay in mind.
Before we begin, don’t forget that, should you have any trouble or get lost, you can always check the full project on github at https://github.com/avalcepina/unity-pong.
Setting up the playing field
Let’s get started by creating a new Unity 3D project. Although it would be possible to make this game in 2D, I decided to do it in 3D for learning purposes. Maybe in the future I can think about remaking it in 2D.
The first step will be defining the boundaries for our play field. We can do that by creating 4 walls, using quads. You can position the walls wherever you want, but the coordinates I used were 0, 0, 9 and 0, 0, -9, for the top and bottom walls, and 20, 0, 0 and -20, 0, 0 for the left and right walls. Let’s add a rigidbody to these walls and set each one to kinematic with continuous collision detection. This is necessary due to the speed the ball will be able to reach, which can sometimes allow it to pass through the walls if we don’t take this precaution.
Let’s now position the main camera so that it looks at our playing field. Personally I set it to 0, 40, 0 with a field of view equal to 35, but feel free to use different values if you like them better.
Your project should now look like this:
Creating the ball
It’s now time to work on our ball.
Before anything else we need to create a physic material that will help us control the bounciness of the ball. Let’s do that in a Materials folder. The new material should have the following values.
This will strip away any friction from the material and make it bounce without losing any energy.
Now create a sphere and take care of resetting it so that it sits at the center of the screen. Add a rigidbody to it and, under constraints, freeze all rotations and the y position, then set the physic material you just created to the collider.
It’s time to define the behaviour of the sphere.
To do that, create a new Scripts folder and, inside it, a new c# script called SphereController that you can then add to your newly created sphere.
Open the SphereController script with your editor (I use visual studio code, but anything is fine) and replace the sample code with the following snippet to get the ball moving.
Set the thrust value on the script component to 600 and, when you hit play, you will see your ball moving and bouncing off walls.
Now create a Prefabs folder and save your ball as a new prefab.
We are doing this because, later on (in the next post), we want to be able to destroy and create balls as needed.
Creating the paddles
Now we need to create two paddles.
Let’s think about what exactly we need.
We need to be able to have one paddle be controlled by some sort of AI, while the other one will be player controlled. Also paddles will be parallel to the left and right walls and should only be able to move up and down.
Let’s create a cube and resize it so that it has the shape of a paddle. In my case I set the scale to 0.6, -0.2, 3.8. Let’s also add the physic material we previously created.
Now add a rigidbody to it and
If you implemented the previous step you should have noticed that the way the ball bounces is a bit TOO realistic, meaning that if the ball hits a wall, or a pad, perpendicularly the reflection angle will be the same, causing the ball never to stray from the normal.
Now, that’s just not acceptable.
To deal with this issue, we could just have the ball start with a random angel, making it unlikely that it will get stuck, but where would the fun be in that?
We can instead solve this by applying the script below to the paddle.
This script will apply a new force to the ball when it hits the paddle, modifying the bounce direction slightly. The force will be directed upwards if the ball hits the paddle above the midpoint and downwards otherwise. This will also give some degree of control to the player or the AI.
As a side effect, that I think improves the gameplay, a player will be able to speed up or slow down the ball by correctly positioning the paddle.
If you hit play you should be able to verify this behaviour.
If everything is working correctly, let’s save the paddle to a prefab.
Paddle controllers
As we previously said, for our game, we need one player controlled and one ai controlled paddle.
So let’s create two prefab variants from our paddle prefab.
We will add the following script to the first, making it the player paddle.
And this other one to the second, making it the ai paddle.
As you can probably tell, the first script is allowing the player to move the pad up and down with the directional arrows.
The second script, on the other hand, is a bit more complex.
The base rule in defining the AI behaviour is that we want to try and constantly match the ball z coordinate. It is probably not the most efficient way to assure that we will catch the ball, but it’s pretty effective nonetheless.
So effective, in fact, that we want to tune it down a bit in order for the player to have fun while playing.
We can achieve that by making three adjustments:
- We allow the paddle to match the ball position only when the ball is past the mid field.
- When the paddle moves, it will move in the same direction for a minimum amount of time, causing it to be slightly imprecise in its movements.
- When the ball is farther away than the mid field, the paddle will move randomly.
Let’s now instantiate the two prefab variants in the scene and position the player paddle at 15, 0, 0 and the ai paddle at -15, 0, 0. Let’s also apply a rotation of 0, 180, 0 to both of them and set the sphere gameobject reference in the EnemyController Script.
When you hit play you should have something like this:
We now have a very basic gameplay, in which the biggest problem is that there’s no victory condition, so the game will continue indefinitely.
That’s not good and we definitely need to take care of it, but this post is already becoming quite long, so let’s stop here for now.
We will continue setting up the game in the next post.
Coming up
In the next post we will conclude the implementation of our version of Pong by adding the following features:
- A starting menu, with a dynamic background showcasing the gameplay
- Victor/loss conditions
- Player score and lives
- A game over screen
For the time being I bid you farewell! I hope you enjoyed this short tutorial and I’m looking forward to see you again very soon!