Sie sind auf Seite 1von 24

How to Create Pong in Unity

Introduction
Within this tutorial you will be shown how to make a game of pong by using Unity. There will be
a step-by-step outline so that everyone can learn and understand how this all works.
List of Materials
PC
Software similar to Microsoft Paint
Unity (I will be using unity 5.0)
Instructions
Open up unity and select create new project.

Name the project, and place the project wherever you want, however make sure you select 2D.
Afterwards hit create project.

Now lets make the assets.


Make sure you have a piece of software that is similar Microsoft paint, gimp, or Photoshop (For
this tutorial I will be using gimp found on gimp.org)

Size the background so that the background is thin but tall, this will be your two paddles (If need
be you can resize within unity). Note: You can design the paddles however you want, and if you
want to design the second players paddle differently then go ahead.

Export this image as a png, the name for the image should look something like this paddle.png. Make sure
that you place this in your assests folder found inside your games main folder, in my case this the assests
folder was found inside Pong Tutorial, and if you want, for organizational purposes, create another folder
within assests called textures.

Hit export again.

Do the same for the walls and the ball.


When youve completed the above steps go back into unity. You should see something like this.

Now were going to set everything up. Go ahead and organize the board however you want.
Dont be afraid to resize anything here, including the camera which controls what, and how
much of what, the player can see. Heres what mine looks like:

Here you can


resize any object
you want.
Right click an object in the hierarchy
and select rename to rename.

When you click on an object you will notice to the right an inspector. Here you will notice a tab
called transform in which holds scale. This will allow you to resize any of your objects however
you see fit.
Another thing you will be able to do is change the position of everything in the hierarchy by
clicking on an object and dragging it around.
And the final thing you may want to do here is change the background color of the game. It is
currently set as blue, you can change this to anything you want but Im going to change it to
black as it allows the white to show better. You have to have the main camera selected for this to
work.

Double click here to


change the color.

At this point youve gotten pretty far, youve managed to setup your first scene. This is a good
point to save by hitting ctrl and s on your keyboard. Afterwards youll want to name the scene
and hit save.

Now you need to add components to each object, we will start with the walls.
Select all four walls by holding ctrl and clicking on all the objects within the hierarchy

Next youre going to want to go to the inspector located on the right of the screen and click add
component.
Once youve clicked add component click on Physics 2D.

Locate box collider and click on it. This will create a collider around each of the walls so that we
can later on calculate the score, reset everything, have the ball bounce off of the top and bottom
wall, and make it so that the paddles dont move past the walls

Alright, now that you have all of the walls setup with colliders lets move on to the paddles.
Yet again select both paddles by holding the ctrl key and clicking on both of them, then give the
two a box collider 2D.
Now, with the two paddles still selected, click on component and go to physics 2D again, and
give the paddles a rigidbody 2D.

Now that you have the rigidbody 2D setup for the paddles youre going to want to check fixed
angles and then set gravity to 0 so that the paddle doesnt fall.
Finally, select the ball, give it a circle collider 2d found in component then physics 2D, and give
the ball a rigidbody2D. Within the rigidbody 2D component, check fixed angles, set the gravity
to 0, and set mass to .001. (Note: The reason the mass is set to such a small number is so that
when the ball hits either of the paddles, the paddles dont move.)
You have just finished setting everything up, the next part of this project is the scripts. The first thing Im
going to do is add a new folder within the assests file, you can do this by right clicking on the assests box,
hovering over create, and clicking on folder, Im going to name this Scripts.

If you choose to create a scripts folder then go inside of it, otherwise you can stay inside of assests.
Now youre going to want to create a new C# Script, you do this by right clicking in the assests segment
of the window, hovering over create, and clicking on C# Script. Create 4 scripts, one for paddle
movement, one for the ball script, one for player 1s score, and the last one for player 2s score. (Note:

You can name these whatever you like.)

Open up all four of the scripts by double clicking everything, we are going to start with making the
paddles move.

Delete everything inside of the public class so that your code looks somewhat like this:
using UnityEngine;
using System.Collections;
public class PaddleMovment : MonoBehaviour {
}
Now, inside of the public class you are going to insert these lines of code (Note: I got these lines
of code from http://noobtuts.com/unity/2d-pong-game):
public float speed = 30;
public string axis = "Vertical";
void FixedUpdate () {
float v = Input.GetAxisRaw(axis);
GetComponent<Rigidbody2D>().velocity = new Vector2(0, v) * speed;
}
The code should now look like this (Note: the comments found within will explain what each
line of code does):
using UnityEngine;
using System.Collections;

public class PaddleMovment : MonoBehaviour {


// This sets the paddles movement speed
public float speed = 30;
// This allows the user to rename the axis of which is being used
// Without this both paddles would be controlled by the same keys
public string axis = "Vertical";
// FixedUpdate is usually used instead of update with physics
// This is used so that the code within can be called at regular intervals
void FixedUpdate () {
// This line of code checks to see whether the button you pressed
// returns a positive output, or a negative output. This is used in the
// below calculations
float v = Input.GetAxisRaw(axis);
// This moves the paddle and inputs the button check, if the button
// returns a positive output then the paddle will move up, and vis-versa
GetComponent<Rigidbody2D>().velocity = new Vector2(0, v) * speed;
}
}
Now we have to add the script components to the two paddles. We do this by dragging our script
up to each separate paddle and releasing (Note: You can also do this by going through
component then clicking on scripts and choosing the script name you want to add).

Click here to run

Alright, try running the program by clicking on the triangle found in the top center of unity. As
you hold down on either the w and s keys, or the up and down arrow keys, youll notice that both
paddles move in unison. This is because we have to differentiate the two axiss we chose to use.
First youre going to want to click on edit, hover over project settings, and then click on input.
You may have to click on axis to show everything.

Click here

Now expand both of the tabs called vertical, and make each one look similar to what I have in
the picture below.

Finally, to get the paddles to move separately all you have to do is go into player 2s paddle,
navigate to the paddle movement script you wrote, and rename axis to Vertical2, or whatever you
decided to call the second Vertical.

Now if you run the game again, and did everything right, each paddle should move separately.
Next we are going to work on the script for the ball.
Navigate to the ball script and delete all of the contents so that you are only left with something
like this:
using UnityEngine;
using System.Collections;

public class Ball : MonoBehaviour {


}
What you are going to want to do next is add these lines of code (Note: I got these lines of code
from http://noobtuts.com/unity/2d-pong-game):
public float speed = 30;
void Start() {
// Initial Velocity
GetComponent<Rigidbody2D>().velocity = Vector2.right * speed;
}
void OnCollisionEnter2D(Collision2D col) {
// Note: 'col' holds the collision information. If the
// Ball collided with a racket, then:
// col.gameObject is the racket
// col.transform.position is the racket's position
// col.collider is the racket's collider
// Hit the left Racket?
if (col.gameObject.name == "RacketLeft") {
// Calculate hit Factor
float y = hitFactor(transform.position,
col.transform.position,
col.collider.bounds.size.y);
// Calculate direction, make length=1 via .normalized
Vector2 dir = new Vector2(1, y).normalized;
// Set Velocity with dir * speed
GetComponent<Rigidbody2D>().velocity = dir * speed;
}
// Hit the right Racket?
if (col.gameObject.name == "RacketRight") {
// Calculate hit Factor
float y = hitFactor(transform.position,
col.transform.position,
col.collider.bounds.size.y);
// Calculate direction, make length=1 via .normalized
Vector2 dir = new Vector2(-1, y).normalized;
// Set Velocity with dir * speed
GetComponent<Rigidbody2D>().velocity = dir * speed;
}

}
float hitFactor(Vector2 ballPos, Vector2 racketPos,
float racketHeight) {
// ascii art:
// || 1 <- at the top of the racket
// ||
// || 0 <- at the middle of the racket
// ||
// || -1 <- at the bottom of the racket
return (ballPos.y - racketPos.y) / racketHeight;
}
Youre final product should look like this (Note: The comments explain what the code does):
using UnityEngine;
using System.Collections;
public class Ball : MonoBehaviour {
// This sets the speed of the ball
public float speed = 30;
void Start() {
// This sets the initial velocity and causes the ball to move
GetComponent<Rigidbody2D>().velocity = Vector2.right * speed;
}
void OnCollisionEnter2D(Collision2D col) {
// I didnt type the next 5 comments
// Note: 'col' holds the collision information. If the
// Ball collided with a racket, then:
// col.gameObject is the racket
// col.transform.position is the racket's position
// col.collider is the racket's collider
// Hit the left Racket? (Note: Dont forget to rename RacketLeft
// with whatever you named the left paddle, for example, Id rename
// it Player1Paddle)
if (col.gameObject.name == "RacketLeft") {
// This calculates the hit factor, essentially where the ball
// is going to move, up, straight, or down
// transform.position is the current position of the ball
// col.transform.position is the current position of the
// paddle the ball collided with
// col.collider.bounds.size.y is the height of the paddle
// the ball collided with
float y = hitFactor(transform.position,
col.transform.position,

col.collider.bounds.size.y);
// I didnt write the comment below
// Calculate direction, make length=1 via .normalized
Vector2 dir = new Vector2(1, y).normalized;
// This sets the new velocity of the ball and causes the ball
// to move at the new direction based on the paddle it hit
GetComponent<Rigidbody2D>().velocity = dir * speed;
}
// Hit the right Racket? (Note: Dont forget to rename RacketRight
// with whatever you named the right paddle, for example, Id rename
// it Player1Paddle)
if (col.gameObject.name == "RacketRight") {
// This calculates the hit factor, essentially where the ball
// is going to move, up, straight, or down
// transform.position is the current position of the ball
// col.transform.position is the current position of the
// paddle the ball collided with
// col.collider.bounds.size.y is the height of the paddle
// the ball collided with
float y = hitFactor(transform.position,
col.transform.position,
col.collider.bounds.size.y);
// I didnt write the comment below
// Calculate direction, make length=1 via .normalized
Vector2 dir = new Vector2(-1, y).normalized;
// This sets the new velocity of the ball and causes the ball
// to move at the new direction based on the paddle it hit
GetComponent<Rigidbody2D>().velocity = dir * speed;
}
}
// This is the hitFactor method
float hitFactor(Vector2 ballPos, Vector2 racketPos,
float racketHeight) {
// I didnt draw the below ascii art
// ascii art:
// || 1 <- at the top of the racket
// ||
// || 0 <- at the middle of the racket
// ||
// || -1 <- at the bottom of the racket

// The math below is checking the balls y position,


// the paddles y position, and then subtracting the two.
// This is used to check whether the ball is move up,
// straight, or down. Then this number is divided by
// the paddles height. This is to make sure that the number
// outputted isnt greater than 1, or less than -1.
return (ballPos.y - racketPos.y) / racketHeight;
}
}
Now if you save this and implement the script to the ball in the game (Note: This is done the
same way you added the script to the paddles) the ball should move and bounce around.
The next thing we want to do is make it so that the ball can keep the score, and so that
everything, except score, resets when the ball hits the left and the right walls. (Note: The new
code from this part was my own work)
For score, add these lines of code under public float speed = 30f;
private int player1Score = 0;
private int player2Score = 0;
// Add this if you plan on later on increasing the balls speed as the game goes on
private float initialSpeed = 30;
Next, youre going to want to add this code somewhere inside of the OnCollisionEnter2D
method:
// Hit the left wall?
if(col.gameObject.name == "LeftWall"){
// This will increment player 2's score
player2Score++;
// This will reset the balls position
transform.position = new Vector2(0f, 0f);
// This will reset the paddles position
GameObject.Find("Player1Paddle").transform.position = new Vector2(15.82f, 0f);
GameObject.Find("Player2Paddle").transform.position = new
Vector2(15.82f, 0f);
// This will cause the ball to move again after the field reset completes.
GetComponent<Rigidbody2D>().velocity = Vector2.right * speed;
// Just in case you later on plan on increasing the balls speed over time
// This will reset the balls speed

speed = initialSpeed;
}
// Hit the right wall?
if(col.gameObject.name == "RightWall"){
// This will increment player 1's score
player1Score++;
// This will reset the balls position
transform.position = new Vector2(0f, 0f);
// This will reset the paddles position
GameObject.Find("Player1Paddle").transform.position = new Vector2(15.82f, 0f);
GameObject.Find("Player2Paddle").transform.position = new
Vector2(15.82f, 0f);
// This will cause the ball to move again after the field reset completes.
GetComponent<Rigidbody2D>().velocity = Vector2.right * speed;
// Just in case you later on plan on increasing the balls speed over time
// This will reset the balls speed
speed = initialSpeed;
}
Since we set the two players scores to private were going to need to write get methods, the
scores are set to private so that the players cannot simply change their scores. We are making
these get methods so that we can display the players current score on the screen.
public intgetPlayer1Score(){
return player1Score;
}
public int getPlayer2Score(){
return player2Score;
}
Your final ball script should look something like this:
using UnityEngine;
using System.Collections;
public class Ball : MonoBehaviour {
public float speed = 30;
// Add this if you plan on later on increasing the balls speed as the game goes on
private float initialSpeed = 30;
private int player1Score = 0;

private int player2Score = 0;


void Start() {
// Initial Velocity
GetComponent<Rigidbody2D>().velocity = Vector2.right * speed;
}
void OnCollisionEnter2D(Collision2D col) {
// Note: 'col' holds the collision information. If the
// Ball collided with a racket, then:
// col.gameObject is the racket
// col.transform.position is the racket's position
// col.collider is the racket's collider
// Hit the left wall?
if(col.gameObject.name == "LeftWall"){
// This will increment player 2's score
player2Score++;
// This will reset the balls position
transform.position = new Vector2(0f, 0f);
// This will reset the paddles position
GameObject.Find("Player1Paddle").transform.position = new Vector2(15.82f, 0f);
GameObject.Find("Player2Paddle").transform.position = new
Vector2(15.82f, 0f);
// This will cause the ball to move again after the field reset completes.
GetComponent<Rigidbody2D>().velocity = Vector2.right * speed;
// Just in case you later on plan on increasing the balls speed over time
// This will reset the balls speed
speed = initialSpeed;
}
// Hit the right wall?
if(col.gameObject.name == "RightWall"){
// This will increment player 1's score
player1Score++;
// This will reset the balls position
transform.position = new Vector2(0f, 0f);
// This will reset the paddles position
GameObject.Find("Player1Paddle").transform.position = new Vector2(15.82f, 0f);

GameObject.Find("Player2Paddle").transform.position = new
Vector2(15.82f, 0f);
// This will cause the ball to move again after the field reset completes.
GetComponent<Rigidbody2D>().velocity = Vector2.right * speed;
// Just in case you later on plan on increasing the balls speed over time
// This will reset the balls speed
speed = initialSpeed;
}
// Hit the left Racket?
if (col.gameObject.name == "Player1Paddle") {
// Calculate hit Factor
float y = hitFactor(transform.position,
col.transform.position,
col.collider.bounds.size.y);
// Calculate direction, make length=1 via .normalized
Vector2 dir = new Vector2(1, y).normalized;
// Set Velocity with dir * speed
GetComponent<Rigidbody2D>().velocity = dir * speed;
}
// Hit the right Racket?
if (col.gameObject.name == "Player2Paddle") {
// Calculate hit Factor
float y = hitFactor(transform.position,
col.transform.position,
col.collider.bounds.size.y);
// Calculate direction, make length=1 via .normalized
Vector2 dir = new Vector2(-1, y).normalized;
// Set Velocity with dir * speed
GetComponent<Rigidbody2D>().velocity = dir * speed;
}
}
float hitFactor(Vector2 ballPos, Vector2 racketPos,
float racketHeight) {
// ascii art:
// || 1 <- at the top of the racket
// ||
// || 0 <- at the middle of the racket
// ||

// || -1 <- at the bottom of the racket


return (ballPos.y - racketPos.y) / racketHeight;
}
public int getPlayer1Score(){
return player1Score;
}
public int getPlayer2Score(){
return player2Score;
}
}
Now we are going to write the player1Score and player2Score scripts, I also wrote both of these
scripts.
player1Scores script should look something like this, player2Scores script will look exactly like
this, except youll have to replace all of the 1s with 2s:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class Player1Score : MonoBehaviour {
public Ball ball;
// Reveals Score
private Text p1S;
void Awake(){
// sets ps1 textbox as p1S
p1S = GetComponent<Text>();
}
// Update is called once per frame
void Update () {
// Reveals player 1's score
p1S.text = "Player 1's Score: " + ball.getPlayer1Score();
}
}
Now back into unity, were going to create the text boxes, but first were going to have to create
a canvas. To do this you go to the gameobject tab, hover over ui, and click on canvas.

When you create the canvas youll also have created an eventsystem, just delete that in the
hierarchy.
Next what youre going to want to do is create 2 textboxes, you do this in gameobject, ui, text.

Rename the textboxes to whatever you want, Im going to rename them to Player1Score and
Player2Score. Once youve done this add the player1Score script to the text box you dedicated to
player 1, and add the player2Score script to the text box you dedicated to player 2.

Next youre going to want to click on canvas, and change the render mode to screen space
camera.

Once you do this youll have to drag the main camera to the render camera.

Drag it here

Afterwards click on the first textbox you made and reposition it to 0, 0. After you do this you can
drag it to wherever you want it to be located, do the same for the second textbox.

Set us to 0

Now you just need to drag ball into ball for the two scripts located in both of the
textboxes.

This is what it will end up looking like.

The last thing you may need to do would be to change the color of the text in each of the
textboxes, you may not need to do this!
You can change the textbox colors by double clicking here:

Double click me to change the text color

And now you have a working pong game.


Congrats!
Troubleshooting
If you run into any errors the first thing you should probably do is look over your code, and look
over your hierarchy and make sure everything is named properly. If this doesnt fix the issue then
you may have copied something wrong, come back here and make sure that everything you
copied is the same as what you can find here, or if youre feeling daring try to find and fix the
issue yourself.
Warning/cautions
This program may be riddled with bugs and errors, and in some parts you may have failed to
read or copy something properly. If you find any errors that prohibit you from doing anything
from moving the paddles to having a ball that can bounce the first thing you may want to do is
look over the code I posted here again and make sure that you didnt forget anything, it may also
be good to note that you may have named things differently from me. If you did this youll
NEED to edit the code to match these changes, failure to do so WILL cause some functions to
fail.

Das könnte Ihnen auch gefallen