Ping Pong 2D - Multiplayer Mac OS

  • Unity is the ultimate game development platform. Use Unity to build high-quality 3D and 2D games, deploy them across mobile, desktop, VR/AR, consoles or the Web, and connect with loyal and enthusiastic players and customers.
  • Tiny Tennis Fun. Table tennis, also known as ping pong, is a game in which two or four players hit a little, light ball back and forth across a table using a small paddle.A point is scored when a player fails to return the ball to the other player. Basically, you’re playing tiny tennis on a table.
  • Play 1 & 2 player pong games online for free, no download: Multiplayer ping pong-like game, Sling, a fun Flash pong arcade game with table tennis style action for kids (boys & girls), teens, brothers and sisters to play now. Pong arrow key games online for PC, Mac, old 80s games, very hard new ball games.
  1. Ping Pong 2d - Multiplayer Mac Os Pro
  2. Free Ping Pong Game Online

Let your computer play a game of Pong against itself when you're away with the Pong Clock screensaver. The current time is displayed in digital format at the top of the screen, in a font matching the simple graphics of the pong game.

By Will Oldham. Updates by Nick Such and Caleb Cornett.

Note, July 2018: Updated for Unity 2018.1

Today, the name of the game is Pong. We’re going to be using Unity 2018.1 or later, and we’ll use C# as our coding language. No prior experience with Unity or C# is required. It will only take you about two hours to complete the tutorial, and at the end you’ll have made your own version of Pong!

Step Zero: The Design

First, let’s think about the pieces and parts of Pong – the individual “mechanics” (the rules and features of the game) that we’ll need to program.

  1. You have a Background to play on

  2. You have a set of Paddles that go up and down

  3. You have a ball that bounces off walls and paddles

  4. You have a set of side walls that you hit to score

  5. You have a score at which you win

  6. You have a reset button so you can play again

Seems simple enough. Let’s get started!

Step One: The Setup

First, download this Unity Pong assets file. It contains images and other assets that we’ll be using in this tutorial.

Now we can start setting up our project! Open Unity and follow these steps:

  1. From the welcome screen, click Projects. (If the Unity editor is already open, click File > New Project instead.)

  2. Click ‘New’. Then you should see something like this:

  3. Name the Project something like ‘Pong Game’.

  4. Make sure you choose the 2D Template.

  5. Set the slider for Enable Unity Analytics to Off.

  6. Click Create Project. And that’s it!

Once the project has been created, you should see a 2D grid appear in the Scene view.

Setting up Unity in 2D mode does several things. First off, it sets up our game camera so that everything is viewed from a 2D perspective. It also tells Unity to import images as Sprites instead of Textures. You’ll see how this helps us in just a bit.

Remember that Unity Pong assets file that we downloaded? Now’s a great time to unzip that file. Once you do, you’ll see a folder called unitypong-assets, which will contain a set of images, fonts, and other assets that we’ll be using today. Select all of these files, then click + drag them into the Project pane at the bottom of your Unity window. It should now look something like this:

Click and drag the Background image from the Project pane into the Hierarchy pane, just below Main Camera. It should appear in your Scene view, and be centered by default. If it’s not centered, use the Inspector pane to set its Transform Position to (0, 0, 0).

Select your Background, now in the Hierarchy pane, and you should see it show up in the Inspector pane like this:

First, up at the top of the Inspector under Transform, change its scale to (0.75, 0.75, 1). This will make it look better in our game. Now look at the Sprite Renderer component. We want to make sure the background actually renders behind our other sprites, and does not accidentally appear on top of them. Go to Sorting Layer, and click Add Sorting Layer. The Inspector pane should now look like this:

Click the + icon to add our new layer. Change its name from ‘New Layer’ to ‘Background’, then click and drag our new layer above the Default layer. This makes it so that anything on the Background sorting layer will appear behind anything on the Default layer, which is exactly what we want.

Now re-select your Background object in the Hierarchy pane so that it will show up in the Inspector again. In the Sprite Renderer component, click the dropdown menu for Sorting Layer and choose our new Background layer. Your Inspector should look like this:

Next, we need to make some changes to the Main Camera so that our game will look nicer.

Select the Main Camera object in your Hierarchy pane. The camera object controls how we see the game world (or “Scene”, in Unity terms). When we’re playing our Pong game, it’s actually possible that our background won’t be big enough to cover the whole screen. We need to make two small changes in our Main Camera to take care of that.

In the Inspector, under the Camera component, change the Size to 3. This will zoom in slightly on our background. Next, click on the Background property of the Camera. This lets us change the color that will be visible on the edges of our screen if the background isn’t big enough. In the color picker, choose the color black, with RGBA values of (0,0,0,0). Then the Camera component in the Inspector should look like this:

All right! Now is a great time to save our progress. Press Ctrl+S (or Cmd+S on macOS) to save the changes made to your current Scene (by default, called SampleScene in the Scenes folder in the Project window).

Step Two: The Paddles

The next step is to make our paddles. Find the image called PongPaddle within your Project pane.

Now click and drag the paddle image onto the scene in the Scene view. A PongPaddle object should appear in your Hierarchy menu.

Click the PongPaddle in the Hierarchy. Over in the Inspector, rename it to Paddle1 and click the Tag dropdown and select Player. (More on this later.) Set Position to (X, Y, Z) = (-4, 0, 0) and Scale to (0.5, 1.5, 1). It should look like this in the Inspector:

All we’re doing here is making sure that the paddle is positioned where we want it. The Sorting Layer and other settings don’t matter this time because we want this object to be drawn on top, which is what Unity defaults to.

Next we’re going to add two components to the Player object. Click on the Add Component button, and then on Physics 2D. Once you’ve done that add both a Box Collider 2D and a Rigidbody 2D. The Box Collider 2D is to make sure the ball will bounce off your paddle, and the Rigidbody 2D is there so we can move the paddle around.

Note: It’s important to use Physics, Box Collider, and Rigidbody 2D here because 3D versions of those exist - that’s not what we want in our 2D game.

Now, we’re going to make a few changes to the Rigidbody 2D component. Unity has a great, realistic physics system built in that calculates the effects of gravity, friction, and other forces on any object that has a Rigidbody 2D component. That system is often very handy, but we don’t want to use it for our paddles. Our paddles aren’t exactly realistic – they’re just kind of floating in space and they only move when we tell them to. Thankfully Unity gives us a way to tell our Rigidbody 2D to only move when we tell it to. We just have to click the Body Type dropdown menu and select Kinematic.

Your Inspector should now look like this:

Now we want to do the hard part: add a Script for movement for our paddles. I’m going to share the code below. I recommend typing each line. It might seem quicker to copy and paste code, but typing it yourself really does help you understand it.

To add a script, make sure that Paddle1 is still selected in your Hierarchy pane, then go to Add Component > New Script. Call this script PlayerControls, then click Create and Add. The script should now appear as a component and in the Project pane.

Double click the script icon to open it up in Visual Studio. (Visual Studio is Unity’s default Integrated Development Environment (or IDE) - essentially, it’s the program we use to write Unity scripts.)

Code Breakdown

In short, the first three lines are packages of pre-written code we want to tell our program it can use.

The next line is the class name, the name of our file. It’s the same thing that we named our Component.

The next few lines are variables we need to write ourselves. The first two lines we add will denote the keys that we’ll press to move the paddles (W goes up, S goes down), and the next one is the speed of the paddle. The boundY variable is the highest position that we want our paddle to go. This keeps it from moving off the edges of the screen. The last variable is a reference to our Rigidbody that we’ll use later.

By making these variables ‘public’, we can adjust them through our Unity interface as well. If we have variables we don’t want other developers to see in the Unity interface, we should call them ‘private’.

Start() is a function that is called when we first launch our game. We’ll use it to do some initial setup, such as setting up our Rigidbody2D:

Update() is a function that is called once per frame. We’ll use it to tell us what button is being pressed, and then move the paddle accordingly, or, if neither button is pressed, keep the paddle still. Lastly we’ll bound the paddle vertically between +boundY and -boundY, which will keep it inside the game screen at all times.

NOTE: Make sure that you name your functions the same thing that I do. For instance, Unity knows to run the Update() function once every frame, because it is called Update(). If you called it anything else (for instance, update() with a lowercase ‘u’ or a misspelling like Updaate()), it will not work. When you’re writing code, you have to be exact or the computer might misunderstand what you want it to do.

Make sure you save your script in Visual Studio. Now, when we go back to Unity, we should have a paddle that moves. To test our game, click the play button (►) at the top of the screen. Use the W and S keys to move. Does it work? Awesome!

Now, it’s important to note something here. You have just entered ‘Play Mode’. This is a really neat feature in Unity that lets you not only test your game but also make changes to it while you’re playing! You’ll know you’re in Play Mode when the editor gets darker and your play button looks like this:

Try clicking the Paddle1 object in the Hierarchy and changing the position of the paddle in the Inspector while the game is running in Play Mode. This is super handy for trying out new ideas in real time. But I have to warn you:

The changes you make during Play Mode do not stay when you close Play Mode.

In other words, always make sure you have stopped Play Mode (by pressing the play button (►) again) before you make significant changes to the game. Otherwise all your recent work will be erased whenever you stop testing the game. Trust me, that’s no fun.

Exit Play Mode, and click on our Paddle1 object. Under the Inspector pane, you should see a place to change the key bindings for up and down, the speed that it moves at, and the bounding value for the paddle’s position. Mess around with those as you please.

The next step is to make a second paddle. All we need to do is right-clickPaddle1 in the Hierarchy menu, and choose Duplicate from the menu that appears when we right click. Rename it to be Paddle2.

Select Paddle2 and change its key bindings (I recommend using ‘Up Arrow’ for up and ‘Down Arrow’ for down), and move it to be the opposite location on the board - change its Transform position to (4, 0, 0). Paddle1 should be on the left, Paddle2 on the right. You should have something that looks like this now:

Run your game and see if you can move both paddles separately. If so, move on - if not, go back and double check to make sure you didn’t miss anything. Your completed C# script should look like this: PlayerControls.cs

Step Three: The Ball

Our Ball will be a little more complicated than the Paddles, but that’s because it has more more to do! It has to bounce around the screen, detect scoring, and interact with paddles.

The first step is going to be finding the Ball image in the Project pane. Click and drag the Ball into the Hierarchy, same as our Paddles. There should now be an object in the Hierarchy pane named Ball. Click on it, then head over to the Inspector pane.

First, we need to add a custom Tag. Tags are Unity’s way of identifying unique game objects, and it’s really simple to use them to find game objects in scripts. At the top of the Inspector, click on Tag > Add Tag... and the Inspector will change to show Tags & Layers. This should look familiar – this is the same window we used earlier to add our Sorting Layer! Except now, we need to click the + icon to add a new Tag. Call it Ball.

Now, click on the Ball object again in the Hierarchy. Go up to the Tag field and select Ball from the dropdown menu. It should look like this:

Change the scale of our ball to (0.5, 0.5, 1). A smaller ball helps make the game feel faster and more fun.

Next we need to add similar components that we did to the paddle. Click the Add Component button, then in Physics 2D, let’s add Circle Collider 2D and of course Rigidbody 2D. In the Circle Collider, change the Radius to 0.23. That way the collider wraps around the ball much tighter.

We also want to apply a Physics 2D Material. Select the BallBounce Material from the Project pane and look at the Inspector. You’ll see the friction value is 0, and the bounce factor is 1. That way our ball doesn’t experience friction from anything, including our paddles and wall. The bounciness factor means that it also doesn’t lose any speed. It bounces back with the exact same speed it hit the object with.

To apply the material, select Ball in the Inspector, then click and drag the BallBounce material to the Circle Collider 2D box. We also need to adjust several settings in Rigidbody 2D so we can get our desired ball behavior. It should look like this at the end:

But of course, to actually get the Ball to move, we need a script. With Ball still selected in your Hierarchy, click Add Component > New Script. This time we’ll call the script BallControl. Double click on the new BallControl script to open it in Visual Studio.

Code Breakdown

First, as always, we import our packages and confirm that our class name matches our filename.

We need to declare a variable that we’ll use later.

We also need a GoBall() function, that will choose a random direction (left or right), then make the ball start to move.

In our Start() function, we’ll initialize our rb2d variable. Then we’ll call the GoBall() function, using Invoke(), which allows us to wait before execution. This will wait two seconds to give players time to get ready before the ball starts moving.

ResetBall() and ResartGame() are two functions used by other scripts which we will write later. ResetBall() is used when a win condition is met. It stops the ball, and resets its position to the center of the board.

RestartGame() is used when our restart button is pushed. We’ll add that button later. This function uses ResetBall() to center the ball on the board. Then it uses Invoke() to wait 1 second, then start the ball moving again.

OnCollisionEnter2D() waits until we collide with a paddle, then adjusts the velocity appropriately using both the speed of the ball and of the paddle.

Let’s recap. We have two paddles that work, and now a ball that bounces around realistically. The completed script we just added should look like this: BallControl.cs. The game should have two paddles and a ball, ready for us to play!

Step Four: The Walls

You may have noticed by now that your ball can fly off the screen. We need to make some walls.

Let’s first make a game object to contain our walls. Make sure nothing is selected in the Hierarchy pane, then right click some empty space in the Hierarchy and choose Create Empty. It will create a plain ol’ empty game object, which we will name Walls. We don’t need to change anything except to make sure that it has a position of (0,0,0).

Now to make an actual wall. In the Hierarchy pane, right click on the Walls object we just made and choose Create Empty. This will make a new game object that is a “child” of the Walls object. For our purposes, having our walls as children of ‘Walls’ will help us keep the hierarchy nice and clear, since we can click the little arrow next to Walls whenever we don’t want to see each individual wall object. The idea of ‘child’ game objects is actually very powerful and does more than just organize things, but we won’t go into it much in this tutorial.

Anyway, call this new child object RightWall. Also make sure you go to Add Component and add a Box Collider 2D. That way the ball will bounce off of the wall object, just like we want!

Now duplicate our new wall object 3 times. Call those duplicates LeftWall, TopWall, and BottomWall. Now we need to move and size those walls so they are in the right spot in our game view - right now, they’re just points sitting in the middle of our board. We need to make them look like walls.

For the RightWall, set its Position to (5.8, 0, 0) and its Scale to (1, 6, 1). This will make it nice and tall. The LeftWall is the same, except its X Position is -5.8. (The numbers might be different on your computer – basically, just make sure your screen looks like the screenshot below, with the walls on the outside edges of each side of the camera view.)

TopWall should be positioned at (0, 3.5, 0) with a scale of (10.7, 1, 1), and BottomWall has the same scale but with a Y Position of -3.5. If you click on the parent ‘Walls’ object, you should now see this in the Scene view:

One cool thing: you can now hit Play (►), and the ball will bounce off the walls! Next comes an important, but slightly harder part. We need to make this an actual game, not just a ball bouncing around. We need a score system, a way to display the score, some win condition, and a reset button. That’s right. It’s time for…

Step Five: The Scoring User Interface

First things first, we need a game object for our HUD (or Heads-Up Display). Right-click an empty space in the Hierarchy pane (not on the Walls game object!) and choose Create Empty. Call the new object HUD, center its position at (0, 0, 0), and add a new script to the HUD object called GameManager.

This is going to be a fairly long script, but it’s really important for our game!

Code Breakdown

First, as always, we import our packages and declare our class.

Next we make four variables. The first two variables are just integers to keep track of the scores for the two players. The next is a GUI object. ‘GUI’ stands for graphical user interface. This object is going to be responsible for displaying all our different buttons and graphics. We’ll make this skin object in Unity after we finish here. The last variable is a reference to our ball object.

Then comes the Start() function, which we use when the game first starts.

Next is the Score() function. It will get called by another script we write in just a minute, that detects when the ball hits the side walls.

The OnGUI() function takes care of displaying the score and the reset button functionality. Then, it checks every time something happens if someone has won yet, and triggers the function ResetBall() if someone has.

The ‘SendMessage’ call is something we’ve been using a lot in this chunk of code - it will trigger any function that matches the name that we send it in a class we specify. So when we say theBall.SendMessage('ResetBall'), we tell the program to access the ‘BallControl’ class and trigger the ResetBall() method. Here’s the completed script: GameManager.cs

Ok cool. Looking at the HUD, we now see there’s one new variable under this script that needs filling. It’s asking for a ‘Skin.’ We need to make that in Unity. If you look in your Assets folder, you should see a file that we downloaded that is a special font called ‘6809 Chargen’.

In your Project pane, right-click and create a GUI Skin called ScoreSkin. Click on that Skin, and you should see a variable field called ‘Font’ at the top of the Inspector pane. Click + drag our font to that variable slot.

If you scroll down and look under the dropdown menus for ‘Label’ and ‘Button’ you can also change the size of your text, etc. Play around with size until it looks good. I set Font Sizes for my Label and Button to 42 and 20, respectively. In the end, my HUD’s Game Manager (Script) looks like this:

Awesome! Now you should, when you play, see something like this:

Cool. Now let’s make sure that the game knows when we do score. To do that, we need to add a script to the LeftWall and RightWall objects under the HUD dropdown. It’s the same script so it should be pretty easy to do. First, we’ll go to Add Component > New Script on the LeftWall, and name this new script SideWalls.

Code Breakdown

After we import our packages, we just need to write one function. This function detects when something is colliding with our left or right walls. If it’s the ball, we call the score method in GameManager, and reset the ball to the middle.

You already added the script to LeftWall, and now, since it’s written, go to Add Component > Scripts on RightWall. Choose the Script we just wrote. Here’s the completed script: SideWalls.cs

Now, in order for Unity to call our OnTriggerEnter2D method, we have to make sure both the LeftWall and RightWall have the Is Trigger checkbox selected on their Box Colliders in the Inspector pane. This means that Unity won’t treat these walls as physical walls, but rather they “trigger” something in the game (in this case, they give a player a point).

Test your game to make sure both players can score a point. If so, know what that means? We’re DONE! Almost.

Last Step: Make The Game

Now, we only have to make our game playable outside of Unity. To do this, go to File at the top of Unity. Go to Build Settings and then choose Mac, PC, Linux Standalone. This will make an executable (playable) file appear on our desktop. You may need to Add Open Scenes, to ensure that Main is included in the build.

Now, click on Player Settings. This is where you should put your name on the Project, choose an icon (I chose the Ball sprite), and uncheck Default Is Full Screen. It asks for a default screen width and height. I chose 960x540 but it really doesn’t matter too much. The important thing is in the Supported Aspect Ratios list. Click the little arrow and uncheck everything except 16:10 and 16:9. If we choose a different aspect ratio, it’s possible we might not see our paddles. Your settings in the end should look like this:

Now, hit Build and choose where you want to save the file (I chose the desktop), and name it something (I named it Pong v1.0). Look at your desktop. Is it there? Sweet. If you want to see the completed version, here’s the sample code on GitHub.

Congratulations, and enjoy your game. Thanks for going through this tutorial, and if you want to learn more about Unity or coding in general, make sure to check out the rest of Awesome Inc U online.

THANKS, AND GAME ON


This Tutorial will show how to make a 2D Pong Game in the Unity Game Engine with only 38 lines of code. Everything will be explained step-by-step so everyone can understand it.

Here is a preview of the final game:

Foreword

Our two-dimensional Pong game will be inspired by the original Pong game from 1972.

We will begin by thinking about the game rules and taking a first look at the Unity engine.

Please note that the Microsoft Windows operating system was used for this tutorial, however this tutorial can be followed on Windows, Mac OS or Linux versions of Unity. If you use a different operating system, you will need to adapt the location of your project accordingly.

Game Concept


The game rules should be very similar to the original Pong. The right player scores a point if the ball hits the left wall. The left player scores a point if the ball hits the right wall. If it hits the top or bottom wall then it bounces off. Each player will have a racket that can be moved up and down to hit back the ball.

Our rackets should have an influence on the ball's outgoing angle:

  • If the racket hits the ball at the top corner, then it should bounce off towards our top border.
  • If the racket hits the ball at the center, then it should bounce off towards the right, and not up or down at all.
  • If the racket hits the ball at the bottom corner, then it should bounce off towards our bottom border.

About the Unity Engine

In order to make our idea a real game, we will have to download and install the Unity Engine first. After clicking on the link, simply select the Download Unity Hub option. This will download the Unity Hub installer. Once the download has completed, simply open the downloaded file and follow the setup wizard, accepting the default options as you go. Please note that Mac OS and Linux users may have additional steps to complete the Unity Hub installation, which are outside the scope of this tutorial.

If Unity Hub does not automatically launch after installation completes, simply launch it from the Windows Start Menu or desktop icon (if one was created). If you're not using Windows, then you will need to adapt this step to your environment.

Installing Unity through the Unity Hub

Note: Please skip this section if you're already using Unity 2018.3 or above.

Once launched, you will be presented the Unity Hub. Unity Hub requires a Unity ID to get past the activation process and while we could have installed Unity 2018.3 manually, the Hub makes it much easier to get things rolling.

A Unity ID is free. Either create an ID or sign into a existing account and then you will be asked to locate or grab a version of Unity to kick things off. Click on the Download button as shown in the screenshot, and you will be presented with the list of Official Releases on the Unity download server. The version at time of writing we are going to install is Unity 2018.3.14f1. If a newer version of Unity is available that has the 2018.3 prefix, then you can safely use that version. Of course, newer versions of Unity can be used but unless you have a good reason to, stay on course.

Select the Download button next to the Unity 2018.3.14f1 option. This will present you with the following:

You don't need any of the extra platform options. If English is not your native language, you may want to take a language pack - some exist for Korean and Japanese, for example. For this tutorial, just click Done.

Your computer may ask you for your username and password as part of the setup process. On Windows, you may have to simply click Yes when it asks Do you want to allow Unity Hub to make changes to your device?. On Mac, it may ask you to enter your login username and password. This installation process will take a while, even on a really fast connection - so it's best you grab a drink before continuing.

If you haven't already installed Microsoft Visual Studio, you will probably find the Unity installation process will download and install it as well. You can disable this optional installation, but you will be missing out on a proper code editor. That said, you can still complete this tutorial using Notepad or Notepad++, it's just a matter of preference. Note: Visual Studio installation is outside the scope of this tutorial, but it should be easy enough to follow the on-screen prompts.

While Unity is downloading, let's talk about the Engine a bit. If someone would have to summarize Unity in one word, it would be simplicity.

Unity is the first Game Engine that is really simple to use (even for normal people), while still being perfectly suitable for professional games that demand high performance and realistic graphics. In Unity, everything is really simple - no matter if it's creating Animations, making a car explode, creating 2D and 3D Games or just making a world with realistic Physics.

One of the greatest features about Unity is the deployment: after creating our game once, we can deploy it to Windows, Mac and Linux desktop targets. Unity also supports mobile platforms such as Android and iOS as well as consoles such as the Nintendo 3DS and Switch, Xbox One, Playstation 4 and more. What usually takes months of hard work can be done with just one click in Unity.

The exact name of the engine is Unity3D, it does however support 2D Game Development since version 4.3. We will be using the 2018.3 version in this Tutorial.

Basically we are doing the same things over and over again in Unity: we create a Project, we put a few things into our Scene and move them around interactively until they are where we want them to be, and then we do some Scripting to implement game logic, respond to events or control our hero.

Unity's uses the C# language for scripting, which is what we will be using for this Tutorial.

Starting Unity

Once Unity has finished downloading and installing via the Unity Hub, simply click on 'New' in the Unity Hub menu, and a screen like the following will appear:

As shown above, for the Project Name we will call it Pong. For Unity version, make sure 2018.3.14f1 is selected (remember, your screen will look different than the screenshot above). Make sure the Template is set to 2D and the location is set to somewhere accessible. Unity Analytics is not required so you can disable that option if it is enabled by default. Once you are happy, simply click Create Project.

Unity will take a few moments depending on your computer's hardware to get started and create a new blank project. It really is that easy!

Exploring Unity

Let's close the Welcome screen and get familiar with the Engine a bit. Here are the main Elements and what they do:

Hierarchy:

On the left side we can see the Hierarchy, which contains a list of all the things that are currently in our game. As we can see, currently it's only the Main Camera, which was added by Unity automatically to make our life easier.

Project Area:

The Project Area contains all kinds of Assets like Textures, 3D Models or Scripts. If we want, we can use those Assets in our game by dragging them into the Hierarchy or into the Scene.

Scene:

We can see the game world in the Scene view. We can find any game object in the Scene by double clicking it in the Hierarchy. To navigate around the Scene, we just click into it once and then use the left, right and middle mouse buttons. Don't be afraid to play around with it a bit until you've mastered it.

Inspector:

The Inspector shows the properties of the currently selected object(s). For example, if we select the Main Camera in the Hierarchy then we can see its Position, Rotation, Name and all other things that are relevant about it.

Unity uses a Component-Based Object system, much like other Game Engines. Everything is just an empty Object first. Then things are added to it, for example a Light, a Position, a Texture, a 3D Model and more. In case of the Camera, the Components are Transform, Camera and Audio Listener. All those Components are put onto one Object, and all together make our Main Camera which can view something, hear sounds, change its position and so on. Don't worry if this sounds confusing, we will do it over and over again and soon we will see that this is the easiest way possible to create games.

Moving, Rotating, Scaling and more:

Let's have some fun and move around the Camera. We can either change the position, rotate it or make it bigger (or smaller). That's what those buttons are for:

The Buttons are as follows:
- The Hand Icon (first button) allows you to look around the scene.
- The Cross-Arrows (second button) allows you to move objects around (Hotkey: W).
- The Circular Arrows (third button) allows you to rotate objects (Hotkey: E) on the X, Y and Z Axes.
- The Expanding Cube (or the box with 4 diagonal arrows) scales objects (Hotkey: R), so we can make them bigger or smaller.
- The Square with circular corners (fifth button) allows easy movement of UI Canvas elements in the 2D UI Canvas (Hotkey: T).
- The last (sixth) button is a new multi-purpose tool (Hotkey: Y) as it allows you to move, rotate and scale all in one go.

You probably don't need to worry about the forth, fifth or sixth buttons for this tutorial. Just click one of the other Buttons and then interact with the Blue/Green/Red lines around the Camera in the Scene View:

The Play Button

Let's run our game and see how it looks by pressing the Play Button:

When pressing Play, we always see the Game World through the eyes of our Camera. So far we only see the blue background because there is nothing in front of the camera yet.

Note: to go back to the editing mode, press the Play button again (to stop playing).

That's it, now we know everything about Unity that we need to know to make a 2D Pong Game. Since Unity has already given us a sample scene, go to the File Menu, and choose New Scene. If asked if you want to save changes, choose No or Discard. Then on the newly created scene, save the scene (Top Menu: File ->Save Scene). When prompted for a filename, call the scene MainScene.

Camera Setup

Alright, we will begin by modifying the Camera so that it shows the game in the correct size and with the right background color. We can modify the Camera settings by first selecting it in the Hierarchy:

Afterwards we can see the settings in the Inspector. We will change the Background color to black and adjust the Size so that it fits our game later on:

Creating the Walls

The Wall Texture

Let's add four walls to our game. All we need to make a wall is a so called Sprite, or in other words: a Texture.

We will use one horizontal Sprite for the top and bottom walls and one vertical Sprite for the left and right walls:

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

Alright now we can see them in Unity's Project Area:
Note: select Assets instead of Favorites in the Project area in case you don't see them.

The Wall Import Settings

Let's select both wall images and then take a look at the Inspector, where we will apply the following Import Settings:
Note: the Filter Mode and Format can be used to decide between quality and performance. A Pixels Per Unit value of 1 means that 1 x 1 pixels will fit into one unit in the game world. We will use this value for all our textures, because the ball will be 1 x 1 pixels later on, which should be exactly one unit in the game world.

Modifying the Import Settings might seem like a weird thing to do if you are new to Unity. As a matter of fact, our game would work just fine without ever touching the Import Settings at all. However in 2D games it's usually a good idea to modify those settings so that the world size is something reasonable (we don't want a 100 meter huge racket, this could make the physics somewhat tricky).

Adding the Walls to the Game World

So in order to add the Walls to our game, all we have to do is drag them from the Project Area into the Scene:

We will drag each texture into the Scene twice so that we have 4 walls:

Afterwards we position the walls so that they look like a rectangle with the Camera in the center:
Note: we can position the walls by either dragging them around, or by selecting them and then changing their Position in the Inspector.

Renaming the Walls

We will also rename the Walls to WallLeft, WallRight, WallTop and WallBottom so that we don't lose the overview later on. Renaming is very easy, all we have to do is right click a wall in the Hierarchy and select Rename:

Here is what our Hierarchy looks like afterwards:

Wall Physics

Right now we can see the walls in the game, but they aren't real walls yet. They are just images in the game world, a purely visual effect.

We want the walls to be real walls so that the Rackets and the Ball will collide with them instead of just going right through them.

Unity comes with an incredibly powerful physics engine, and all that we have to do is tell Unity that our walls are supposed to be Colliders. We will select all the walls in the Hierarchy:

Afterwards we click on the Add Component button in the Inspector and then select Physics 2D ->Box Collider 2D, or thanks to Unity's search option we simply start typing box:
Note: whatever we do in the Inspector will be done for all objects that are selected in the Hierarchy. And because we selected all four walls, they will all have a Collider now.

Now we can see that all our walls have a Box Collider 2D component in the Inspector:
Note: the -- values are the ones that are different between the selected GameObjects.

If we take a look at the Scene then we can also see that each wall is now surrounded by a green rectangle:
Note: the green rectangles are the colliders. They are only shown in the Scene and not in the final game.

We can also select only a single wall to see all the values correctly:

Adding the Dotted Line

Alright, if you got this far, then good work! Let's add the dotted line in the middle. We will use the following texture:

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

We will select it in the Project Area and then apply the same Import Settings that we used before:

Afterwards we can drag it from the Project Area into the Scene. We will position it in the middle of the game:
Note: the dotted line is a great example to understand how Unity's Physics work. Right now the dotted line is just a texture. Just something that we can see. The ball will not collide with the dotted line unless we add a Collider to it (which we won't, because the ball is not supposed to collide with it).

Creating the Rackets

The Racket Texture

We will use yet another white texture for the rackets:

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

We will use the following Import Settings for it:

Our game will have two players, one on the left and one on the right. So let's drag the racket into the game twice and position it once on the left and once on the right:

Renaming the Rackets

Again to make our lives easier later on, we will rename the two rackets to RacketLeft and RacketRight in the Hierarchy:

Racket Physics

Okay so our Rackets should make use of Unity's Physics Engine. At first they should be able to collide with the wall, hence why we add colliders again by selecting both Rackets in the Hierarchy, then pressing Add Component ->Physics 2D ->Box Collider 2D in the Inspector so they look like the screenshot that follows. If you did the search trick as mentioned earlier, Box Collider 2D will appear already.

The player should also be able to move the Racket upwards and downwards later on. But the Rackets should stop moving upwards (or downwards) when they collide with a wall.

What sounds like some complicated math will be ridiculously easy in Unity, because a Rigidbody does just that. It always adjusts an object's position so it's physically correct. For example, it can automatically apply gravity to the object, or it can make sure that our Rackets will never move through a wall.
Note: as a rule of thumb, everything physical that moves through the game world will need a Rigidbody.

To add a Rigidbody to our Rackets we just select both of them in the Hierarchy again, then take a look in the Inspector and press Add Component ->Physics 2D ->Rigidbody 2D. We then modify the Rigidbody 2D to disable Gravity(because there is no gravity in a pong game) by setting Gravity Scale to 0, enable Freeze Rotation Z(the rackets should never rotate) under Constraints. Then we set the Collision Detection to Continuous and enable Interpolation by selecting Interpolate from the drop-down that appears next to Interpolate. This ensures that the physics are as exact as possible:

Racket Movement

Let's make sure that players can move their rackets. That kind of custom behavior usually requires Scripting. With both rackets still selected, we will click on Add Component ->New Script and finally name it MoveRacket.

Afterwards we can double click the Script in the Project Area in order to open it:

Here is what our Script currently looks like:

Multiplayer

The Start function is automatically called by Unity when starting the game. The Update function is automatically called over and over again, roughly 60 times per second.

But there is another Update function, it's called FixedUpdate. This one is 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 usually a good idea to use FixedUpdate when doing Physics stuff (we want to move Rackets that have Colliders and RigidBodys, hence Physics stuff).

Okay so let's remove the Start and Update functions and create a FixedUpdate function instead:

Note: it's important that we name it exactly FixedUpdate because this is the name that Unity expects. We can also make functions with different names, but they wouldn't automatically be called by Unity then.

The rackets have a Rigidbody component and we will use the Rigidbody's velocity property for movement. The velocity is always the movement direction multiplied by the speed.

The direction will be a Vector2 with a x component (horizontal direction) and a y component (vertical direction). The following image shows a few Vector2 examples:

The rackets should only move upwards and downwards, which means that the x component will always be 0 and the y component will be 1 for upwards, -1 for downwards or 0 for not moving.

The y value depends on the user input. We could either check for all kinds of key presses (wsad, arrow keys, gamepad sticks and so on), or we could simply use Unity's GetAxisRaw function:
Note: we use GetAxisRaw to check the vertical input axis. This will return 1 when pressing either the W key, the UpArrow key, or when pointing a gamepad's stick upwards. It will return -1 when using the S key, the DownArrow key, or when pointing a gamepad's stick downwards. It will return 0 when none of those keys are pressed. Or in other words, it's exactly what we need.

Now we can use GetComponent to access the racket's Rigidbody component and then set its velocity:

We will also add a speed variable to our Script, so that we can control the racket's movement speed:

We made the speed variable public so that we can always modify it in the Inspector without changing the Script:

Now we can modify our Script to make use of the speed variable:
Note: we set the velocity to the direction multiplied by the speed, which is exactly the velocity's definition.

If we save the Script and press Play then we can now move the rackets:

There is just one problem, we can't move the rackets separately yet.

Adding a Movement Axis

Right now, both our Scripts check the 'Vertical' Input axis for the movement calculations. Let's create a new Axis variable so that we can change the Input Axis in the Inspector:

Let's select Edit ->Project Settings. This will bring up a pop-up window with a variety of settings you can tweak, as shown below. From the left-side menu, select Input. This will show something like the following:

Here we can modify the current Vertical axis so that it only uses the W and S keys. We will also make it use only Joystick 1. Click the first Vertical entry (usually straight under Horizontal) and make it look like the following:

Now we will increase the Size by one in order to add a new axis:

We will name it Vertical2 and modify it accordingly:

Ping Pong 2d - Multiplayer Mac Os Pro

Afterwards we will select the RacketRight GameObject and change the MoveRacket Script's Axis property to Vertical2:

If we press Play then we can now move the rackets seperately:
Note: instead of using axes, we could also create a up and down key variable in our Script and then set it to w/s for the left racket and UpArrow/DownArrow for the right racket. However by using axes we end up with far less code and perfect gamepad/joystick/keyboard support.

Creating the Ball

The Ball Texture

Almost there! Creating the Ball will be easy again. At first we save the following texture to our Project's Assets folder:

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

We will use the following Import Settings for it:

Now we can drag it from the Project Area into the middle of the Scene:

The Ball Collider

Our Ball should make use of Unity's Physics again, so let's select the Ball object if it's not already selected and choose Add Component ->Physics 2D ->Box Collider 2D to add a Collider:

Our ball is supposed to bounce off walls. For example when flying directly towards a wall it should bounce off in the exact opposite direction. When flying in a 45° angle towards a wall, it should bounce off in a -45° angle and so on.

This sounds like some complicated math that could be done with Scripting. But since we are lazy, we will just let Unity take care of the bouncing off thing by assigning a Physics Material to the Collider that makes it bounce off things all the time.

At first we right click in our Project Area and selected Create ->Physics 2D Material which we will name BallMaterial:

Now we can modify it in the Inspector to make it bounce off:

Then we drag the material from the Project Area into the Material slot of the Ball's Collider:

And that's all. Now the ball will bounce off in case it collides with things in the game.

The Ball Rigidbody

In order to make our ball move through the game world, we will add a Rigidbody2D to it again by selecting Add Component ->Physics 2D ->Rigidbody 2D.
Note: remember, every Physics thing that is supposed to move through the game world will need a Rigidbody.

We will modify the Rigidbody component in several ways:

  • We don't want it to use Gravity
  • We want it to have a very small Mass so it doesn't push away the Rackets when colliding
  • We don't want it to rotate
  • We use Interpolate and Continous Collision Detection for exact physics


Note: those modifications are not very obvious to beginners. The usual workflow is to add a Rigidbody, test the game and then modify the Rigidbody in case of undesired effects like a too big mass.

Okay so there is one more thing to do before we see some cool ball movement. We will select Add Component ->New Script and name it Ball. Afterwards we will double click the Script in the Project Area in order to open it:

Multiplayer

Let's remove the Update function because we won't need it. Instead we will use the Start function to give the ball some initial velocity. Yet again we will use a direction multiplied by a speed:

Now if we press play, we can see the Ball bounce off the walls and rackets:

Again, we didn't have to worry about any complicated math. Unity took care of it for us with its powerful Physics engine.

The Ball <-> Racket Collision Angle

Our game already looks a lot like Pong, but there is one more important modification to be done. We explained in the very beginning that the ball's outgoing angle should depend on where it hit the racket:

This way the players can shoot the ball into whatever direction they please, which adds a huge tactical component to the game.

Let's modify our Ball Script to use the OnCollisionEnter2D function that is automatically called by Unity upon colliding with something else:

So now we need a function that calculates the ball's velocity depending on where it hit the racket. The following image shows the Vector2 for several movement directions again:

Now the x value is obvious, it's -1 in case it bounces off the right racket and it's 1 in case it bounces off the left racket. What we need to think about is the y value, which will be somewhere between -1 and 1. All we really need to calculate is this:

Or in other words: we just have to find out where the ball is in relation to the racket. Or in other words: we just have to divide the ball's y coordinate by the racket's height. Here is our function:

Note: we subtract the racketPos.y from the ballPos.y to have a relative position.

Free Ping Pong Game Online

Here is how our final OnCollisionEnter2D function looks:

Note: please read through the comments in order to understand what's going on.

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

Summary

Congratulations for making it this far!

In this Tutorial we learned how to install and use Unity, create a basic Scene with just some textures, use Unity's 2D Physics engine and create Scripts to add custom game mechanics.

When making further improvements to the game, always remember: Unity is simple, you can do almost everything with just a few mouse clicks or a few lines of C# code. There are tons of features that can be added to make the game as fun as possible:

  • Add a Trail Effect like shown at the top
  • Add the old Pong Sound that we all love
  • Add a Score
  • Increase the Ball's speed over time
  • Add an AI enemy
  • Add a menu and a credits screen

The Project Files can be downloaded here. If you get a prompt to upgrade the Unity project from Unity or the Unity Hub, simply click Upgrade.