left-icon

Unity Game Development Succinctly®
by Jim Perry

Previous
Chapter

of
A
A
A

CHAPTER 5

Input

Input


If the player can’t control the game, we don’t have much of a game. The main types of input your game must handle will be mouse and keyboard (PC), gamepad (PC and console), and touch (mobile). You might also consider voice and tilt inputs, although we won’t cover those here. And, touch is difficult to implement correctly—it would require more explanation than we have room for here. If you’re creating only mobile games, you’ll want to look into both touch and tilt input methods. The Touch, TouchScreenKeyboard, and Gyroscope classes in the API will be good places to start.

Fortunately, Unity handles a lot of the input automatically. For PC games, the mouse works fine. No need to draw the pointer every frame and calculate its location. Unity also handles a lot of the UI work for you. Nearly all you need to do is write code for whatever a button does when you click on it, what happens when a check box is checked or unchecked, etc. We’ll see that in the UI section.

Input Manager

Before dealing with getting input, we need to see how Unity handles peripheral configuration. The Input Manager tracks which keys/mouse control/etc. is used for actions in the game and allows the player to configure the input. The screenshot in Figure 27 shows the Input tab of the window being displayed when a game is run.

Game Configuration Window

Figure 27: Game Configuration Window

This window shows the input values that were set when the game was compiled. These values can be changed in the InputManager window in the Unity editor, as shown in Figure 28.

InputManager Window

Figure 28: InputManager Window

Note that some actions, such as Horizontal, Vertical, Fire, Submit, and Jump, are listed multiple times. If you open all the versions of an action, you’ll see that they are defined for multiple types of input devices. The first Horizontal type is Key or Mouse button—the left/right or a/d keys, as well as the x-axis on the mouse, will trigger horizontal movement. The second Horizontal type is Joystick Axis. You might wonder why they didn’t simply define the Joystick type with the mouse. A PC will almost always have a mouse and keyboard, but a joystick is generally pretty rare.

In order to make this more confusing, take a look at the Fire1 actions. Both are listed as Key or Mouse button, one is left Ctrl/mouse 0 and the other is joystick button 0. This means that configuring your own actions will take some trial and error. Or you can just use the Get… methods of the Input class to check for specific inputs for specific actions and not allow the player to custom configure those actions. This will limit your game somewhat, however.

Input class

The main class you’ll be dealing with is the Input class. Everything in the class is static, which means you don’t need an instance of the class. For PC, the variables you’ll be dealing with are inputString, mousePosition, and possibly anyKey and anyKeyDown. There are a number of methods in the class for dealing with mouse and keyboard (and joystick for those who still use them). Table 3 shows a partial list of input methods.

Table 3: Input Class Methods for PC

GetAxis

Returns the value of the virtual axis identified by axisName.

GetAxisRow

Returns the value of the virtual axis identified by axisName with no smoothing filtering applied.

GetButton

Returns true while the virtual button identified by buttonName is held down.

GetButtonDown

Returns true during the frame the user pressed down the virtual button identified by buttonName.

GetButtonUp

Returns true the first frame the user releases the virtual button identified by buttonName.

GetJoystickNames

Returns an array of strings describing the connected joysticks.

GetKey

Returns true while the user holds down the key identified by name. Think autofire.

GetKeyDown

Returns true during the frame the user starts pressing down the key identified by name.

GetKeyUp

Returns true during the frame the user releases the key identified by name.

GetMouseButton

Returns whether the given mouse button is held down.

GetMouseButtonDown

Returns true during the frame the user pressed the given mouse button.

GetMouseButtonUp

Returns true during the frame the user releases the given mouse button.

Fortunately, for our purposes we’ll only need to use three methods and the mousePosition variable. We don’t have any text input to deal with. If you want to enhance the game by adding a login for items such as a multiplayer mode and tracking high scores, you still won’t necessarily need to use any more functionality in the Input class because the UI controls will be able to handle most of your needs.

We’ll use the GetKeyDown method for determining when to pause and unpause the game. We’ll use the GetAxis method for moving the player. We’ll use the GetButton method for handling firing bullets. Lastly, we’ll use the mousePosition for determining where the character is pointing in order to rotate the character sprite, which will affect where the bullet is fired.

In the Scripts folder, add a class that we’ll use for controlling the character or player. I have called it PlayerController because that’s the name you’ll find in a lot of Unity samples and tutorials. Add the code from Code Listing 12.

Code Listing 12: PlayerController Class

public float Speed;

private float _fireRate = .5f;

private float _nextFireTime = 0.0F;

public GameObject Bullet;

private bool _bulletFired = true;

void OnTriggerEnter2D(Collider2D collider)

{

    if (Globals.CurGameState == GameState.PlayingGame)

    {

        if (collider.gameObject.tag == "Ghost")

        {

            Globals.Health--;

            Destroy(collider.gameObject);

        }

    }

}

void Update()

{

    if (Globals.CurGameState == GameState.PlayingGame)

    {

        Vector3 vel = new Vector3();

        vel.x = Input.GetAxis("Horizontal");

        vel.y = Input.GetAxis("Vertical");

        Vector3.Normalize(vel);

        vel *= Speed;

        float x, y;

        GetComponent<Rigidbody2D>().velocity = vel;

        x = Mathf.Clamp(transform.position.x, -4.5f, 4.5f);

        y = Mathf.Clamp(transform.position.y, -3.0f, 3.0f);

        transform.position = new Vector3(x, y, 0);

        //rotation

        Vector3 mouse = Input.mousePosition;

        Vector3 screenPoint = Camera.main.WorldToScreenPoint(transform.localPosition);

        Vector2 offset = new Vector2(mouse.x - screenPoint.x, mouse.y - screenPoint.y);

        float angle = Mathf.Atan2(offset.y, offset.x) * Mathf.Rad2Deg - 90.0f;

        transform.rotation = Quaternion.Euler(0, 0, angle);

        if (_bulletFired)

        {

            _nextFireTime += Time.deltaTime;

            if (_nextFireTime >= _fireRate)

                _bulletFired = false;

        }

        if (Input.GetButton("Fire1") && !_bulletFired)

        {

            //spawn bullet

            GameObject bullet = (GameObject)Instantiate(Bullet, transform.position, transform.rotation);

            _nextFireTime -= _fireRate;

            _bulletFired = true;

        }

              

    }

}

The Update method will be called with every frame. We’ll use the current mouse and keyboard values to determine where the character script will be drawn and which way it will face. The Horizontal and Vertical axes are used along with a constant speed, which is set in the Unity editor, and the current position of the sprite from the built-in Transform object to determine the new position. The mousePosition variable of the Input class is used along with the position of the sprite in order to determine how much the sprite needs to be rotated in order for it to face the mouse—so that the sprite will appear to be firing toward where the mouse is pointed.

The last action of the method will check to see if the player is pressing the control mapped to the Fire1 action. If so, and if the player is allowed to fire, a bullet is spawned and variables are set to ensure the player can’t fire again before he’s allowed.

The code uses a couple of globals that we need to add to the Globals script. The CurGameState and Health members go in the Globals class, with the enum outside of it.

Code Listing 13: Input-Related Global Code

public static GameState CurGameState;

public static int Health;

public enum GameState

{

    PlayingGame,

    PauseGame,

    GameOver

}

You might want to consider allowing the player to use a gamepad in order to control the character. Even on a PC, some players prefer to use a gamepad for games. Allowing your game to handle a gamepad will also make it easier to convert to a console version.

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.