Creators – Starting Our First Game

This week we started our first game in earnest. Let’s talk about the design and the steps we took to begin implementing it.

PinBowling.jpg

Game Design

The game involves a simple play area with pins. The players tries to knock down the pins by controlling the direction and force at which the ball is projected. The number of pins knocked constitutes the score. The game shares element of classic games such as pinball, bowling and skittles, to name a few.

Setting up the play area

To establish the play area, we used a plane (for the ground) and four cubes stretched to size to provide the walls:

gameboard

Because we don’t want gaps in our walls, we’ve been careful to be precise with the positions of everything.

Applying a Force to our Sphere

We added a sphere to our scene and made sure that it had a RigidBody body component. The RigidBody component makes it so that the physic engine takes care of the movement of the sphere.

To test adding a force to the sphere we added a temporary script to the sphere and had it add a force to the RigidBody as soon as the game starts.

Immediately it was clear that the force was too weak, so we added a property to the script which allowed us to scale the force. In testing 1000 proved to be a good value. Here is the script:

 using UnityEngine;
 using System.Collections;
 
 public class PushSphere : MonoBehaviour 
 {
   public float PushStrength = 1.0f;
 
   // Use this for initialization
   void Start ()
   {
     Rigidbody rb;
     rb = GetComponent<Rigidbody> ();
     rb.AddForce (Vector3.back * PushStrength);
   }
   
   // Update is called once per frame
   void Update () 
   {
   }
 }

 

We also experimented with creating a physic material and assigning it to the sphere. Different levels of friction and bounciness give different behaviours.

Testing With a Single Pin

To test the sphere colliding with a pin we added a single cylinder to the scene. Like the sphere, we made sure it had a RigidBody component attached to it. When the game started the ball shot forward and knocked the pin, as we’d hoped.

Aimer

To aim our sphere and control the strength of our shot, we created an aimer. The aimer is composed of an empty object containing two cylinders, one pointing forwards and one pointing crossways.

We didn’t want the aimer cylinders interacting with anything so we made sure to remove the colliders from the cylinders.

We also wanted the aimer to be partially transparent so we created a new material, setting the Rendering Mode to “Transparent”, choosing a colour from the Albedo colour picker and setting the Alpha value to a value less than 255.

Screen Shot 2016-10-10 at 22.39.21.png

Project

Updated project files for this week’s project can be found here. This requires Unity Version 5.4.1f1 or later.

Creators – Covering the Basics

PhysicsTest

We’ve been busy the last two weeks covering the basics of Unity. Among the topics we’ve touched on are:

  • Customising the Unity layout
  • Explaining what the main Unity windows (Scene, Game, Hierarchy, Project and Inspector) are each for
  • Talked about 3D space and vectors and talked about the difference between local and global axes (child objects)
  • Shown how to place objects in the scene and how to position, rotate and scale them
  • Shown how to “fly” around the scene view
  • Explained how the physics engine works (Physics clock monitoring and moving rigidbodies and tracking collisions and other interactions)
  • Built a simple physics-based scene which had a ball fall, hit a ramp and roll into a bunch of stacked block
  • Wrote a script to have the camera follow the ball as it moves

 

Additionally Mike kindly filled in and talked about the basics of object oriented programming, classes and class diagrams. There is a post from last year that covers this well for those who’d like to read it.

Additionally, the basics of the C# language that we discussed are covered in both that post which we have already linked to above and another which can be found here. The topics we touched on were:

  • Curly braces as “containers” and the requirement that they occur in pairs.
  • How semicolons (;) mark the end of statements
  • Using directives and namespaces.
  • A basic class declaration
  • Properties, both public and private
  • Methods, both public and private
  • How Unity automatically calls certain methods at certain times, and some specific examples of this:
    • Start() called when we start the game
    • Update() called every time the scene is drawn

 

The up-to-date project file can be found here. Please note it will require Unity 4.5.1 or later.

Unity – A Basic Inventory System

backpack-145841_1280

Image from Pixabay

One of our ninjas was looking for a basic inventory system that he could use, so we knocked up something very quickly.

It’s all based on the standard .NET Dictionary class, documented here.

Dictionary allows us to store keys and associated values. In our specific case, our key is a string (the name of the item) and the value is an int (the count of items of that type).

This is all implemented in a script called InventoryManger.cs which is attached to an empty game object, also called InventoryManagement, for convenience. The InventoryManager class provides the following public methods:

void AddItem(string name)

This takes an item name. It looks to see if there’s an item of this name already in the inventory. If there is, it increases the count by one. If not, it adds it with a count of one. This cannot fail, so it doesn’t return anything.

bool RemoveItem(string name)

This takes an item name. It looks to see if there’s an item of this name in the inventory and that its count is greater than zero; it’s possible that it’s listed there, but the count is zero. If there is, it decreases the count by one and returns true. If not, it returns false. The true/false return value allows us to test, when calling this method, if it succeeded, if that’s important to us.

int GetCount(string name)

This takes an item name. It looks to see if there’s an item of this name in the inventory. If so, it returns its count. If not, it returns zero.

So that allows us to add, remove and track an arbitrary number of items with very little effort.

The sample project also has a few other scripts. The intention is that the player picks up objects by moving over them. Pickup objects are tagged “PickUp”. The HandlePickup.cs script is added to the FPSController to detect moving over a pickup. Pickups have a PickupDetails.cs script attached. This automatically tags them “PickUp” and contains the items name (to use in the inventory). The project also has a FruitStealer.cs which removes one banana from your inventory every time you pass through its gate. It’s just there to show the RemoveItem method in action.

Screen Shot 2016-05-15 at 13.33.13

The files for this project can be found here.

Other small things of note about this project: the “bananas” and “apples” are animated, as is the UI-text containing the text “Fruit Stealer”. The material used for the Fruit Stealer is transparent.

 

Finishing our Game Projects

110401-N-HC601-027

Image from US Navy via Wikipedia Commons

With two more regular dojo sessions to go before our final party and belt awarding ceremony, the finish line’s in sight and we’ve been concentrating on helping people work on their projects.

Some projects are already looking good, and that’s fantastic. Others however aren’t showing a lot of progress.

If you are struggling, please remember – overly ambitious scopes are the things that ruin most game projects. Ask yourself: what are the basic things that will be the most fun in my game? Maybe it’s exploration. Maybe it’s shooting. Whatever it is, get that working as soon as possible. Don’t do ten weapons, do one. Other features can be layered on over time as long as the fundamentals are there. Try hard to have something working for the next session. We’re here to help.

In the next session we’ll talk about the specific belts we’re going to be awarding. We’ll explain how they’re earned and we’ll try to get an idea of how many people are going for each category.

Basic Sample Projects

I briefly showed a number of sample projects that I’d been playing around with this week. These projects are intended to demonstrate certain useful things that you might want to put in your own game.

The first sample project was a modified version of SprocketLeague. The modifications were relatively modest: each car was given its own camera which was set to render into half the screen. The original top-down camera was set to render into a small area at the top of the screen.

The project files are available here.

The second project, called BasicAI, was just an experiment with baking a NavMesh and having an AI character follow you about. For extra fun, the followers spawn every 1.5s and they’re labeled “HipsterISIS” thanks to a very funny gag one of our ninjas made when watching the game run.

The project files for this are here.

Doors Project

This project wasn’t working fully during our session. It is now. The project contains two scenes. Both implement a door but in different ways. The two scenes can be found in the _scenes folder.

The first implementation is a physics based door. There is a box called DoorFrameRight which has a RigidBody component but is constrained so that it can neither move nor rotate:

Screen Shot 2016-05-08 at 14.57.38

Immediately to the left of this is the Door itself. This is also a box with a RigidBody component. In addition, it has a HingeJoint component. This HingeJoint component links it to the DoorFrameRight box. The HingeHoint is just visible as a small orange arrow on  the left hand side of this picture:

Screen Shot 2016-05-08 at 14.56.18.png

The HingeJoint component is positioned exactly where the door and door frame meet and its axis is set to be vertical, as the door is to swing around the vertical. It also has a spring which will close the door again (more or less) once the thing pushing it open moves away:

Screen Shot 2016-05-08 at 14.56.33.png

A regular FPSController can’t push this door, as it has a kinematic RigidBody (no physics), so note that we use the RigidBodyFPSController instead to represent the player in this scene.

The other door works in a very different manner. The door consists of a frame and a “hinge”. The hinge is just an empty GameObject which contains all the parts of the door that will be moving. It’s origin is at the left-hand edge of the door panel; this means that when we change the hinge’s Y rotation, the door will pivot about it’s left-hand side. The hinge’s origin is shown here:

Screen Shot 2016-05-08 at 15.40.36.png

I could have made the hinge rotate in code, but instead I decided to create animations to do the same thing (change the hinge’s Y rotation). To explain how animation works in Unity is beyond the scope of this post, but I’ll give a very broad introduction to it in the next session.

The door has a box collider around it. When it detects that the player has entered the collider, it triggers one of the opening animations (the direction depending on which side of the door it determines the player to be). Once the player leaves the collider, it closes the door again.

Screen Shot 2016-05-08 at 15.59.07

The files for this project are here.

Random Maze Project

This project was started live in our last session on the suggestion of one of the ninjas; it generates a random maze using a very simple algorithm.

An empty GameObject called MazeGenerator is placed in the scene. In its Start method, it constructs a random maze which appears in the scene. An FPSController from Standard Assets allows us to navigate this maze and try to find our way out.

The MazeGenerator constructs a 2D array of bool values to represent the maze. All the values in this array are ‘false’ by default and we take this to mean ‘solid’. Taking a point in the centre of the array we mark it ‘true’ to indicate an empty space. We then randomly pick a direction from North, South, East or West and set a new position. We check if we’ve moved outside the bounds of the array yet, if not, we mark this as another empty space and continue until we are outside.

Once we have this maze generated, we know we have a path from the centre (the start) to the exit (the outside of the maze). We loop over all elements in our array and place a solid block (from a prefab) everywhere we find a ‘false’, unless we’re at the edge of the maze in which case we place a special prefab that detect the player and plays a sound. This is our ‘exit’. For a ‘true’ we do nothing. The picture below shows one such generated maze from above.

Screen Shot 2016-05-08 at 18.35.04.png

To make this more fun to play, we also added a script to the FPSController to drop “breadcrumbs” as we move. This shows where we’ve already been so that going around in circles shouldn’t be a problem.

The files for this project are available here.

Review and a Couple of Sample Projects

This week we did a review of everything we’ve covered so far in Unity this year. It was a really usefully exercise as we ramp up to doing our own projects. People talked about their project ideas and I even got so see a few things running. I was impressed with the ingenuity and inventiveness. As I explained, over the coming few weeks, I won’t be presenting much in the way of new material. We will instead concentrate on getting our projects running and polishing them to the best of our ability.

I presented a couple of small sample projects intended to inspire game project ideas. The first was a top-down, single-keyboard, two-player game where two cars complete to drive a ball into their opponent’s goal area. If this sounds familiar, then you’ve heard of Rocket League. This low-rent version I dubbed “Sprocket League”. It can be downloaded from here. It uses the car from Standard Assets, slightly modified to allow the input axes to be defined in the inspector so that each can be controller independently. The red car uses the arrow keys and the blue keys uses WSAD for movement. To make it into a full game some means of keeping score and timing the game would be needed.

Screen Shot 2016-04-18 at 22.58.09.png

I also posted a basic sliding tiles game based on 2048. It is intended to show that we can achieve a 2D game appearance, even while using the 3D elements we have been working with. Although the basic game mechanics are there, it would ideally need a lot of work to bring it up to a reasonable standard. The real game provides a lot more visual feedback to the user than this version. Again, it can be downloaded from here. For those that recall, my broken attempt at making the tiles animate can be enabled via the “Show Me The Broken Movement” checkbox on the GameController object.

Screen Shot 2016-04-18 at 22.54.20.png

Best of luck working on your projects over the next two weeks and I’ll see you all when we return!

Shooting Mechanics In Unity

It was a thrill to have such significant games industry figures come to visit us on Saturday. The mentors, dads and dad-mentors were probably the most excited; Wolfenstein 3D, Doom and Quake were probably the most exhilarating games of our generation.

I was unsatisfied with how much benefit people were getting from continuing with the Tanks tutorial and I decided that we’d looked at it enough. Partially because I know some people want to implement shooting for their own projects and partially because one of our guests had invented the entire first-person-shooter genre, I decided to do a project to demonstrate different ways of implementing shooting in a game.

Please excuse the tinny sound; I was using the computers built in microphone.

There are two main ways to handle shooting: ray-casting and physics-based projectiles. We’re going to do both so lets discuss them in turn.

Ray-casting

Ray-casting uses mathematics to determine if a target is in our cross-hairs and, if it is, registers a hit instantly. It’s a good technique to use where the bullet is very fast moving and distances are relatively short. Regardless of action movie tropes, nobody is dodging a fast-moving bullet in real-life!

In Unity the Physics class contains several Raycast methods (documentation here). They all look along a line from a point and return ‘true’ if that line crosses through a Collider. The specific version we’re using can fill in a RaycastHit object with information about what it hit, if it hit anything.

To determine if we hit anything we must:

  1. Find the position and forward direction of the FPS Camera. This represents where we are and where we’re looking towards.
  2. Call Physics.Raycast with this information. If it didn’t cross any colliders, then we are finished.
  3. If it did hit something, then we check to see if that object is a target. We have tagged all target objects in the scene as “Target” so we can easily check this.
  4. If it is a target, we perform the effect we want. In this case, we push the target away from us with force applied to its RigidBody . In another case, we might want to actually destroy the GameObject instead.

Physics-based projectiles

A physics-based projectile is actually an object in the scene. It has a Collider so that it can detect collisions and a RigidBody so that it is affected by physics.

In many cases of physics-based projectiles, the Collider is simply a trigger and once an collision is detected, an effect, such as reducing the target’s health, is applied to the target.

Our specific physics-based projectile weapon is a cannonball. In this specific case, we actually allow the cannonball to hit the target and the physics engine takes care of the effect (knocking the target away).

The general steps that we need for physics-based projectiles are:

  1. Find the position and forward direction of the FPS Camera. This represents where we are and where we’re looking towards.
  2. Instantiate an instance of our projectile prefab. Position it so that it’s slightly in front of us and not intersecting with the FPS Controller’s own Collider.
  3. Give the projectile some forward velocity.
  4. Either:
    1. Have the projectile detect collisions and perform an appropriate effect on the target, or
    2. Simply allow the physics engine to take care of the impact.

The cannonball prefab has a small script attached to it. It detects collisions. Once the first collision is detected, a coroutine is launched. This coroutine waits for two seconds and then destroys the GameObject. This means that cannonballs have a limited life-span and don’t end up littered all over our level.

Area-effect weapon

We have also implemented an area-effect weapon, namely a grenade. In many ways it is similar to the cannonball but we project it with a more modest velocity.

Once created, however, it’s behaviour is very different. A coroutine is launched as soon as it is created. This coroutine waits for a few seconds to mimic a grenade fuse. It then “explodes”.

To explode, the grenade does the following:

  1. Plays an explosion sound on it’s own AudioSource.
  2. Instansiates a particle-effect prefab at the grenade’s location to display an visual explosion effect.
  3. Disables the grenade’s MeshRender component so that he body of the grenade can’t be seen any more.
  4. Uses Physics.OverlapSphere (documentation here) to find all Colliders within a given radius of the grenade
  5. Loops over these Colliders. If the collider is not attached to an active GameObject or if that GameObject is not tagged as a target, we ignore it.
  6. If it is an active target, we use RigidBody.AddExplosionForce (documentation here) to apply an explosion force, emanating from the grenade’s position, to the target.

Two seconds after the “explosion” the grenade GameObject, now invisible, destroys itself to remove itself from the scene. This short delay gives time for scripts to complete and sounds to finish playing.

Please note that although the grenade wasn’t working correctly on Saturday during our session, it’s fully functional now.

Gun selection

Gun selection is handled using the “[” and “]” keys. In the past we have tended to use Input.GetAxis to detect user input. This is good for where we wish to perform an action continuously as long as a key is held down. It’s not so good where we wish to perform a since action in response to a single keystroke. For that, using Input.GetKeyDown (documentation here) is better and that’s what we do.

The selected weapon is stored using an enum. An enum is a special variable type which can only take one of a number of pre-defined values. Since we have a limited list of weapons, three to be exact, this works well for us.

Putting it all together

Screen Shot 2016-04-12 at 21.17.02

Our level is a simple terrain. It’s been textured and had trees, grass and a wind zone added to it. There is a simple lake. A few target spheres have been positioned around the map and a box containing a number of small targets has been created as a good place to test the grenade in particular.

A standard first person controller prefab has been added to the scene. Our own GunController script has been attached to it as a component. GunController handles all the aiming and firing of the weapons.

Sound effects for the project are all from www.freesound.org with thanks to the original creators. All other third party assets are from the Unity Standard Assets pack.

Downloading the project

The project can be downloaded from DropBox here. Please ensure you have updated to Unity 5.3.4 before opening this project. Be aware, it’s relatively large at 160MB+.

 

Unity – Tanks Tutorial Part 3

Hey folks, we had a quite complicated session this week which discussed a lot of new concepts.

Screen Shot 2016-03-13 at 21.07.33Screen Shot 2016-03-13 at 21.07.10

We talked about the difference between perspective cameras and orthogonal cameras. With perspective cameras, as shown in the first image above, things appear smaller the further they are from the camera. With an orthogonal camera, as shown above in the second image, they appear the same size, regardless of how far they are from the camera.

The screen, and by extension, the camera which draws into that screen has an aspect ratio. This is defined as the width divided by the height. For example, a standard 1080p HD screen of has 1920 x 1024 pixels. This is an aspect ratio of 1.875. Our aspect ratio depends on how we’ve sized our game panel.

The camera in the tanks game is an orthogonal camera and the amount it can see is determined by it’s size. Whatever the camera’s size is, twice that distance in world units will be shown vertically by the camera. Our camera’s size is 5 so that means we can see 10 world distance units vertically and (10 x aspect ratio) distance units horizontally.

The code we showed the last day tries to position the camera at the average position between the tanks and size it so that both tanks fit in at the same time.

One unusual thing  that it does is to ensure smooth movement of the camera by not jumping it instantly to the place we want it to be, or the size we want it to be, but rather using the Vector3.SmoothDamp() method. This method allows us to specify two vectors, one representing the current value and the second representing value we’d like to get to, and returns a vectors that is someway from the first to the second such that it gives a smooth, as opposed to sudden or jerky, movement:

        transform.position = Vector3.SmoothDamp(transform.position, 
                                                m_DesiredPosition, 
                                                ref m_MoveVelocity, m_DampTime);

 

I’ve completed the health bar, as promised, and we won’t be doing that at Dojo. Just download the up-to-date project file from here, and we will start with it next week.

Remember to be working on your own projects! See you next week.

Unity – Tanks Tutorial Part 2

Introduction

This week we looked at getting our tank to move.

Tanks, and all tracked vehicles, have a very particular way of moving. By turning their tracks on both sides in the same direction, they can move forwards or backwards. By turning their tracks in opposite directions, they can turn around. In our game, we don’t model the tracks explicitly, but we do want our tank to behave in this same way.

Input Manager

In our previous two projects, we didn’t concern ourselves too much with how the keys we pressed caused actions to occur in the game. It mostly “just worked”.

In Roll-A-Ball we used the method Input.GetAxis() with axes called “Horizontal” and “Vertical” and these allowed us to control our player object.

The Input Manager allows control axes to be defined. It can be found under the Edit|Project Settings|Input menu. We can add as many control schemes as we need for our game here.

Screen Shot 2016-03-06 at 21.16.37

In the case of Tanks, we need controls for two players so we have Horizontal1, Vertical1 and Fire1 and also then Horizontal2, Vertical2, and Fire2.

When we retrieve the axis values in our code, it will have a value between -1 (full negative) and 1 (full positive). A value of zero indicates no input on this axis. When we’re dealing with keys, the only possible values are (-1, 0, 1) but if we had an alternative controller such as a gamepad, we would have values in-between too.

Calculating How Much to Move

The tank’s vertical axis controls how much to move forwards and backwards. To calculate how much the tank should move in one physics frame and in what direction we use the following code:

 Vector3 movement = transform.forward * m_MovementInputValue * m_Speed * Time.deltaTime;

It’s a vector, so it it has direction as well as magnitude. The direction comes from transform.forward – this vector always points in the tank’s forward direction, regardless of how the tank has been turned, and is always 1 unit long. It’s worth noting that there are companion vectors called right and up.

The m_MovementInputValue part is how much the user is currently pressing the keys in the vertical axis. As already discussed, it will be either -1 (full speed backwards), 0 (no movement) or 1 (full speed forwards).

The m_Speed property is a value we’ve set which sets the tanks maximum forwards/backwards speed. We have it set to 12 (distance units per second).

If we multiply all of these three things above together, we get a vector that points from the tank’s current position to the location the tank will be at in one second, if nothing else changes.

This is good, but it isn’t taking into account how often we’re doing our physics calculations (i.e several times a second). Time.deltaTime is the time since the last physics calculation. It will be some fraction of a second. Multiplying by this, we get a vector that points from the tank’s current position to the location the tank will be at after one physics calculation. That is what we want.

Calculating How Much to Turn

Calculating how much to turn is easier. This is the code:

 float turn = m_TurnInputValue * m_TurnSpeed * Time.deltaTime;

It’s a float describing how many degrees we’re turning.

As before, m_TurnInputValue represents the user input. The value is either -1 (turn anticlockwise), 0 (don’t turn) or 1 (turn clockwise).

The m_TurnSpeed property is a value we’ve set which sets the tanks maximum turning rate. We have it set to 180 (degrees per second).

Finally, for the same reason as before, we multiply by Time.deltaTime to get the number of degrees we’re turning in this physics calculation.

Applying the Movement

The movement was hard to calculate, but it’s easy to apply:

 m_Rigidbody.MovePosition (m_Rigidbody.position + movement);

We just tell the Rigidbody to move to a new position. That new position is simply the old position with the movement vector we calculated added on.

Applying the Turn

The turn was easy to calculate, but applying it is a little more complex. It’s not important to understand why it work the way it does, just know that if you’re applying an additional rotation to something that you can’t just “add it on” as we did with the positioning. Here is the code:

Quaternion turnRotation = Quaternion.Euler (0.0f, turn, 0.0f);
m_Rigidbody.MoveRotation (m_Rigidbody.rotation * turnRotation);

To turn the rotation into something we can use, we need to construct a Quaternion. A Quaternion is a special way of storing a rotation. The Quaternion.Euler() method allows us to create a Quaternion from X,Y,Z axis rotations. Here our turn was about the Y axis and the values for the X and Z rotations are simply zero.

Once we have our Quaternion, you might imagine that we add it to the Rigidbody’s existing rotation, but that wouldn’t work. We actually have to multiply it to get the correct new rotation for our Rigidbody.

Changing the Engine Sound

Another thing we spent a good bit of time on was checking to see if the tank was moving and changing the engine sound between an idle and driving sound.

We used the Mathf.Abs() function to get the absolute value of m_MovementInputValue and m_TurnInputValue. The absolute value of something is the value with the negative sign ignored. We compared these to a very small value to determine if the tank was currently stationary, or not.

Once we determined if the tank was stationary or not, we checked the engine sound that was playing. If it wasn’t the one it should be, we swapped in the correct one, taking time to randomly alter the pitch a little so that the two tanks won’t sound identical.

Project Download

The up-to-date files for the project are here. Please download these and we will all start from this point next week!

Unity – Tanks Tutorial Part 1

Update: This post has been updated with a link to download the project. See the bottom of the post.

Screen Shot 2016-02-29 at 00.17.14

This week we started work on the Unity Tanks tutorial. This is a single-keyboard, two-player, tank game where users can complete in a number rounds against each other.

We began with downloading the tutorial assets from the Unity Assets Store. This tutorial comes with many lovely assets including 3d models and audio clips.

The assets, as downloaded, contained a “Completed” folder. We deleted this first, as it has a second copy of many of the scripts and assets in the project and had the potential to create confusion.

We created a new scene and deleted the default directional light as we wouldn’t be needing it. Then we added the provide “LevelArt” prefab. This prefab contains the entire playing area and also contains a directional light. We discussed the different types of lighting that we can have in a game: ambient, directional, point, and spotlight. The image below shows the same scene lit in each of these four ways, respectively.

lighting

We then set our camera to be orthographic. We described the difference between orthographic and perspective cameras. With perspective cameras, the space the camera sees in front of it is shaped like a pyramid and things that are further away look smaller (as in real life). With an orthographic camera, the space the camera sees in front of it is box-shaped and things do not get smaller the further away they get. For some game types, the less realistic orthographic camera is a good stylistic choice. We also removed the standard skybox and just changed the background to a solid colour, again a good stylistic choice for this game.

We then started to build our tank. The 3d model was pre-supplied, so we added it to the hierarchy. We then added a rigidbody, a box collider and two audio sources for the playback of sounds. We were able to add constraints on the rigidbody to prevent the tank from ever moving vertically, or from rolling or pitching. Applying these constraints both prevents unwanted movements and makes the physics engine’s job much easier.

Screen Shot 2016-02-29 at 01.02.07

Finally, we added two dust trail particle effects to the tracks of the tank. These were also pre-supplied as assets for the project.

We had just started to look at tank movement and that’s where we’ll pick it up again next week. The project can be downloaded here.

Remember that you should now be starting to plan and work on your own projects for the end of the year. Best of luck and we’re here to help in any way we can!

Unity – Creating Objects at Run-Time

This week, once we made the final finishing touches to Amazing Racer, we took at look at a small project which introduced a number of new concepts, which are very useful when building games:

  • Creating objects at run-time
  • Creating a coroutine
  • Using random values
  • Using array parameters to specify multiple values

To create object at run-time, we saw the Instantiate method. This method is provided with a reference to an existing game object or prefab and it will create a new copy of it in the scene. Optionally, a new position and a new rotation can be specified for the duplicated object. The Unity documentation has more information on Instantiate.

A coroutine is a special kind of method. It is a method that can do some work, relinquish control temporarily to the game engine for a period, and then continue from where it left off. It has the special return type of IEnumerator. By calling yield return it can relinquish control. By calling yield return new WaitForSeconds(n) it can relinquish control for a specific period of time. To start a coroutine, we use the StartCoroutine method. You can read the Unity documentation for more information on coroutines.

We saw how Random.Range(min, max) can be used to give a random value between a maximum and minimum. This randomness can add interest and naturalism to our scene. The Unity manual reference for the Random class is here. You will see that there are many other ways to get random values, apart from the Range method.

Finally, we saw how a parameter can be an array. We used an array to specify multiple game objects which could be created by our source object. In the source our property objectsToSpawn is an array, as indicated by the square brackets [].

SourceControlProperties

In the inspector panel, we can see Objects To Spawn which offers a size that can be set, in this case we’ve entered 3, and as many boxes as the array is large.

SourceControlInspectorPanel

The Coroutine Test project is available here.

Our completed Amazing Racer project is available here.

Finally, I was asked to provide the completed Roll-A-Ball project too. That’s here.

All these projects are compatible with Unity V5.3.2f1.

We look forward to seeing you in two weeks! Remember to work on your game ideas over the break!