Unity3D Workshop – 01 – Invading Space

Hello and welcome to this game development workshop, for this series we will be using the ‘Unity 3D’ engine (4.0.1 at time of writing) to be the backbone of our projects. The goal across all of these workshops is to learn what elements go into making a game, and some of the roles that are available to you as part of making games. Since we are going to be using the Unity3D engine before we get too far into introductions, let’s take a look at the engine itself.

Open up your web browser and download the latest version of Unity,  available here: http://unity3d.com/unity/download/

So you may be wondering, “What is Unity3D, and why are we using it?”.  Unity3D is a powerful game creation editor and engine that can be deployed to multiple platforms. There are numerous SDKs (Software Development Kits)  that are either free or low-priced (especially for students) available for building games including: GameMaker, Flash, Unreal, XNA, and others. We’ll be using Unity because while free, and though it does do much of the ground work for us, it still leaves enough for us to dig in and get our hands dirty. Many of the retail games you may be familiar with are made with Unity for a variety of platforms and devices. You can see some of the big ones on their site: http://unity3d.com/gallery/made-with-unity/game-list

As we make our way through these workshops we will examine not only programming but art, sound, design and many other areas of game development. You may not feel skilled in every area of game development but I encourage you to take part in every exercise. In a large-scale professional setting, it is very likely that you would be using an engine and/or tools created in house. The experience you gain from these workshops is designed to line up with what you would experience as an entry-level developer. Working on any size project with a team and having a basic understanding of the various roles you may encounter and their tasks will aid you in communication.  Remember, there is no grade at the end of this workshop, placeholder assets and full code examples will be available for all the steps should you find yourself struggling. So you have nothing to lose!

Once everything is downloaded and up and running, let’s take a quick look around the Unity editor. We will be spending a lot of time in there so it will be good to be familiar with how to navigate it. All of the reference screenshots will be in the default layout, however there are many different pre-sets and you are free to dock windows wherever you like, this is a great feature, especially if you’re using multiple monitors. Let’s make one small change to the default layout, pull the game preview tab out from behind and dock it to the right of the assets panel, this can be done by left clicking on the table and dragging it into position.

Step 0: Editor Customization

With each workshop we are going to look a few existing games that share common gameplay style and features.  This being the first workshop, we are going back almost to the beginning of video game history with a 1978 classic, designed by Tomohiro Nishikado. The game of course, is ‘Space Invaders‘ a game that features gameplay design that is still used today.

Space Invaders – 1928 Titan Attack – 2012

The gameplay here is the player controls an object that is locked to a single axis of movement and fires projectiles at enemies who move about the screen and can fire back.  Hundreds of games have use this concept with minor changes, for example, simply rotate the game 90 or 180 degrees and you have a completely different feeling game.

To start making our own version, we are going to setup a simple background image for our project to use.  Now as you might not have known, the original arcade version of ‘Space Invaders’ had no background, later it was faked by using a piece of cardboard. With the advances in hardware since the 1970s we can avoid the use of cardboard for making our background. Instead, we will use one of the default objects that are part of the Unity editor, the ‘Plane’. Creating one is simply click on the create button in the from the Hierarchy tab on the left and selecting plane from the pull down menu.

Step 1: Adding the plane to our project.

This creates a new ‘plane’ object in the world and adds it to the list of items in our ‘object hierarchy’, your screen should look something like this:

Step 2: Plane to see

Now there is a lot of new information here, our ‘Plane’ is made up a grid of 10×10 unit squares each made up of a pair of triangles, you can see the wire frame that makes up the object when it selected.  Additionally, the object inspector on the right is loaded with all sorts of new options, which are organized as ‘Components’.  Unity3D is best when used as a composition based object creation, objects are built by combining independent parts.  Roughly the difference between building a toy car out of blocks instead of carving one out of a single piece of wood.  Our plane being a built in object comes preloaded with a few default components that are common enough to assume that we will want to have them.

Before we start working with that, a brief disclaimer: we will not be focusing on optimizations this early in the workshop.  While, internally I would be screaming if I found someone using 200 polygons to make a square that could be done with only 2 triangles, don’t worry, we’ll come back around to this later.  When dealing with 3D graphics, polygons, most often triangles, are the basic building blocks. While definitely not the only aspect that goes into the ‘quality’ of graphics it is an important part. For the vast majority of this project we will be dealing with games in 2D, we will touch on the importing of 3D models for use later in the workshops.

Right now all we have is a simple gray square that is not very exciting and offers very little gameplay value.  This drives us to another of the major elements that is needed for our project’s graphics, which is the texture. In our case with today’s project being fully 2D the texture will be pretty much all that determines our graphics. Also for today’s project, we will be working with an 16:9 aspect ratio. This is relative number of pixels, 9 pixels vertically for every 16 pixels horizontally. This aspect ratio is very common and likely what is used for any monitor, television, or phone that you may use.

Here is the placeholder background that will be used in any of the following screenshots, make sure to get the full size version and not the thumbnail:

A star filled sky.

As a professional, I am a programmer not an artist as you can easily see.  So this is a great chance try your hand at making your own textures. I used MSPaint to make my background, but there are numerous tools out their you can use to make a texture. For our needs, anything that can save a file in ‘.png’ format will work, and for the background I recommend using a canvas size of 1280×720, or any image with a 16:9 aspect ratio so it won’t be stretched unevenly will work just fine.

Importing assets into our project is as simple as dragging the image file from where it is saved into the project tab in the bottom left. It will take a brief second to import and we will be able to use it.  I had already made a folder for textures and scripts to help me organize the assets for the project, we will only be using a few assets for this so you could do fine with out folders, but building a good habit for this will be a huge time saver down the road.

To create a folder, simply click on ‘Create’ right under project tab in the bottom left and select folder which you can then immediately rename.

Step 3: Everything in it’s place.

To apply it to our ‘Plane’ it is the nearly the same process, you can just drag the texture from the assets folders and drop it onto the ‘Plane’ in our either in the object hierarchy or the object in the editor view. While were in that area, we should rename our ‘Plane’ to something more appropriate such as ‘Background’, right clicking on the object name will present a context menu with the ‘Rename’ option.

If everything is still on track, we should all be seeing something close to this:

Step 4: A plane with a name.

That’s a good bit of progress for a little mouse work, a texture on that gray square goes a long way. However, we’re still not seeing anything down in the game preview window at the bottom. This is because our plane is two dimensional and exactly in line with our camera, it would be essentially holding up a piece of paper exactly at our eye level. Except in this case, it is the game camera not our eye, and the piece of paper is infinitely thin, which makes it effectively invisible.

Easy enough problem to fix, you can either move the camera or the ‘Background’, in this case we will do the latter. Pressing ‘e’ which is the hot-key for rotate mode in the editor we can click the rotation rings and adjust our objects rotation. Holding down ‘control’ will lock the rotation into 15degree increments. For a complete list of all the hot keys you can refer to this list.

You may have notice that depending on which way the object rotated, that it disappeared even from our editor window.  The reason for that is the default setup for polygons used in the editor are ‘Front Facing’, this means that you can only see them if you are viewing them from their front, similar to how a one way mirror works.

With a little trial and error, you should be able to find that the target rotation you want for the background to face the camera is ( 90:X, 180:Y, 0:Z ).  If you are not seeing this, double check that the ‘Background’ object position is at the origin (0:X, 0:Y, 0:Z) and the camera is positioned a bit back on the Z axis (0:X, 0:Y, -10:Z) and not rotated. It is very easy to nudge things out of position, and lose sight of objects.

Step 5: A texture book example

At this point you may be wondering why the texture is looking a bit darker than the source file, the problem is a lack of lighting. With a quick couple of clicks you can adjust the ambient lighting to a solid white light.  Another option would have have been changing the textures to be ‘unlit’ and draw fully without reference the project’s lighting, but since this project is not doing any complex lighting making this global change is the simpler solution.

Step 6: Let there be light.

The difference is night and day, and makes it real easy to see what is going on, but before we continue with camera changes we are going to toss a few generic objects into our project to help us visualize the next change. The example I used was a pair of cubes added the same way we did for the plane.  The are positioned slightly offset from each other, enough to see both and have them appear to be different sizes in the ‘Game’ preview window.

Having these cubes here will help us highly the differences between a ‘perspective‘ camera and an ‘orthographic‘ one. The perspective camera uses all three dimensions when drawing an object, just like the human eye works, objects look smaller the farther away they are. By moving the cube around in the editor you should see it grow smaller or larger in the game preview, despite the objects being the same size.

The ‘orthographic’ camera removes this effect, and sees everything only in two dimensions, so the by switching the camera to that mode, the two squares snap back to appearing as the same size, as highlighted in the image below.

How to remove a dimension.

To switch camera modes, you need to select the ‘Main Camera’ out of the object hierarchy as you would do for any other object and then adjust the ‘Projection’ setting in the object inspector. You may have also noticed that the ‘Depth of Field’ setting also changed to ‘Size’. Think of this ‘Size’ as if you were looking at piece of graph paper, every square in one direction would be one unit of ‘Size’, for our project we will be using a ‘Size’ of 10 mainly to keep the math simple. This gives us a total of ‘Size’ of 20 units 10 above and 10 below the center of the camera on the y-axis.

The math on the x-axis is a little more complex, as you recall we are using a 16:9 aspect ratio for our game. Let’s switch the preview window to that mode but adjusting it in the pull down menu which currently says ‘Free Aspect’.

Step 7: Not what you aspected

To figure out how big our space is on the x-axis it takes just a bit of math:

20 (total vertical height) / 9 (vertical aspect) * 16 (horizontal aspect) = 35.55~ units wide.

A total size 20 x 35.55~ for the play area will be great for the project, however you may have noticed that our background does not fit fully into our preview window. To scale it up, just hop back over to the object in the hierarchy and then set the size in the ‘scale’ part of the transform area in the object inspector. If you remember from before, the plane was a 10×10 grid of squares, and luckily, each one of the squares is the same size of the unit used by the camera, this makes scaling the background very simple. Setting the scale to (3.55:X, 1:Y, 2:Z) will fit the plane perfectly filling the camera’s view.

Step 8: Drawn to scale

Despite the fact that many believe that programmers are supposed to love math, most really only love simple math. To help keep things simple, take a quick second to move the positions of the camera and the background to be positive 10 on the y-axis, it’ll pay off later. As for the two cube companions, only one of them can survive to the next step, delete one from the object hierarchy and rename the survivor as ‘Player’ because it’s time to put some game into this project.

The player object is going to need it’s own texture, as with the background you can use anything you would like for the the player. However, the player is going to keep it’s square shape, so the texture we will use is a 1:1 aspect ratio. Below is the placeholder texture to use, if you are making your own, 128×128 pixels is the recommended size.

The goal was a tank.

Just like before, smoothly drag the texture into the proper folder inside of the Unity3D editor, and then drag that texture onto the ‘Player’ object. Unlike the background, which was solid in it’s entirety, the player object needs to make use of ‘transparency’ or the ‘alpha‘ channel.  The .png files used for this project have an alpha layer which dictates what parts are see through or not.  Other setups are done using the ‘green screen‘ method picking once color of the image to be ignored or replaced.

A single setting takes care of it in a snap. If this does not work for you custom texture, make sure the editor you are using allows for transparency when saving the file as a .png

Step 9: Transparency in game development

As you can see, while setting the transparency, it was also a good time to rotate the object so it was facing up right to the camera, scale it up a bit, and move it’s position up to where it looked good on the background, all things doable in the ‘Transform’ component of the inspector.

Now up to this point, you have done everything in the project by just composting elements together by dragging and dropping followed up by small modifications in the inspector. However, the time to do some coding has arrived, and to do that you will need to make a script, and for this workshop you will be working with C# as the default language. To make a script once again use the create button in the project tab and select ‘C# Script’ then name it ‘PlayerInput’.  In the example image the script was created in an aptly named ‘Scripts’ folder.

Step 10: Stick to the script

Scripts can not be edited in the primary Unity3D editor, it will require a much more complete text editor.  The good news is that Unity comes with it’s own script editor called ‘MonoDevelop’ and will open automatically if you double click on the script you just made.

Step 11: Or step 3 in binary

The Unity engine already handles much of the low level input for you, everything you need for this project is already setup by default.  However, a quick quick look at these settings to get familiar with where they can be found later, is a good idea.

Step 12: Seizing control

Notice how there are already two definitions for ‘Horizontal’? This is because the Unity engine supports publishing for many platforms and devices, being able to use the same name for input saves a lot of time when publishing cross platform.

Switching back to MonoDevelop you just need to add a few lines to our Update function. The player input can be read from the global ‘Input’ object by asking it for the ‘Horizontal’ axis value.  The Unity engine and C# already provide many functions and abilities for you to use.  In this case ‘Input’ is a common element for all projects, and is known as a ‘Global’ object mean it can be found and accessed everywhere.

float fXInput = Input.GetAxis("Horizontal");

To adjust the object’s position, which is stored as part of the ‘transform’ component on the object, this is the same transform component you have been making changes to inside of the editor up to this point, you are just accessing it from code while the project is running.

transform.Translate(-fXInput, 0.0f, 0.0f);

Put both of the lines together in the update function and you end up with:

    // Update is called once per frame
    void Update ()
    {
        // We are going to read the input every frame
        float fXInput = Input.GetAxis("Horizontal");
        // We move the player left or right
        transform.Translate(-fXInput, 0.0f, 0.0f);
    }

One thing to not here, the lines that start with two slashes, colored green in this example are known as ‘Comments’ these are notes left by developers to remember what code is or at least should be doing, they are ignored by anything non-human.

Save this file in MonoDevelop, and switch back to the Unity editor and drag the script from the assets folders onto the ‘Player’ object exactly how you did for the texture.  Now you can test the project to make sure that your script is working, simply click the play arrow at the top of the screen and you should then be able to make the player object move left and right by using the arrow keys, a / d, or a connected gamepad, our first bit of gameplay.

It should look very close to this example.

Not bad for just two lines of codes, but there are definitely a lot that can still be done, first off issue to address is that it is very easy to slide right off the edge of the screen. The fix for that is very strait forward, switching back to MonoDevelop and the ‘Update’ function in the ‘PlayerInput’ file you can add in some checks to keep the player inside of the play space.

    // Update is called once per frame
    void Update ()
    {
        ...

        // Make sure we're inside the bounds of our play space
        //  NOTE: This is a non-optimal solution
        if(transform.position.x < -14.0f)
        {
            transform.position = new Vector3(-14.0f, 2.0f, 0.0f);
        }
        else if(transform.position.x > 14.0f)
        {
            transform.position = new Vector3(14.0f, 2.0f, 0.0f);
        }
    }

Working with computers is purely binary, or ‘yes’ and ‘no’ type interactions. You have just used a pair of very simple conditional statements which read like math problems comparing two numbers or yes/no questions. Such as:

if(transform.position.x < -14.0f)
{
  .A.
}
else if(transform.position.x > 14.0f)
{
  .B.
}

Translating such conditionals to speakable english would be:

if our position is less than -14 do ‘A’
else if our position is greater than 14 do ‘B’

Breaking problems down in basic yes/no logic is a skill that will always be useful to a programmer, there are more tools and complex conditionals and they will be touched as needed.

Congratulations, with these two conditionals, you have just solved your first code bug. Notice that there is a comment pointing out that this code is a non-optimal solution, this will be a place for those interested in deeper code exploration to dig in and spend some time improving the code of others. A task that most programmers will undertake at one time or another.

This is also a good place where you can make a game play decision: “How far the player can move on the play space?” and “How fast can the player move?” simple questions like this make up a large part of game play balance and ultimately the ‘fun’ of a game.

This will be very clear when moving into the next feature to add to your project, that ability to fire a projectile. Many of these steps you have already done and as you likely guessed first you will need to start off with an image to represent the projectile. Below are two examples of possible place holder art:

Drop these into your texture folder or if you are creating your own stick with the name of ‘Projectile_01’ and ‘Projectile_02’ to stay consistent with the rest of the steps to follow. The place holder images above were created as 128×128 pixel images, also with transparency support. Up until this point, the Unity editor has handle all of the material creation for objects, these which were automatically generated when we placed the textures onto the objects.

While the texture is the raw data creating a picture, a material is a combination of many modifiers and often multiple textures.  You could have two coins in your pocket with the same image on them, but one might be shiny or rough or bumpy, these differences are what are combined to make materials.

In the case of the projectile the approaching will be a bit differently, you will want to make the materials by hand. Change to the material folder and create a material by either right clicking in the folder and navigating to create → material or by using the create pull down under the project tab. Then name it ‘Projectile_01’ and head over to the object inspector.

Inside the object inspector for our new material you can see it’s set to nothing, click on select and pick the projectile, then at the top where it says ‘Shader’ like with the player object, you want to select ‘Transparent → Diffuse’ as the material type.

Step 13: Material concerns

Repeat this process for the other projectile, and you should then have four different textures that look like this:

On a side note, the slider at the bottom right of the asset windows will allow you to scale the icons for each object, this can be handy when the folders start to fill up.

Next step is to create a fresh script, and call it ‘Projectile’, then open it up into MonoDevelop. Like before with the player object, this projectile needs to move to move, and that happens in the update function.

public class Projectile : MonoBehaviour
{
    // Local variables
    float m_fProjectileSpeed = 0.5f;

    ...

    // Update is called once per frame
    void Update ()
    {
        // Our project moves on it's own without needing player input
        transform.Translate(0.0f, m_fProjectileSpeed, 0.0f);

        if(transform.position.y > 21.0f)
            DestroyObject(gameObject);
    }
}

This was also a good time to set the default speed for the projectile, this will be something you can  customize.  Take not of the ‘DestroyObject’ function, this function is common to all objects in Unity and the use here is to have the object delete itself.  A process generally refereed to as ‘clean up’ or ‘garbage collection‘ some systems perform this task automatically but many performance conscious systems do not and leave that work to the programmers.  This is important because computers have limited resources such as ‘ram’ and if objects are not cleaned up it will cause the program to crash.

This is just what a projectile will do when it updates, to actually create a new projectile, you need to go back to our ‘PlayerInput’ script and setup code to listen for the ‘Fire1’ button.

public class PlayerInput : MonoBehaviour
{
    ...

    // Update is called once per frame
    void Update ()
    {
        ...

        // Check if the player press the fire button
        //  'left mouse' 'left control' or 'button 0' on the game pad
        bool bFirePressed = Input.GetButtonDown("Fire1");
        if(bFirePressed == true)
        {
            // Create a new shot
            GameObject pNewObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
            pNewObject.name = " Player_Projectile";
            pNewObject.AddComponent("Projectile");
        }
    }
}

Input buttons work differently than an analog axis would. They have states of ‘Up’ and ‘Down’ if you were making a game where holding down a button would charge a shot, using the time between ‘Down’ → ‘Up’ would be a great way to add that feature, something to remember for later.

Input buttons work differently than an analog axis would. They have states of ‘Up’ and ‘Down’ if you were making a game where holding down a button would charge a shot, using the time between ‘Down’ → ‘Up’ would be a great way to add that feature, something to remember for later.

Take a look at the new code that is being using to create a projectile line by line.

GameObject pNewObject = GameObject.CreatePrimitive(PrimitiveType.Cube);

Here a basic or ‘primitive’  cube is being used as the object for the new projectile, this is the code equivalent to adding a cube to the object hierarchy like you did for the player object.

pNewObject.name = " Player_Projectile";

The object is given a name, just as would rename it in the object hierarchy.  Even though the projectile objects only exist temporarily, having a descriptive name for it would make later problem solving and ‘debugging’ much easier.

pNewObject.AddComponent("Projectile");

Last but not least,  giving the new object the ‘Projectile’ script, which is referenced here as a component.  This would have been the same as placing the ‘Player Input’ script on ‘Player’ object. As you can see, you can accomplish much the same results by very different methods, the trick is knowing the right time to use each. In this case, the projectiles are short lived objects, unlike the player object which is persistent for the entire game. This makes the creation of the projectiles manually into the game space not a viable solution.

Take a quick moment to try out your project and see how well the projectiles work. A demo at this point is available here

Step 14: A long shot

On the plus side if you watch the space in the object hierarchy in the upper left, we see that the projectiles are being created when you press the fire button and then destroyed after they pass the top of the screen. On the down side, the projectiles are all being created from the center of the play space and that is definitely a bug in this feature, most players like to be able to aim.

Additionally, it is only shooting raw cubes, and not the one of the textures we setup earlier. Now you could go into the ‘Projectile’ script and assign the texture there. However, since we are are basing this off a game where the enemies fire back, a better solution would be make changes on the player object so we can reuse the projectile script for the enemies.

Back into ‘PlayerInput’ to add some new variables at the top of the file.

public class PlayerInput : MonoBehaviour
{
    // Projectile type
    public Material m_pProjectileType = null;
    public float m_fProjectileSpeed = 0.5f;

    …
}

The ‘m_pProjectileType’ here is a local ‘member’ variable and is defined outside the start function at the top of the file. The naming convention here is know as ‘Hungarian notation‘ now to be honest, there have been thousands of hours lost in the game industry debating what the best way to name things.

The reason for such a heavy emphasis on picking good names is that a good name helps you remember what you are working with. In this case, the ‘m’ before the underscore represents ‘member’ which means the variable is part of this object itself, while a ‘g’ would represent a variable that is globally accessible. The lower case ‘p’ designates this as a ‘pointer’ type, we will go into greater detail as we use these more.

One nice feature of the Unity editor, but placing the ‘public’ keyword in front of the the variables become visible back in the object inspector.

Step 15: Public Access

Here you can adjust the material to use on the projectiles created by the player, and the speed in which the projectiles move, select one of the projectile materials that you setup earlier. The ability to do this is a huge time saver as projects get larger allowing you to make changes quickly without having to adjust the scripts. Additionally, you could have different settings for the same script on different objects in the editor.

One more small change needs to be done in the ‘PlayerInput’ script before moving onto the ‘Projectile’ script. The process of actually telling the newly created projectile the settings that were just added to the Player object, and you do so like this:

public class PlayerInput : MonoBehaviour
{
    ...

    // Update is called once per frame
    void Update ()
    {
        ...

        if(bFirePressed == true)
        {
            // Create a new shot
            GameObject pNewObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
            pNewObject.name = " Player_Projectile";
            Projectile pNewProjectile = (Projectile)pNewObject.AddComponent("Projectile");
            pNewProjectile.Init(gameObject, m_pProjectileType, m_fProjectileSpeed);
        }
    }
}

Now when a new projectile is created, it is given the a few of the values saved by the object that created it.  A quick note, the MonoDevelop might give you a warning that ‘Init’ is not a valid function to call on a ‘Projectile’ object, don’t worry that is to be expected be cause you are going to add that now by switching over to the ‘Projectile’ script.

public class Projectile : MonoBehaviour
{
    // Local variables
    GameObject m_pOwner;
    float m_fProjectileSpeed = 0.5f;

    // The constructor for this class
    public void Init(GameObject pOwner, Material pMaterial, float fProjectileSpeed)
    {
        // Remember who made us
        m_pOwner = pOwner;

        // Projectiles start where their owner was
        transform.position = m_pOwner.transform.position;
        transform.Rotate(0.0f, 0.0f, 180.0f);

        // How fast are we going to move?
        m_fProjectileSpeed = -fProjectileSpeed;

        // Apply the material
        renderer.material = pMaterial;
    }

    …
}

This new function ‘Init’ has a lot of new information in it, so time to go over it line by line in detail.

public void Init(GameObject pOwner, Material pMaterial, float fProjectileSpeed)

This is the ‘definition’ for the function, as with the variables the ‘public’ keyword allows the function to be seen outside of the object, but in this case it is visible to other parts of code and is not something you would see in the editor. The ‘void’ keyword is what this function will return when it finishes back to what called the function, in this case ‘void’ is simply saying ‘nothing’. Finally, the next three parts inside of the parentheses are variables that are being passed in to use be used inside of the function.

// Remember who made us
m_pOwner = pOwner;

// Apply the material
renderer.material = pMaterial;

// How fast are we going to move?
//   Speed is negated to adjust for object rotation
m_fProjectileSpeed = -fProjectileSpeed;

This lines are all assignments, the three variables sent to this object are stored in it. The ‘renderer’ is a intrinsic or default part of the object, and already has a spot to assign the material to.

// Projectiles start where their owner was
transform.position = m_pOwner.transform.position;
transform.rotation = m_pOwner.transform.rotation;

The final part of the function is where we set the initial position of the projectile to be wherever the calling object is at the time, and then rotate the object so the texture is facing up the right direction.

Save the files and give the project another go, if everything went according to plan, it should look just like this.

All this shooting is looking good, however without something to shoot at the fun runs out rather quickly, so time make a target to shoot at. This is our last new art asset for the project, and definitely saved my best art for last, behold the evil Space Pigeon!

Evil but Cute

Taking the simple approach here, you can create this frightful creature the same way as you did for the player object. Create a cube named ‘Enemy’ in the object hierarchy, import and apply the texture to the cube, and then place the cube in a nice center spot on the game area. Don’t forget to set the shader for the material as ‘Transparent/Diffuse’.

Step 16: Evil takes flight

If you test the project now, you will quickly notice that the player’s projectiles simply pass through the enemy with no effect. The reasons is that basic simple collision detection has to be setup to make the projectiles effective. The first step towards this goal is setting the ‘box collider’, a component that is created on cubes automatically, as a trigger simply by checking the box ‘Is Trigger’.

Step 17: Collusion

The unity editor allows use to ‘multi-edit’ objects, so you can change the ‘Is Trigger’ setting on both the player and the enemy at the same time by simply selecting both in the object hierarchy while holding down the ‘control’ key.

The second half of this task is done back in the MonoEditor in the Projectile.cs file. First off you are going to add a new component to the projectile inside the ‘Start’ function. The ‘Start’ function for objects in Unity is special, like the Update function and many others it is something that all ‘MonoBehaviour’ based objects have. The ‘Start’ function is called only once right before the ‘Update’ is called for the first time.

public class Projectile : MonoBehaviour
{
    // Local variables
    GameObject    m_pOwner;
    Rigidbody    m_pRigidBody;

    ...

    // Use this for initialization
    void Start ()
    {
        m_pRigidBody = (Rigidbody)gameObject.AddComponent("Rigidbody");
        m_pRigidBody.useGravity = false;
    }

    …
}

The new code is adding a ‘Rigid Body’ to all of the projectiles that are created, this is the basic piece of collision physics for many games. Up until now nothing in the project had any mass or substance, like a hologram of a ghost. By creating a rigid body for the projectiles, you can easily add object interactions. Please note, as before, this is not an optimal solution for this problem, but it’s simplicity out weighs it being inefficient.

The only custom setting that you need to apply to the rigid body of the projectile is turning off gravity for it, adding gravity wouldn’t be beneficial and would throw off the settings you have already made. Now that you are done with the ‘Start’ function, and made both the player and the enemy into ‘Triggers’ the projectile’s rigid body has three ways to interact with them.

OnTriggerEnter – The first time the rigid body touches the trigger
OnTriggerExit – The last time the rigid body touches the trigger
OnTriggerStay – Every update that the rigid body is touching the trigger

For needs of this project, you want to use ‘OnTriggerEnter’ since all the work you want to do is the first time the rigid body touches one of the triggers. Go ahead and add that as a new function to the ‘Projectile’ script.

public class Projectile : MonoBehaviour
{
    ...

    void OnTriggerEnter(Collider pOther)
    {
        // We don't want to hit the object that fired us
        if(pOther.gameObject == m_pOwner)
            return;

        // Tell whatever we hit to take damage
        pOther.gameObject.BroadcastMessage("TakeDamage", 1.0f);

        // This projectile can only hit one thing
        DestroyObject(gameObject);
    }
}

The ‘BroadcastMessage’ is something new, so a quick pause to take a closer look at this. Up until now, every time function calls have been made very precisely, by calling public functions on the object itself. There are however many cases where you cannot be that exact. In such a case you can use ‘BroadcastMessage’, in essence you are shouting at the object “Anyone have a ‘TakeDamage” function!?’ and then every component is checked to see which if any has a ‘TakeDamage’ function. Because right now the ‘TakeDamage’ function is not defined on any of the components, nothing will happen.

Which leads right into the final stretch of the project, setting up a script for the enemy.  This time to create a new script, you can do it right from MonoDevelop by right clicking on the script folder in the upper left and then add → new file. Inside of the popup window we select unity → C# script and give it the name ‘Enemy’

Step 18: Code Creation

public class Enemy : MonoBehaviour
{
    // Local variables
    float m_fReenableTime;            // When we re-enable the render for this object
    public float m_fXSpeed = 0.2f;    // How fast this object moves horizontally
    public float m_fYSpeed = 0.2f;    // How fast this object moves vertically

    // Use this for initialization
    void Start ()
    {

    }

    // Update is called once per frame
    void Update ()
    {
        // Turn our rendering back on if it was off and enough time has passed
        if(renderer.enabled == false && Time.time > m_fReenableTime)
            renderer.enabled = true;

        // Move our object on the screen
        transform.Translate(m_fXSpeed, Mathf.Sin(Time.time * 5.0f) * m_fYSpeed, 0.0f);

        // Check play area boundaries
        if(transform.position.x < -14.0f && m_fXSpeed > 0 ||
          transform.position.x > 14.0f && m_fXSpeed < 0)
        {
            m_fXSpeed = -m_fXSpeed;
        }
    }

    // React to taking damage
    void TakeDamage(float fAmount)
    {
        // Turn off the rendering of this object for a while
        renderer.enabled = false;
        m_fReenableTime = Time.time + 2.0f;
    }
}

The last script is a big block of code to take in all at once, time to break it down into smaller pieces.

    // Local variables
    float m_fReenableTime;            // When we re-enable the render for this object
    public float m_fXSpeed = 0.2f;    // How fast this object moves horizontally
    public float m_fYSpeed = 0.2f;    // How fast this object moves vertically

This code is setting up local variables for this script, to make it more interesting the enemy should move around the screen, to do that you need to give it some speed values. They are public once again to let you change them quickly in the Unity Editor.

    // React to taking damage
    void TakeDamage(float fAmount)
    {
        // Turn off the rendering of this object for a while
        renderer.enabled = false;
        m_fReenableTime = Time.time + 2.0f;
    }

This is the new ‘TakeDamage’ function that is being broadcasting to from the projectile when collision between the two is occurs. The function that reacts to damage is simple, the enemy is just made invisible for a short amount of time by disabling the object’s renderer.   The damage ‘fAmount’ variable we send this function is not actually used, however if the enemy had ‘heath’ you would find that variable to very useful.

    // Update is called once per frame
    void Update ()
    {
        // Turn our rendering back on if it was off and enough time has passed
        if(renderer.enabled == false && Time.time > m_fReenableTime)
            renderer.enabled = true;

        // Move our object on the screen
        transform.Translate(m_fXSpeed, Mathf.Sin(Time.time * 5.0f) * m_fYSpeed, 0.0f);

        // Check play area boundaries
        if((transform.position.x < -14.0f && m_fXSpeed > 0) ||
          (transform.position.x > 14.0f && m_fXSpeed < 0))
        {
            m_fXSpeed = -m_fXSpeed;
        }
    }

The update function has some similar parts to the ‘PlayerInput’, you should recognize the ‘transform.Translate’ and the boundary check. However it is not using the player input but instead a flat ‘m_fXSpeed’ to determine how fast and which direction the enemy is moving. For a little extra flare, ‘m_fYSpeed’ is being used to add some vertical motion regulated by a sine wave.

The very first part of the update function is where some basic logic is performed. However, there are some new pieces of syntax to learn. Sometimes you need the code consider multiple pieces of data before making an yes/no decision, you can do that by combining and grouping the simple conditionals.

A && B → means ‘A and B’ need to be true
A || B → means ‘A or B’ need to be true
!A → means ‘not A’ needs to be true
^ this on is tricky it is using a double negative in programming ‘not false’ would cause the condition to be true.

Just like with algebra, these conditionals also respect an order of operations, in the bottom part of the ‘Update’ function we use parentheses to group conditionals together:
(A and B) or (C and D)

That may be a bit complex all at once, but the more you use these conditionals the easier it will become.

Back to the project and to the Unity Editor, if we place the ‘Enemy’ script onto the enemy object when you run the project you should now have a moving target to shoot, something like this.

With that you have reached the end of this first workshop, take some time to customize your projects. Consider new art, having the enemy shoot back, allowing the player to move vertically, add health or multiple enemies, be creative!