21 min read

This article written by John P. Doran, the author of Unity Game Development Blueprints, teaches us how to use Unity to prepare a well formed game. It also gives people experienced in this field a chance to prepare some great stuff.

(For more resources related to this topic, see here.)

The shoot ’em up genre of games is one of the earliest kinds of games. In shoot ’em ups, the player character is a single entity fighting a large number of enemies. They are typically played with a top-down perspective, which is perfect for 2D games. Shoot ’em up games also exist with many categories, based upon their design elements.

Elements of a shoot ’em up were first seen in the 1961 Spacewar! game. However, the concept wasn’t popularized until 1978 with Space Invaders. The genre was quite popular throughout the 1980s and 1990s and went in many different directions, including bullet hell games, such as the titles of the Touhou Project. The genre has recently gone through a resurgence in recent years with games such as Bizarre Creations’ Geometry Wars: Retro Evolved, which is more famously known as a twin-stick shooter.

Project overview

Over the course of this article, we will be creating a 2D multidirectional shooter game similar to Geometry Wars.

In this game, the player controls a ship. This ship can move around the screen using the keyboard and shoot projectiles in the direction that the mouse is points at. Enemies and obstacles will spawn towards the player, and the player will avoid/shoot them. This article will also serve as a refresher on a lot of the concepts of working in Unity and give an overview of the recent addition of native 2D tools into Unity.

Your objectives

This project will be split into a number of tasks. It will be a simple step-by-step process from beginning to end. Here is the outline of our tasks:

  • Setting up the project
  • Creating our scene
  • Adding in player movement
  • Adding in shooting functionality
  • Creating enemies
  • Adding GameController to spawn enemy waves
  • Particle systems
  • Adding in audio
  • Adding in points, score, and wave numbers
  • Publishing the game

Prerequisites

Before we start, we will need to get the latest Unity version, which you can always get by going to http://unity3d.com/unity/download/ and downloading it there:

Unity Game Development Blueprints

At the time of writing this article, the version is 4.5.3, but this project should work in future versions with minimal changes.

Navigate to the preceding URL, and download the Chapter1.zip package and unzip it. Inside the Chapter1 folder, there are a number of things, including an Assets folder, which will have the art, sound, and font files you’ll need for the project as well as the Chapter_1_Completed.unitypackage (this is the complete article package that includes the entire project for you to work with). I’ve also added in the complete game exported (TwinstickShooter Exported) as well as the entire project zipped up in the TwinstickShooter Project.zip file.

Setting up the project

At this point, I have assumed that you have Unity freshly installed and have started it up.

  1. With Unity started, go to File | New Project. Select Project Location of your choice somewhere on your hard drive, and ensure you have Setup defaults for set to 2D. Once completed, select Create. At this point, we will not need to import any packages, as we’ll be making everything from scratch. It should look like the following screenshot:

    Unity Game Development Blueprints

  2. From there, if you see the Welcome to Unity pop up, feel free to close it out as we won’t be using it. At this point, you will be brought to the general Unity layout, as follows:

    Unity Game Development Blueprints

    Again, I’m assuming you have some familiarity with Unity before reading this article; if you would like more information on the interface, please visit http://docs.unity3d.com/Documentation/Manual/LearningtheInterface.html.

Keeping your Unity project organized is incredibly important. As your project moves from a small prototype to a full game, more and more files will be introduced to your project. If you don’t start organizing from the beginning, you’ll keep planning to tidy it up later on, but as deadlines keep coming, things may get quite out of hand.

This organization becomes even more vital when you’re working as part of a team, especially if your team is telecommuting. Differing project structures across different coders/artists/designers is an awful mess to find yourself in.

Setting up a project structure at the start and sticking to it will save you countless minutes of time in the long run and only takes a few seconds, which is what we’ll be doing now. Perform the following steps:

  1. Click on the Create drop-down menu below the Project tab in the bottom-left side of the screen.
  2. From there, click on Folder, and you’ll notice that a new folder has been created inside your Assets folder.
  3. After the folder is created, you can type in the name for your folder. Once done, press Enter for the folder to be created. We need to create folders for the following directories:
    •      Animations
    •      Prefabs
    •      Scenes
    •      Scripts
    •      Sprites

    If you happen to create a folder inside another folder, you can simply drag-and-drop it from the left-hand side toolbar. If you need to rename a folder, simply click on it once and wait, and you’ll be able to edit it again.

    You can also use Ctrl + D to duplicate a folder if it is selected.

  4. Once you’re done with the aforementioned steps, your project should look something like this:

    Unity Game Development Blueprints

Creating our scene

Now that we have our project set up, let’s get started with creating our player:

  1. Double-click on the Sprites folder. Once inside, go to your operating system’s browser window, open up the Chapter 1/Assets folder that we provided, and drag the playerShip.png file into the folder to move it into our project. Once added, confirm that the image is Sprite by clicking on it and confirming from the Inspector tab that Texture Type is Sprite. If it isn’t, simply change it to that, and then click on the Apply button. Have a look at the following screenshot:

    If you do not want to drag-and-drop the files, you can also right-click within the folder in the Project Browser (bottom-left corner) and select Import New Asset to select a file from a folder to bring it in.

    Unity Game Development Blueprints

    The art assets used for this tutorial were provided by Kenney. To see more of their work, please check out www.kenney.nl.

  2. Next, drag-and-drop the ship into the scene (the center part that’s currently dark gray). Once completed, set the position of the sprite to the center of the Screen (0, 0) by right-clicking on the Transform component and then selecting Reset Position. Have a look at the following screenshot:

    Unity Game Development Blueprints

  3. Now, with the player in the world, let’s add in a background. Drag-and-drop the background.png file into your Sprites folder. After that, drag-and-drop a copy into the scene.

    If you put the background on top of the ship, you’ll notice that currently the background is in front of the player (Unity puts newly added objects on top of previously created ones if their position on the Z axis is the same; this is commonly referred to as the z-order), so let’s fix that.

    Objects on the same Z axis without sorting layer are considered to be equal in terms of draw order; so just because a scene looks a certain way this time, when you reload the level it may look different. In order to guarantee that an object is in front of another one in 2D space is by having different Z values or using sorting layers.

  4. Select your background object, and go to the Sprite Renderer component from the Inspector tab. Under Sorting Layer, select Add Sorting Layer. After that, click on the + icon for Sorting Layers, and then give Layer 1 a name, Background. Now, create a sorting layer for Foreground and GUI. Have a look at the following screenshot:

    Unity Game Development Blueprints

  5. Now, place the player ship on the foreground and the background by selecting the object once again and then setting the Sorting Layer property via the drop-down menu. Now, if you play the game, you’ll see that the ship is in front of the background, as follows:

    Unity Game Development Blueprints

    At this point, we can just duplicate our background a number of times to create our full background by selecting the object in the Hierarchy, but that is tedious and time-consuming. Instead, we can create all of the duplicates by either using code or creating a tileable texture. For our purposes, we’ll just create a texture.

  6. Delete the background sprite by left-clicking on the background object in the Hierarchy tab on the left-hand side and then pressing the Delete key. Then select the background sprite in the Project tab, change Texture Type in the Inspector tab to Texture, and click on Apply.
  7. Now let’s create a 3D cube by selecting Game Object | Create Other | Cube from the top toolbar. Change the object’s name from Cube to Background. In the Transform component, change the Position to (0, 0, 1) and the Scale to (100, 100, 1).

    If you are using Unity 4.6 you will need to go to Game Object | 3D Object | Cube to create the cube.

    Since our camera is at 0, 0, -10 and the player is at 0, 0, 0, putting the object at position 0, 0, 1 will put it behind all of our sprites. By creating a 3D object and scaling it, we are making it really large, much larger than the player’s monitor. If we scaled a sprite, it would be one really large image with pixelation, which would look really bad. By using a 3D object, the texture that is applied to the faces of the 3D object is repeated, and since the image is tileable, it looks like one big continuous image.

  8. Remove Box Collider by right-clicking on it and selecting Remove Component.
  9. Next, we will need to create a material for our background to use. To do so, under the Project tab, select Create | Material, and name the material as BackgroundMaterial. Under the Shader property, click on the drop-down menu, and select Unlit | Texture. Click on the Texture box on the right-hand side, and select the background texture. Once completed, set the Tiling property’s x and y to 25. Have a look at the following screenshot:

    Unity Game Development Blueprints

    In addition to just selecting from the menu, you can also drag-and-drop the background texture directly onto the Texture box, and it will set the property.

    Tiling tells Unity how many times the image should repeat in the x and y positions, respectively.

  10. Finally, go back to the Background object in Hierarchy. Under the Mesh Renderer component, open up Materials by left-clicking on the arrow, and change Element 0 to our BackgroundMaterial material. Consider the following screenshot:

    Unity Game Development Blueprints

Now, when we play the game, you’ll see that we now have a complete background that tiles properly.

Scripting 101

In Unity, the behavior of game objects is controlled by the different components that are attached to them in a form of association called composition. These components are things that we can add and remove at any time to create much more complex objects. If you want to do anything that isn’t already provided by Unity, you’ll have to write it on your own through a process we call scripting. Scripting is an essential element in all but the simplest of video games.

Unity allows you to code in either C#, Boo, or UnityScript, a language designed specifically for use with Unity and modelled after JavaScript. For this article, we will use C#.

C# is an object-oriented programming language—an industry-standard language similar to Java or C++. The majority of plugins from Asset Store are written in C#, and code written in C# can port to other platforms, such as mobile, with very minimal code changes. C# is also a strongly-typed language, which means that if there is any issue with the code, it will be identified within Unity and will stop you from running the game until it’s fixed. This may seem like a hindrance, but when working with code, I very much prefer to write correct code and solve problems before they escalate to something much worse.

Implementing player movement

Now, at this point, we have a great-looking game, but nothing at all happens. Let’s change that now using our player. Perform the following steps:

  1. Right-click on the Scripts folder you created earlier, click on Create, and select the C# Script label. Once you click on it, a script will appear in the Scripts folder, and it should already have focus and should be asking you to type a name for the script—call it PlayerBehaviour.
  2. Double-click on the script in Unity, and it will open MonoDevelop, which is an open source integrated development environment (IDE) that is included with your Unity installation.

After MonoDevelop has loaded, you will be presented with the C# stub code that was created automatically for you by Unity when you created the C# script.

Let’s break down what’s currently there before we replace some of it with new code. At the top, you will see two lines:

using UnityEngine;
using System.Collections;

The engine knows that if we refer to a class that isn’t located inside this file, then it has to reference the files within these namespaces for the referenced class before giving an error. We are currently using two namespaces.

The UnityEngine namespace contains interfaces and class definitions that let MonoDevelop know about all the addressable objects inside Unity.

The System.Collections namespace contains interfaces and classes that define various collections of objects, such as lists, queues, bit arrays, hash tables, and dictionaries.

We will be using a list, so we will change the line to the following:

using System.Collections.Generic;

The next line you’ll see is:

public class PlayerBehaviour : MonoBehaviour {

You can think of a class as a kind of blueprint for creating a new component type that can be attached to GameObjects, the objects inside our scenes that start out with just a Transform and then have components added to them. When Unity created our C# stub code, it took care of that; we can see the result, as our file is called PlayerBehaviour and the class is also called PlayerBehaviour. Make sure that your .cs file and the name of the class match, as they must be the same to enable the script component to be attached to a game object. Next up is the: MonoBehaviour section of the code. The : symbol signifies that we inherit from a particular class; in this case, we’ll use MonoBehaviour. All behavior scripts must inherit from MonoBehaviour directly or indirectly by being derived from it.

Inheritance is the idea of having an object to be based on another object or class using the same implementation. With this in mind, all the functions and variables that existed inside the MonoBehaviour class will also exist in the PlayerBehaviour class, because PlayerBehaviour is MonoBehaviour.

For more information on the MonoBehaviour class and all the functions and properties it has, check out http://docs.unity3d.com/ScriptReference/MonoBehaviour.html. Directly after this line, we will want to add some variables to help us with the project. Variables are pieces of data that we wish to hold on to for one reason or another, typically because they will change over the course of a program, and we will do different things based on their values.

Add the following code under the class definition:

// Movement modifier applied to directional movement.
public float playerSpeed = 2.0f;

// What the current speed of our player is
private float currentSpeed = 0.0f;

/*
* Allows us to have multiple inputs and supports keyboard,
* joystick, etc.
*/
public List<KeyCode> upButton;
public List<KeyCode> downButton;
public List<KeyCode> leftButton;
public List<KeyCode> rightButton;

// The last movement that we've made
private Vector3 lastMovement = new Vector3();

Between the variable definitions, you will notice comments to explain what each variable is and how we’ll use it. To write a comment, you can simply add a // to the beginning of a line and everything after that is commented upon so that the compiler/interpreter won’t see it. If you want to write something that is longer than one line, you can use /* to start a comment, and everything inside will be commented until you write */ to close it. It’s always a good idea to do this in your own coding endeavors for anything that doesn’t make sense at first glance.

For those of you working on your own projects in teams, there is an additional form of commenting that Unity supports, which may make your life much nicer: XML comments. They take up more space than the comments we are using, but also document your code for you. For a nice tutorial about that, check out http://unitypatterns.com/xml-comments/.

In our game, the player may want to move up using either the arrow keys or the W key. You may even want to use something else. Rather than restricting the player to just having one button, we will store all the possible ways to go up, down, left, or right in their own container. To do this, we are going to use a list, which is a holder for multiple objects that we can add or remove while the game is being played.

For more information on lists, check out http://msdn.microsoft.com/en-us/library/6sh2ey19(v=vs.110).aspx

One of the things you’ll notice is the public and private keywords before the variable type. These are access modifiers that dictate who can and cannot use these variables. The public keyword means that any other class can access that property, while private means that only this class will be able to access this variable. Here, currentSpeed is private because we want our current speed not to be modified or set anywhere else. But, you’ll notice something interesting with the public variables that we’ve created. Go back into the Unity project and drag-and-drop the PlayerBehaviour script onto the playerShip object. Before going back to the Unity project though, make sure that you save your PlayerBehaviour script. Not saving is a very common mistake made by people working with MonoDevelop. Have a look at the following screenshot:

Unity Game Development Blueprints

You’ll notice now that the public variables that we created are located inside Inspector for the component. This means that we can actually set those variables inside Inspector without having to modify the code, allowing us to tweak values in our code very easily, which is a godsend for many game designers. You may also notice that the names have changed to be more readable. This is because of the naming convention that we are using with each word starting with a capital letter. This convention is called CamelCase (more specifically headlessCamelCase).

Now change the Size of each of the Button variables to 2, and fill in the Element 0 value with the appropriate arrow and Element 1 with W for up, A for left, S for down, and D for right. When this is done, it should look something like the following screenshot:

Unity Game Development Blueprints

Now that we have our variables set, go back to MonoDevelop for us to work on the script some more.

The line after that is a function definition for a method called Start; it isn’t a user method but one that belongs to MonoBehaviour. Where variables are data, functions are the things that modify and/or use that data. Functions are self-contained modules of code (enclosed within braces, { and }) that accomplish a certain task. The nice thing about using a function is that once a function is written, it can be used over and over again. Functions can be called from inside other functions:

void Start () {

}

Start is only called once in the lifetime of the behavior when the game starts and is typically used to initialize data.

If you’re used to other programming languages, you may be surprised that initialization of an object is not done using a constructor function. This is because the construction of objects is handled by the editor and does not take place at the start of gameplay as you might expect. If you attempt to define a constructor for a script component, it will interfere with the normal operation of Unity and can cause major problems with the project.

However, for this behavior, we will not need to use the Start function. Perform the following steps:

  1. Delete the Start function and its contents.

    The next function that we see included is the Update function. Also inherited from MonoBehaviour, this function is called for every frame that the component exists in and for each object that it’s attached to. We want to update our player ship’s rotation and movement every turn.

  2. Inside the Update function (between { and }), put the following lines of code:
    // Rotate player to face mouse
    Rotation();
    // Move the player's body
    Movement();

    Here, I called two functions, but these functions do not exist, because we haven’t created them yet. Let’s do that now!

  3. Below the Update function and before }, put the following function to close the class:
    // Will rotate the ship to face the mouse.
    void Rotation()
    {
    // We need to tell where the mouse is relative to the
    // player
    Vector3 worldPos = Input.mousePosition;
    worldPos = Camera.main.ScreenToWorldPoint(worldPos);

    /*
       * Get the differences from each axis (stands for
       * deltaX and deltaY)
    */
    float dx = this.transform.position.x - worldPos.x;
    float dy = this.transform.position.y - worldPos.y;

    // Get the angle between the two objects
    float angle = Mathf.Atan2(dy, dx) * Mathf.Rad2Deg;

    /*
       * The transform's rotation property uses a Quaternion,
       * so we need to convert the angle in a Vector
       * (The Z axis is for rotation for 2D).
    */
    Quaternion rot = Quaternion.Euler(new Vector3(0, 0, angle + 90));

    // Assign the ship's rotation
    this.transform.rotation = rot;
    }

    Now if you comment out the Movement line and run the game, you’ll notice that the ship will rotate in the direction in which the mouse is. Have a look at the following screenshot:

    Unity Game Development Blueprints

  4. Below the Rotation function, we now need to add in our Movement function the following code:
    // Will move the player based off of keys pressed
    void Movement()
    {
    // The movement that needs to occur this frame
    Vector3 movement = new Vector3();

    // Check for input
    movement += MoveIfPressed(upButton, Vector3.up);
    movement += MoveIfPressed(downButton, Vector3.down);
    movement += MoveIfPressed(leftButton, Vector3.left);
    movement += MoveIfPressed(rightButton, Vector3.right);

    /*
       * If we pressed multiple buttons, make sure we're only
       * moving the same length.
    */
    movement.Normalize ();

    // Check if we pressed anything
    if(movement.magnitude > 0)
    {
       // If we did, move in that direction
       currentSpeed = playerSpeed;
       this.transform.Translate(movement * Time.deltaTime *
                               playerSpeed, Space.World);
       lastMovement = movement;
    }
    else
    {
       // Otherwise, move in the direction we were going
       this.transform.Translate(lastMovement * Time.deltaTime
                               * currentSpeed, Space.World);
       // Slow down over time
       currentSpeed *= .9f;
    }
    }

    Now inside this function I’ve created another function called MoveIfPressed, so we’ll need to add that in as well.

  5. Below this function, add in the following function as well:
    /*
    * Will return the movement if any of the keys are pressed,
    * otherwise it will return (0,0,0)
    */
    Vector3 MoveIfPressed( List<KeyCode> keyList, Vector3 Movement)
    {
    // Check each key in our list
    foreach (KeyCode element in keyList)
    {
       if(Input.GetKey(element))
       {
         /*
           * It was pressed so we leave the function
           * with the movement applied.
         */
        return Movement;
     }
    }

    // None of the keys were pressed, so don't need to move
    return Vector3.zero;
    }
  6. Now, save your file and move back into Unity. Save your current scene as Chapter_1.unity by going to File | Save Scene. Make sure to save the scene to our Scenes folder we created earlier.
  7. Run the game by pressing the play button. Have a look at the following screenshot:

Unity Game Development Blueprints

Now you’ll see that we can move using the arrow keys or the W A S D keys, and our ship will rotate to face the mouse. Great!

Summary

This article talks about the 2D twin-stick shooter game. It helps to bring you to familiarity with the game development features in Unity.

Resources for Article:


Further resources on this subject:


1 COMMENT

LEAVE A REPLY

Please enter your comment!
Please enter your name here