Unity 2D Techniques: Build a 2D Pinball Game

In this tutorial, you’ll learn how to use Unity’s 2D techniques to build an old-school pinball game using sorting groups, the mesh editor and more. By Ben MacKinnon.

Login to leave a rating/review
Download materials
Save for later

In this tutorial, you’ll learn how to use Unity’s 2D techniques to build an old-school pinball game using sorting groups, the mesh editor and more.

Update note: Ben MacKinnon updated this tutorial for Unity 2019.3. Arai wrote the original.

In this Unity 2D Techniques tutorial, you’ll learn advanced tips and tricks for building 2D games in Unity. Learn how to apply these techniques while building an epic old-school pinball game called Snap and Strike!

Should you find this tutorial too advanced, work through this starter on Unity 2D games How to Make a Game Like Jetpack Joyride in Unity 2D tutorial first. Once done, come back and level up your 2D Unity skills even further.

There’s minimal scripting in this tutorial, but it’ll be easier to follow if you have some basic knowledge of C# programming. To brush up your skills, check out our Introduction to Unity Scripting tutorial.

Note: This tutorial assumes that you’re comfortable working with Unity and you know your way around Unity’s UI. If you’re not, take the time to read through our Introduction to Unity UI tutorial first.

By the time you’ve finished this tutorial, you’ll know more about:

  • Sorting groups
  • Sprite masks
  • 9-slice sprites
  • 2D colliders and joints
  • The mesh editor
  • Types of effectors and 2D physics materials

It’s time to get the (pin)ball rolling!

Getting Started

First, download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.

Make sure you’re using Unity version 2019.3, which you can download through the Unity Hub.

Unzip the materials and open the starter project in Unity. When the project launches, switch to the Scene view and make sure you’re using 2D mode.

Where to find 2D mode

Exploring the Starter Project

Start by exploring the project.

Double-click the PinballWizard scene in Assets/RW/Scenes. In the Hierarchy, you can see the GameObjects separated into categories:

  • SoundObjects
  • Main camera
  • Hotspots
  • Static colliders
  • Static panel
  • Animations

Click Play and take a look at the current state of the pinball table.

Unsorted pinball layers

Well, things are certainly animating! But the images are currently fighting each other to render on-screen.

Your first task is to adjust the Sorting Layers for the last three groups so they render in the correct order.

Adjusting Your Sorting Layers

A Sorting Group is a group of components you use to create consolidated Sorting Layers. That is, multiple instances of a prefab with multiple objects on different sorting layers.

The Sorting Layers in this project should be in the following order:

  • Panel (lowest layer)
  • Efx
  • Logo
  • Obstacles
  • Top
  • Cover (highest layer)

Now, adjust your Sorting Layers as follows:

  1. Static colliders: These objects with colliders form the basic collision structure of the pinball table. A sorting group is not required here.

    The static colliders of the pinball table.

  2. Static panel: Contents in this group are hidden.

    To show this group, select Static Panel in the Hierarchy. Then, click Add Component and select Rendering ▸ Sorting Group. In the newly-added Sorting Group component, find the Sorting Layer drop-down and select Panel.

    Editing the Sorting Layer.

  3. Animations: Select Animations in the Hierarchy and click Add Component. Then, select Rendering ▸ Sorting Group.

    In the Sorting Layer drop-down, select Efx and click Play.

    Pinball game with proper animation layers

You’ll find that most of the nuts and bolts for the pinball game are already in the starter project. Now it’s time for the fun stuff: adding the action!

Getting the Ball Rolling

First, you need to create an empty GameObject to hold your work.

Do this by right-clicking an empty space in the Hierarchy and selecting Create Empty. Now, name the new object Interactive Parts.

In the Inspector, reset its Transform values by clicking the Settings icon and selecting Reset.

Next, create seven more empty GameObjects as children of Interactive Parts and name them:

  • ScrollingTrees
  • BillBoard
  • Plunger
  • Flippers
  • Float Piece Area
  • Road Tunnel Zone
  • Bumpy Parts

Be sure to reset all their Transform values as well.

New GameObjects

Note: Create these GameObjects quickly by selecting the Interactive Parts GameObject and pressing Alt-Shift-N to create a child GameObject. Then use Control/Command-D to duplicate it six times! Then all that’s left is to rename each GameObject.

Scrolling Trees

Next, you’ll use a Sprite Mask to display only a part of an animation. It’ll look like this:

Unity 2017 2D Techniques

Here’s how you do it:

  1. Go to Assets/RW/Sprites, drag trees_circle onto ScrollingTrees in the Hierarchy and name the sprite instance TreeCircle.
  2. In the Inspector, set the Transform Position to (X:-0.7, Y:2.2, Z:0) and set its Rotation to (X:0 Y:0 Z:17).
  3. Right-click ScrollingTrees in the Hierarchy, select 2D Object ▸ Sprite Mask and name it TreeMask.
  4. Set the Transform Position to (X:-1.91, Y:2.58, Z:0) and set Scale to (X:1.48, Y:1.58, Z:1).
  5. In the Inspector, go to the Sprite field of the Sprite Mask component, click on the circle icon to launch the list of sprite assets, and select trees_mask.
  6. Select TreeCircle in the Hierarchy. Using the Inspector, find the Sprite Renderer and select Efx from the Sorting Layer drop-down. From the Mask Interaction drop-down, select Visible Inside Mask.

Editing the Sprite Renderer.

Scripting the Animation

With the graphics in place, it’s time to add the script that controls the animation.

Double-click Assets/RW/Scripts/AnimateController to open it in your code editor.

Add the following variables below the existing ones:

public GameObject treeObject;
private float turnSpeed = 30f;

Then add the following FixedUpdate:

private void FixedUpdate()
    if (treeObject != null)
        treeObject.transform.Rotate(new Vector3(0f, 0f, turnSpeed * Time.fixedDeltaTime));

This rotates the sprite assigned to the treeObject variable at a consistent speed, regardless of whether the player’s frame rate is 30 FPS, 60 FPS, or fluctuates in between. turnSpeed allows you to tweak how fast the trees rotate.

Note: You can learn more about FixedUpdate in the official Unity docs.

Click Save and return to Unity.

Select ScrollingTrees in the Hierarchy, click Add Component and select Scripts ▸ Animate Controller. Then drag TreeCircle from the Inspector onto the Tree Object field.

Click Play to preview your new working animation.

The trees moving on the pinball table.

Adding the Billboard

There’s no sense playing pinball if you can’t try to beat your last score! To help you do that, you’ll add an animated billboard with flashing lights next.

Open Assets/RW/Sprites/ani_billboard and drag aniBillbord0001 into BillBoard in the Hierarchy. Name the child instance AniBillboard.

In the Sorting Layer drop-down, select Top. Click Add Component and select Miscellaneous ▸ Animator.

In the Inspector, open the Controller field of Animator and click the circle icon beside it to launch the list of animator controllers. Select ani_Billboard.

Open the Animation window from Menu ▸ Window and click Play to preview what the billboard will look like.

Animated billboard

The 9-slice sprite is another useful 2D technique. This feature preserves the corners and borders of graphical elements when resizing.

Go to Assets/RW/Sprites/ani_billboard and select one of the sprites. In the Inspector, click the Sprite Editor icon to edit the stretchable parts of the sprite.

The sprites used for this animation come prepped with a 9-slice sprite, so resizing them won’t be a problem now. Phew!

Here’s what you achieve using 9-slice on your billboard:

9-slice example

Placing the Billboard

Now, you need to place the billboard onto your pinball machine.

Go to AniBillboard in the Hierarchy, set its Transform values for Position to (X:1.5, Y:4.3, Z:0) and change its Scale to (X:-3.5, Y:2, Z:1).

Skeptical face

Uh… it’s a bit big, isn’t it? To fix that, set the Draw Mode in Sprite Renderer to Tiled and Size to Width:1 Height:1. In the Tile Mode drop-down, select Adaptive.

Happy face.

Much better!

Adding the Score

Add the score to your billboard by going to Assets/RW/Prefabs, dragging scoreText into Billboard in the Hierarchy and changing its Scale to (X:0.41, Y:0.4, Z:1).

Click Play to preview your pinball game with its swanky new animated billboard!

Unity 2017 2D Techniques

Adding the Ping!

With the “bling” in place, it’s time to add the “ping” to the playfield! In other words, you need to add the colliders that make the game interesting.

Pinball game without enough colliders

Start by going to the Hierarchy and moving BumperRamps and CurveRamp from Static Colliders into Interactive Parts.

Adding the Plunger

The first thing you need to play pinball is a plunger so you can shoot a ball out of the barrel and start the game!

In the real world, the player pulls back the plunger, which engages the spring coils. Upon release, the spring coils propel the ball into the playfield. You want the same feeling in your app.

To implement those mechanics, select Plunger in the Hierarchy. In the Inspector, add a Rendering ▸ Sprite Renderer component.

Select the Sprite Renderer Component, click the circle icon beside the Sprite field and assign the cam asset to it. Set Sorting Layer to Top and the Transform Position to (X:2.66, Y:-4.6, Z:0).

Pointing out the elements

Now, think about the plunger’s physics. It’s a spring with two elements at work:

  • The anchor: Anchors the moving part of the joint, which builds the tension.
  • The spring joint: The moving part of the joint, which creates the force.

Next, you’ll need to implement the physics that will make the plunger behave as expected.

Adding the Anchor

Go to Assets/RW/Prefabs and drag plungerAnchor into Plunger in the Hierarchy to create a child instance. In the Inspector, add Physics 2D ▸ Rigidbody 2D and set its Body Type to Kinematic to fix its position.

Selecting the Kinematic option

Adding the Spring Joint

Now that you’ve created the anchor, it’s time to create the spring joint. This acts like a spring to pull back and launch the plunger.

To do this, click the arrow sign beside plungerAnchor in the Hierarchy to show its nested contents. Select the Plunger-springjoint and add a Spring Joint 2D to it via the Inspector.

Selecting Spring Joint 2D

Make sure you select the 2D Spring joint option!

Note: All 2D Joint components come with a compulsory Rigidbody 2D.

Error message: can't remove Rigidbody 2D

In Rigidbody 2D, set Body Type to Dynamic and Mass to 2.

Expand the Constraints section and enable Freeze Position for X and Freeze Rotation for Z.

Editing Mass and Constraints

In Spring Joint 2D, check Enable Collision. Disable Auto Configure Distance. Set Distance to 1 and Frequency to 10.

Set Connected Anchor to (X:0, Y:-1) and assign plungerAnchor as the component’s Connected Rigid Body.

Editing Spring Joint 2D.

In the Hierarchy, drag Assets/RW/Prefabs/plungerEffects into the Plunger object. This creates a child object instance.

Adding the Plunger Script

Finally, it’s time to control the physics you added to the plunger and spring joint.

In the Inspector, with Plunger-springjoint still selected, click Add Component and select Scripts ▸ Launcher. Double-click to launch it in the code editor.

Declare the following variables below the existing ones:

private SpringJoint2D springJoint;
private Rigidbody2D rb;
private float force = 0f;          // current force generated
public float maxForce = 90f;

Then, at the end of Start, add the following:

springJoint = GetComponent<SpringJoint2D>();
springJoint.distance = 1f; 
rb = GetComponent<Rigidbody2D>();

After // #1 in Update, add the following line:

// calculates current force of exertion
force = powerIndex * maxForce;

Finally, add the following FixedUpdate at the end of the class:

private void FixedUpdate()
    // When force is not 0
    if (force != 0)
        // release springJoint and power up
        springJoint.distance = 1f;
        rb.AddForce(Vector3.up * force);
        force = 0;

    // When the plunger is held down
    if (pressTime != 0)
        // retract the springJoint distance and reduce the power
        springJoint.distance = 0.8f;
        rb.AddForce(Vector3.down * 400);

Save the file and return to Unity.

Assign plungerEfxZoom and plungerEfxLight from the plungerEffects instance to the component’s fields. Set Max Force to 200.

Editing the plunger

Test Your Work

You’re now ready to test your newly-working pinball plunger.

Drag a Assets/RW/Prefabs/ball into the Hierarchy to create an instance. Set its Transform Position to (X:2.84, Y:-1.08, Z:0). Click Play and test your plunger by pressing and releasing the space bar.

Pinball game with working plunger

Now you’re rolling!

Adding the Flippers

Right now, the ball shoots out from the barrel into the game zone, then drops off the bottom and into space.

Time to add flippers — the main weapons for pinball victory! You’ll start with the left flipper.

In the Hierarchy, right-click Flippers and select Create Empty. Rename the GameObject FlipLeft-hingejoint. In the Inspector, set Transform Position to (X:-1.26, Y:-3.8, Z:0) and Scale to (X:1.05, Y:1.05, Z:1).

For the right flipper, duplicate the left one and rename it FlipRight-hingejoint. Set its position to (X:0.46, Y:-3.8, Z:0).

Again, think about how the flippers will work. It’s like the plunger, only this time you need to rotate the flipper using the following components:

  • Hinge joints: Anchor a movable part at its point of rotation.
  • Flipper: The movable, flipper-y part.

Next, go to Assets/RW/Prefabs and drag the flipperLeft prefab into FlipLeft-hingejoint and the flipperRight prefab into FlipRight-hingejoint.

Location of the hingejoint elements

The Hinge Joints

Select FlipLeft-hingejoint in the Hierarchy. Go to the Inspector and add a Hinge Joint 2D. Set the Rigidbody’s Body Type to Kinematic. This makes this joint the fixed point of rotation for the flipper.

In Hinge Joint 2D, assign the flipperLeft instance as its Connected Rigid Body.

Enable Use Limits, then set Angle Limits to -30 for Lower and 30 for Upper.

Editing Hinge Joint 2D

Pop Quiz! Since the rotation limit for the Left HingeJoint is between -30 to 30 degrees, what do you think the rotation limit for the Right HingeJoint should be?

[spoiler title=”Steps for Right Flipper”]
Create a new Hinge Joint 2D component for FlipRight-hingejoint. Set its Rigidbody 2D Body Type to Kinematic.

The Angle Limits for the Right HingeJoint are Lower: 30 and Upper: -30.

Remember to assign the flipperRight instance as its Connected Rigid Body.

Setting the right flipper

Adding a Script to Flip

Now, add the script to make the flippers work.

Open FlipControlLeft.cs from Assets/RW/Scripts.

Declare the following variables below the existing ones:

public float speed = 0f;
private HingeJoint2D hingeJoint2D;
private JointMotor2D jointMotor;

Grab your references in Start by adding:

hingeJoint2D = GetComponent<HingeJoint2D>();
jointMotor = hingeJoint2D.motor;

Then, in the if statement in FixedUpdate, add the code to engage the joint’s motor:

// set motor speed to max
jointMotor.motorSpeed = speed;
hingeJoint2D.motor = jointMotor;

Finally, add an else statement to the same block:

    // snap the motor back again
    jointMotor.motorSpeed = -speed;
    hingeJoint2D.motor = jointMotor;

Try repeating the above code for the right flipper:

  1. Declare the required variables to gain access to the object’s HingeJoint2D and JointMotor2D components.
  2. Create a variable that stores the speed value for the motor.
  3. Listen for user interaction in FixedUpdate and trigger its motor speed.

[spoiler title=”Code Update for FlipControlRight“]
The only difference here is that you flip the speed variable because you rotate the flipper the other way.

In FlipControlRight.cs, declare the same variables:

public float speed = 0f;
private HingeJoint2D hingeJoint2D;
private JointMotor2D jointMotor;

Store your references in Start again:

hingeJoint2D = GetComponent<HingeJoint2D>();
jointMotor = hingeJoint2D.motor;

Then, in the if statement in FixedUpdate, add:

// set motor speed to max
jointMotor.motorSpeed = -speed;
hingeJoint2D.motor = jointMotor;

Finally, add the following else statement to that same block:

    // snap the motor back again
    jointMotor.motorSpeed = speed;
    hingeJoint2D.motor = jointMotor;


Save the files and return to Unity.

Attach the script component FlipControlLeft to FlipLeft-hingejoint and FlipControlRight to FlipRight-hingejoint. Set their Speed values to 1700.

Setting the Speed value

Click Play and try your flippers using the left and right arrow keys.

Pinball game with functional flippers

Road Tunnel Zone

The curved orbit at the top of the playfield increases the chance for the ball to enter the CurveRamp for more points — if you’re able to get the ball in!

In this step, you’ll create a vortex at the entrance to suck the ball into the tunnel and spit it out at the other end. Whee!

Force Field With Area Effector 2D

Set the ball instance’s Transform Position to (X:-2.28, Y:1, Z:0). In the Hierarchy, right-click Road Tunnel Zone and select Create Empty. Name this object Force Field.

Click Add Component and select Physics 2D ▸ Polygon Collider 2D.

In the Inspector, click the Edit Collider icon and move the vectors to the area outside the entrance of the tunnel. Enable Is Trigger and Used By Effector.

Adjusting the size of Polygon Collider 2D.

Click Add Component and select Physics 2D ▸ Area Effector 2D. Enable Use Global Angle. Then, set Force Angle to 90 and Force Magnitude to 20. In the Force Target drop-down, select Rigidbody.

Hit Play and test your new vortex.

Testing the vortex.

Note: Increasing Force Magnitude to 200 also sends the ball through the tunnel. But you wouldn’t get to use Surface Effectors 2D, so for the sake of this tutorial, make this a weak vortex.

A Guided Path With Surface Effector 2D

The “weak” vortex has only enough power to push your ball to the tunnel’s entrance. Next, you’ll create a path to guide the ball through the rest of the tunnel.

  1. Right-click Road Tunnel Zone in the Hierarchy and select Create Empty. Name this new object Road Surface.
  2. In the Inspector, click Add Component and select Physics 2D ▸ Edge Collider 2D.
  3. Click the Edit Collider icon and move the vectors accordingly.
  4. Enable Used By Effector and increase Edge Radius to 0.03.

Adjusting the Edge Collider 2D.

Next, click Add Component and select Physics 2D ▸ Surface Effector 2D. Set Force Speed to 15 and Force Scale to 1. Click Play.

Pinball game with misbehaving ball

Wait, what is that ball doing? You’ll fix is behavior in the next section.

Mesh Editing in Unity

At this point, when you preview your work you’ll see that the ball is acting weird.

Go to the Hierarchy, select Static Colliders/WallBoard and enable Sprite Renderer in the Inspector. Here, you’ll find the culprit — some vectors are blocking the tunnel’s entrance.

To fix this, go to Polygon Collider 2D, click on the Edit Collider icon and move the offending vectors out of the way. Don’t make the gap too wide.

Adjusting the Polygon Collider 2D

Note: For faster mesh editing:
  • Hold Alt and left-click to change the cursor into the Hand icon to move the canvas around.
  • Press Command (Mac) or Control (Windows) to highlight vertices, then left-click to delete.

Click Play again. There you go… all better!

Ball properly entering the tunnel

Blocking With Platform Effector 2D

Now, the ForceField pushes the ball onto the Road Surface, which then guides the ball along the tunnel and right back to the shooter and then…

Wha…? It goes right back down the chute to the plunger.

Pinball game with ball returning to plunger

That’s not quite right.

You need a collider to prevent the ball from falling back into the Plunger. But at the same time, you need to allow the ball to exit from the shooter after launch.

Back in the old days, you might have if-else‘d” your way out of it. But now, Platform Effector 2D is here to save the day!

Right-click Road Tunnel Zone in the Hierarchy, select Create Empty and name the new object Block Platform.

In the Inspector, click Add Component and select Physics 2D ▸ Edge Collider 2D. Then Edit Collider to move the vectors that will block the exit. Enable Used By Effector and set Edge Radius to 0.03.

Blocking the plunger chute

Next, click Add Component and select Physics 2D ▸ Platform Effector 2D. Disable Use Collider Mask. Then, set the value of Rotational Offset to 90 and the value of Surface Arc to 130. Enable Use One Way.

Click Play… you’ve solved the problem!

Ball now blocked from entering the plunger chute

Float Piece Area

Another sweet spot where the player can score more points is in the floating area.

To implement it:

  1. Set the Transform Position of the ball instance to (X:-2.2, Y:-0.5, Z:0).
  2. Go to Assets/RW/Sprites and drag floatpiece into Float Piece Area object in the Hierarchy.
  3. Name the child instance Float Area.
  4. In the Inspector, set Transform Position to (X:-2.63, Y:0.18, Z:0) and select Logo as its Sorting Layer.
  5. Click Add Component and select Physics 2D ▸ Polygon Collider 2D. Enable Is Trigger and Used By Effector.
  6. Add another component from Physics 2D ▸ Buoyancy Effector 2D. Set Density to 50. Under Damping, set Linear Drag and Angular Drag to 10.
  7. Set Flow Variation to -5 to give the floating effect a bit of movement.

Adjusting the Buoyancy Effector 2D

Click Play to check out the floating effect.

Ball in the floating area

Code the Float

Now, you’ll set the float duration. In Assets/RW/Scripts, double-click Floatpiece.cs to launch the file in the code editor.

Declare the following variables below the existing ones:

private BuoyancyEffector2D floatEffector;
public float floatingTime = 0f; // floating duration
private float runningTime = 0f; // the current duration since startTime
private float startTime = 0f;

At the end of Start, add:

floatEffector = GetComponent<BuoyancyEffector2D>(); // assign component to this instance

Replace the code inside the if block in OnTriggerEnter2D with the following:

// on enter zone, start float
floatEffector.density = 50;
// start timer
if (startTime == 0f)
    startTime = Time.time;
    scoreBoard.gamescore += 10;
    golightRenderer.sprite = golightAniController.spriteSet[0];

And replace the entire BeginFloat method with the following:

IEnumerator BeginFloat()
    while (true) 
        // calculate current duration
        runningTime = Time.time - startTime; 

        // play animation loop
        int index = (int)Mathf.PingPong(handcamAniController.fps * 
                    Time.time, handcamAniController.spriteSet.Length);
        handcamRenderer.sprite = handcamAniController.spriteSet[index];
        yield return new WaitForSeconds(0.1f);
        // when time is up            
        if (runningTime >= floatingTime)  
            // stop float and reset timer
            floatEffector.density = 0;    
            runningTime = 0f;
            startTime = 0f;
            // stop sound & animation 
            golightRenderer.sprite = golightAniController.spriteSet[1];
            handcamRenderer.sprite = handcamAniController.spriteSet 
                          [handcamAniController.spriteSet.Length - 1];

Click Save and return to Unity.

That was the most code you’ll need to write in this whole tutorial! A lot of it was calling things already defined for you.

First, you declared some variables, a reference to the BuoyancyEffector2D component that you added in the scene and some timers.

You’ll call OnTriggerEnter when the ball enters the Float Area. You start the timer, start some sound and animation effects and award the player some points. Then you start the BeginFloat coroutine.

In BeginFloat, you keep track of how long the ball has been in the Float Area and run some sprite animations.

When the time is up, you reset all the timers, stop all animations and sound effects and reduce the BuoyancyEffector2D.density to 0. This causes the ball to fall out of the Float Area and back into play!

Implementing the Float Area

Go to Assets/RW/Prefabs and drag floatEffects into the Float Piece Area object in the Hierarchy to create a child instance. Click the arrow icon beside floatEffects to expand the contents.

Select Float Area in the Hierarchy. Click Add Component and select Scripts ▸ Floatpiece. In the Inspector, assign floatEffects to Handcam Obj and StaticLight to Golight Obj. Set the Floating Time value to 2.

Editing Floatpiece.

Now press Play again to test.

Unity 2017 2D Techniques

Triangle Bumpers

You’re almost done with your pinball game! All that’s left is to enhance gameplay with point effectors and a physics material.

To do this, you’ll add bumpers to your game. If the ball hits any of these bumpers, it’ll shoot in the opposite direction.

To create these bumpers, go to Assets/RW/Prefabs and drag bumperTriangleLeft into Bumpy Parts in the Hierarchy. Place the ball instance in front of the bumper.

Click Play to see how the ball just rolls off the slope.

Pinball game with triangle bumpers that don't bump

Physics Material 2D Versus Point Effector 2D

In Unity, to add momentum to animated objects on collision, you have two options:

  • Physics Material 2D: Velocity remains consistent throughout the entire object surface, regardless of the point of impact.

    Using Physics Material 2D

  • Point Effector 2D: Velocity depends on the object’s center of mass and its point of impact.

    Using Point Effector 2D.

Feel free to play with both options. Experiment with different settings to find the optimal impact for the different colliding elements in the game.

Select bumperTriangleLeft in the Hierarchy. Find Polygon Collider 2D in the Inspector and enable Is Trigger and Used By Effector.

Next, click Add Component and select Physics 2D ▸ Point Effector 2D. Set Force Magnitude to 500 and adjust the Damping settings to Drag: 5000 and Angular Drag: 1000.

Editing the Point Effector 2D.

Now, drag bumperTriangleRight from Assets/RW/Prefabs into Bumpy Parts. Set it up the exact same way as the left bumper.

Then set the ball instance’s Transform Position to (X:-1.6, Y:-1.6, Z:0). Click Play to test your new bumpers.

Unity 2017 2D Techniques

Look! The ball’s so fast, you can’t see it.

Adding More Bumpers

There are two more prefabs you can try to explore more of the 2D Physics engine: bumperCircles and bumperDividers. To add them to your pinball game, drag them into Bumpy Parts in the Hierachy.

The starter project has already set these up for you. However, you can tweak the impact of the collision using either Point Effectors 2D or Physics Material 2D.

Finally, set the position of the ball instance to (X:2.8, Y:-1, Z:0).

Click Play and enjoy playing Snap and Strike!

Completed pinball game

Where to Go From Here?

Download the final project files by clicking the Download Materials button at the top or bottom of the tutorial.

To expand this game, you could build a menu system and limit the player to only three balls to go for a high score. Or you could hook it up with Facebook and setting up a High Score table to challenge your friends.

I hope you found this tutorial useful. If you have any questions or comments, or you’ve put together some other cool effects using Unity’s 2D techniques, tell us about them in the comments section below!