Creators: Text Based Adventure

The last two weeks we were looking at something quite different: a text-based adventure system built in Unity. This was inspired by the Henry Stickmin games and also by the old 80s-style choose-your-own-adventure books.

158788261_51be05e517_z

Basic Program Design (Story Card)

The user is presented with a “story card”. A card consists of some text describing their current situation and (normally) a number of options to choose from.

Screen Shot 2017-04-05 at 14.12.23.png

Depending on which option they pick, the story branches from there, card-by-card, until it reaches an end (a card with no options).

Setting up a card is straightforward:

Screen Shot 2017-04-05 at 14.15.27.png

You enter the card description (the text the user sees on screen), the text that the user will see on each option button (the program supports up to four at the moment) and the card (or branch, but we’ll get to that later) to jump to when that option is selected.

There’s also the mention of “States to Set True/False” and we’ll explain that next.

Story States & Story Branches

We could have programmed the system entirely using only cards, but there’s one situation where this becomes tedious. Imagine that you have a choice; hitting a button for example. The consequences of this choice won’t become apparent until later in the story. If we only had story cards, then we’d have to branch the story immediately at his point, replicating the same steps on both branches until the point at which the consequences of your action played out.

Fortunately, there is a better way.

First, to remember the value we introduce the idea of a “story state’. It’s just a container for a true or false value. Cards can set the value of specific states when they are activated as seen above.

Screen Shot 2017-04-05 at 14.14.09

So, that covers remembering values, how do we then make use of them? This requires a “story branch”. A branch references a state and two places for the story to go (either of these can be a card or another branch). The value of the state determines which is picked.

Screen Shot 2017-04-05 at 14.19.01

 

Game Manager

This class looks after the story. It is responsible for updating the UI to the details of the current card, for handling the use clicking on specific buttons and generally directing the flow of the story. It also needs a StoryCard to start off the story with.

Screen Shot 2017-04-05 at 14.21.33.png

Project

 

The project, including a very simple story using a number of cards and also a couple of states, can be found here. There are two scenes in the project, Adventure which contain a simple story and Basic which is a good starting place for your own story.

Bodgers – Reaction Game

reaction_bb.pngHi Everybody

This week we finished coding our Reaction Game. We then had Reaction Game tournament congratulations to Darragh our winner. I have a few slides from today which are available here reaction and you can also check out our code on Dropbox here.

For the next few weeks we will be building an Attendance/Clock In machine using our Laptops. You will need a version of Python 3, if you don’t have it installed you can download it from here.

See you all next week.

Creators – Random Pin Placement

This week we worked on random pin placement for our game. We updated the existing PinManager component to randomly (as opposed to regularly) place a number of pins into the scene.

Arrays

An array is a way for a variable to hold more than one value. It’s a a very useful concept in programming; complex programs would be practically impossible without them. In C# arrays are declared as follows:

     int[] nums = new int[4];
     bool[,] grid = new bool[rows, cols];

The first line creates a one-dimensional array called nums which has four entries: nums[0], nums[1], nums[2] and nums[3].

The second line creates a two-dimensional array called grid. Note the size in this case depends on the values of the variables rows and cols. The first entry is grid[0,0] and the last is grid[rows – 1, cols – 1]. The total number of locations in this array is rows * cols.

Continue reading

Creators – Getting User Input

This week we worked on getting input from the user and making the game react to it.

InputManager

Unity has a build in system for handling user input. The InputManager can be found under the Edit|Project Settings|Input menu:

Screen Shot 2016-10-17 at 21.21.01.png

The Unity input system is based on the concept of “axes”. The game request if there is input on a specific axis, giving the axis name. What that means in terms of button presses, mouse or controller input depends on the settings in the InputManager. Axes have a value that ranges from -1.0f (full negative, if negative values are allowed) through 0.0f (no input) to 1.0f (full positive).

inputaxes

Pre-defined Input Axes

While the game programmer can define as many input axes themselves as they like, Unity come with many common ones built-in. The first two shown above, called “Horizontal” and “Vertical” are commonly used for movement. The third “Fire1” is usually used for shooting.

We redefined “Fire1” from it’s default key (Left Ctrl) to bind it to the space key instead.

screen-shot-2016-10-17-at-21-36-26

Updating the Code to Detect “Fire1”

We originally had a force applied to our ball in the “PushSphere” script as soon as the game started. We modified the code so that in the Start() method all we did was to retrieve and store the Rigidbody component. In the Update() method (called every time the game draws) we ask if there’s been any input on “Fire1” and only if there has, do we apply a force to the ball:

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

Before proceeding, we ran our game and tested to ensure it  was working correctly.

Moving Our Aimer

The aimer was rotated using input from the horizontal axis. We added a script called AimerController to our Aimer game object. A public property called RotateSpeed gives us a way to tune the speed our our aimer. We don’t need anything in the Start() method, and it’s been removed here for clarity. The Update() method looks for input on the “Horizontal” axis (which maps to the left and right keys) and applies a rotation to the Aimer’s transform using the following logic:

amount to rotate = speed of rotation * user input * time

User input here will either be -1.0f, 0.0f or 0.0f. This equates to rotate in a negative direction (anti-clockwise), don’t rotate or rotate in a positive direction (clockwise).

 using UnityEngine;
 using System.Collections;
 
 public class AimerController : MonoBehaviour {
 
   public float RotateSpeed = 1.0f;
    
   // Update is called once per frame 
   void Update () {
     float horiz = Input.GetAxis("Horizontal");
 
     transform.RotateAround (transform.position, Vector3.up, 
                             RotateSpeed * horiz * Time.deltaTime);
   }
 }

Note that we’re rotating about the vertical axis and the rotation is centred around the aimer’s position.

Linking the Aimer and the Sphere’s Direction of Fire

To link the aimer’s with the sphere’s direction of fire, we needed to provide the sphere with a new public property which could store a reference to the Aimer’s game object:

public GameObject Aimer;

We then simply had to update the AddForce call, in the Update() method, to take the aimer’s direction into account:

 rb.AddForce (Aimer.transform.forward * -1.0f * PushStrength);

Note that we had to also multiply by -1.0f as the ball was initially going opposite to the direction we wanted.

Prefabs

Prefabs are objects, or collections of objects that we want to re-use multiple times. To create a prefab, all we need to do is to drag an object from the Hierarchy to a project folder. We made a prefab of our pin by doing this. Note that prefabs show up blue in the hierarchy to mark them out. When the prefab is changed, all copies of it in the hierarchy are updated as well.

Automatic Creation of Game Objects at Run-Time

Once we created our pin prefab, we worked on adding pins automatically into the game a run-time.

We added a new empty game object and named it PinManager, we then added a component to it of the same name. This script was given a public property, of type GameObject, to store a reference to the prefab. In the Start() method, we use two loops to place nine pins automatically into the scene, using the Instantiate() method:

 using UnityEngine;
 using System.Collections;
 
 public class PinManager : MonoBehaviour 
 {
   public GameObject PinPrefab;
 
   // Use this for initialization
   void Start () 
   {
     for (int x = -1; x <= 1; x++)
     {
       for (int z = -2; z <= 0; z++)
       {
         Vector3 pos = new Vector3(x * 2, 0.5f, z * 2);
 
         Instantiate (PinPrefab, pos, Quaternion.identity);
       }
     }
   }
 }

Note that there are several versions of the Instantiate() method. The version we’re using allows us to specify the position and rotation of the newly created object. A Quaternion is variable type that can store a rotation. Quaternion.identity simply means “no rotation”.

Testing

Project File

The latest project files can be downloaded from here.

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.

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 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!

Intermediate Scratch – Challenge 15 – Create a Rock-Paper-Scissors Game for 1 or 2 Players!

CDA-S2-Challenge15-RockPaperScissorsThis week’s challenge is to create a game of Rock-Paper-Scissors.

This week, you can choose to either create a 2-player networked game with a friend, or if you don’t feel like doing networking, you can write a 1-player version where you play against the computer. It’s up to you!

This challenge makes use of the networking ideas that we have covered in recent weeks, when writing a network Chat program and when writing 2-player Pong.

The big ideas behind today’s challenge are:

  1. How to design a 1-player or 2-player program
  2. Using variables  for exchange of data between computers and to pick random numbers
  3. Using broadcasts to sync parts of the game

Here are the presentation slides from the day, in PDF format: CDA-S2-Challenge15-RockPaperScissors.pdf

Next time, we will help ninjas to work on their own games.

If you would like me to send you these slides in PowerPoint format, feel free to get in touch on Twitter or via the comments!