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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s