Tag Archives: input

UI MouseOver

In this quick tutorial, I’ll show you how to modify a UI object when the player moves the mouse over it.

As always, if anything in this tutorial is new to you, refer to my Pong tutorial where I explain all the major Unity functionality in detail.

In this tutorial we use Event Triggers, which were explained in a bit more detail in the Input Manager tutorial, so if you want more detailed steps, refer to that tutorial.

What We’ll Do

We will create a simple scene with a few UI buttons. We will create a script that changes the colour and size of a button when the mouse passes over it.

Getting Started

  1. Create a new Unity project.
  2. Add a UI Canvas GameObject to the Hierarchy (Unity will automatically add an EventSystem object as well)
  3. Add some buttons to the canvas, and make sure they don’t overlap.

image

Colour Change on MouseOver

Unity already gives buttons a mouseover colour change, though the default setting is quite subtle. Let’s start by making this colour change more obvious.

Select one of the buttons in the Hierarchy so that its components show in the Inspector pane:

image

The ‘Highlighted Color’ property is the shading applied to the button when the mouse is over the button (or when the button is currently the selected button with keyboard/gamepad). Click in the Highlighted Colour box and select a new colour. Pick something obvious:

image

Now play the scene and move the mouse cursor over the button you modified.

mouseover

Advanced MouseOver Using Event Trigger

The built-in mouseover behaviour is fine for simple use and prototyping, but in a game you usually want something more interesting. Using an Event Trigger, we can script anything to happen to the button when the mouse is over it.

Choose one of the other buttons in your scene this time so you can compare the difference with the button you already played with.

Create a Script

  1. Create a new C# script and call it ‘MouseOverEffect’.
  2. Open MouseOverEffect in your code editor of choice.

For now, we’ll just create empty methods in the script. We need these empty methods so we can assign them to the events in the Inspector. Once that is done we will add the actual code to the script.

Put the following code in the script:


using UnityEngine;

public class MouseOverEffect : MonoBehaviour
{
    public void PointerEnter()
    {   
        print(“MouseEntered”);
    }

    public void PointerExit()
    {
        print(“MouseExited”);
    }
}

Create the Events

Your button needs to know when to call the code in the script, so we use an Event Trigger component to set up the events we want to listen to.

  1. Add an Event Trigger component to your button.
  2. Click the Add New Event Type button and choose PointerEnter.
  3. Click the Add New Event Type button again and choose PointerExit.

Your component should look like this:

image

Now you need to tell the Event Trigger what code to call when these events occur.

  1. On the same button you added the Event Trigger component, add your MouseOverEffect script.
  2. Click the plus sign button at the bottom of the Pointer Enter area.
  3. Drag-and-drop the same button GameObject you are working with into the field on the left.
  4. Select MouseOverEffect > PointerEnter from the drop-down selector on the right.

image

You have now told the Event Trigger that when the mouse (pointer) enters this button, run the PointerEnter method on the MouseOverEventSctipt attached to the button’s GameObject.

Now repeat those steps for the PointerExit event, except this time choose the PointerExit method in the final step.

Troubleshooting Tip

If the MouseOverEffect methods don’t show up in the drop-down list, make sure the methods are public, and that you have saved the script.

Now run your scene and test that it is working. You should see text in the Console panel when the mouse cursor enters and exits the button area.

If that’s working correctly, you can move onto the next section where we will add something more interesting to the mouseover effect.

Scale the Button

The basic functionality is all there now. You are detecting when the mouse is over the button and running some code when it happens. Now all you need to do is put something more interesting into that code.

We are detecting two events – PointerEnter and PointerExit. This is so we can do something when the mouse moves over the button, then undo it when the mouse leaves the button.

Let’s scale the button.

Replace the two methods with the following:

 

public void PointerEnter()
{
    transform.localScale = new Vector2(1.2f, 1.2f);
}

public void PointerExit()
{
    transform.localScale = new Vector2(1f, 1f);
}

Now test the scene (make sure you save the script first). You should now have something like this:

scale

You can add any code here you like. You can also combine the built-in colour shading that Unity provides.

Since the button is quite generic, try replacing the button image, text, and font to create something that looks a bit more at home in a game.

Here is a button I’ve created:

play

Next Steps

There is no limit to what you can do to enhance this functionality and create interesting UI. Here are a few things you could try adding to your code:

  • Change the image/sprite
  • Play a sound effect
  • Rotate or animate the button

The scaling technique I’ve shown above is very basic. You will probably want to replace it with a smooth animation. Look into ‘tweening’ to find ways of smoothly animating the scale so it looks slick and professional.

A Simple Input Manager for Keyboard, Gamepad, and Touch

In this tutorial, I will show you how to create a simple input manager to handle directional input via the keyboard, a gamepad, or on-screen touch controls. Though this tutorial only covers directional movement, it can easily be extended to add extra functionality, such as a jump button.

As always, if you get stuck on any of the basics, refer to my Pong Tutorial where you can get up to speed on all the Unity basics. This tutorial is written in the assumption that you know your way around Unity and its main functionality.

What We’ll Do

We will create a very basic scene with a player sprite that can be moved up, down, left, and right using the three input methods. The keyboard and gamepad inputs will be handled using the standard Unity Input class, which is super simple. For on-screen touch controls, we’ll create a special script and attach it to some buttons. All the touch will be handled by a special InputManager class to keep the player code simple, so the player script doesn’t know (or care) what input method is being used.

We’ll do everything in the following order:

  1. Create the player
  2. Create the InputManager script to handle keyboard and gamepad input.
  3. Create the Player script to move the player according to input in the InputManager script.
  4. Create touch input buttons.
  5. Modify the InputManager script it include it.

What you Need

To complete this tutorial, you need:

  • Unity 5.6.1, though any recent version should be fine.
  • Some sprites – anything to represent the player and the four directional movement buttons. Check out Kenney.nl or OpenGameArt.org if you don’t have anything handy.

Download the following sprites if you want (these are all public domain):

Keyboard_Black_Arrow_UpKeyboard_Black_Arrow_DownKeyboard_Black_Arrow_LeftKeyboard_Black_Arrow_Rightgiraffe

1. Create the Player

Basic Setup

  1. Start a new Unity project with the 2D settings.
  2. Create an empty GameObject and rename it to Player.
  3. Add a SpriteRenderer component to the Player object.
  4. Add your sprites to the project.
  5. Add the player sprite to the Player’s SpriteRenderer.

You should now see something similar to this in Unity (I always change the default camera background colour from the horrid shade of blue to something nicer):

image

2. Detect Input

Now let’s make the player move using Unity’s input axes.

Unity provides great automatic horizontal and vertical input via the Input class, and this means you can effortlessly get player input from the keyboard and any gamepad with very little code. Here’s a quick example of how to get the left/right input from the player:


var horizontalMovement = Input.GetAxis(“Horizontal”);

That’s all the code you need to detect input on the horizontal axis. The value of horizontalMovement will be between –1 and 1, with –1 being fully to the left, 0 being no movement at all, and 1 being fully to the right. Switch “Horizontal” for “Vertical”, and you have –1 equal to fully down and 1 to fully up.

InputManager Script

Let’s put that into a script and make it move the player.

  1. Create a new C# script called “InputManager.cs”.
  2. Open InputManager.cs in your code editor of choice, then replace the code with the following:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InputManager : MonoBehaviour 
{

    public Vector2 CurrentInput
    {
        get
       {
           return new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
       }
    }
}

That code is pretty straightforward. It simply wraps up the horizontal and vertical input axes into a public Vector2, which the player can then grab. The reason we do it in this separate script instead of having the player directly access the input is so we can add more to it later without needing to mess with the player script. This keeps the code nice and modular, so that each script sticks to its own. This is very important when your project gets more complicated. Later on, we’ll add more code to this script to enable touch controls, but we’ll leave it like this for now.

Save the script and return to Unity.

3. Create the Player Script

  1. Create a new C# script called “Player.cs”.
  2. Open Player.cs and replace the code with the following:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour 

{

    InputManager inputManager;

    [SerializeField] float playerSpeed = 5f;

    private void Awake()
    {
        inputManager = GetComponent<InputManager>();
    }

    void Update ()
    {
        transform.Translate(inputManager.CurrentInput * Time.deltaTime * playerSpeed);
    }
}

This script simply moves the player transform according to the input from the InputManager script. In the Update method, the movement amount is multiplied by Time.deltaTime (i.e. the time since the last frame), which ensures the movement is smooth (otherwise the movement would be slightly slower or faster on each frame). The movement is also multiplied by a playerSpeed variable to control how fast the player moves.

As you can see, we use a GetComponent to get a reference to the InputManager script, meaning that we must ensure the two scripts are both on the Player GameObject.

Put it all together:

  1. Add the Player script to the Player GameObject.
  2. Add the InputManager script to the Player GameObject.
  3. Play the scene and move the player around. If you have a gamepad (e.g. an Xbox controller), you can move the player with that. The keyboard arrow keys and WASD will also work.

If the player moves too slowly or quickly for your taste, adjust the speed variable in the Inspector pane.

image

4. Touch Controls

Touch controls are a little more complicated. I use a technique that is very easy to extend because it is quite modular.

I use a UI canvas to place buttons on the screen, then use Unity’s Event Triggers to detect when a button is pressed or released. A bit of simple logic and state handling replicates Unity’s normal button functionality so you can detect if a button is currently held, was pressed down on the last frame, was released on the last frame, or is not being manipulated at all.

Create a ButtonState Enum

Before we start on a new script, open up InputManager.cs and add the following enum type (place it just before the ‘Vector2 _currentInput;’ variable):


public enum ButtonState
{
    None,
    PressedDown,
    Released,
    Held
}

That gives us a list of button states we can use to track the buttons. If you’re not familiar with enums, read this explanation over at DotNetPerls. Basically, an enum lets us define our own variable type with a fixed set of possible values.

Create the TouchButton Script

Let’s create a script to attach to all the on-screen touch buttons.

  1. Create a new script called TouchButton.cs.

I’ll go through the code in sections, then put the whole code in one lump at the end of this section, so for now, don’t copy-and-paste each chunk in separately, just read along for the explanation, then copy the whole script at the end.

The Variables


bool pressedDown;
bool pressedLastFrame;

public InputManager.ButtonState CurrentState;

These variables let us keep track of the button’s state so we know if the player is pressing the button. As you can see, we track whether the button is (currently) pressed, whether it was pressed on the previous frame, and the button’s current state (using the enum ButtonState we created in the InputManager script).

Pressed and Released Methods

These two methods will be called automatically by Unity (once we’ve wired them up in the Inspector) when the player touches or releases the button.


public void PressDown()
{
    pressedDown = true;
}

public void Release()
{
    pressedDown = false;
}

These methods are very simple – they just set the pressedDown variable based on whether the player touched the button or released it. These methods therefore let us know whether a touch began or ended on a given frame.

The Update() Method

During Update(), we check the current state of the button, then using the previous state as a comparison, we determine what the state should be. For example, if pressedDown is true and pressedLastFrame is false, we know that the player has just started pressing the button in this frame (because they are pressing it now, but weren’t pressing on the previous frame).

Here is the code:


void Update()
{ 
    // update the state based on the change since the last frame

    // update the state when the button is pressed
    if (pressedDown)
    {
        if (pressedLastFrame)
        {
            // was pressed in the previous frame and is still pressed, so the button is considered held
            CurrentState = InputManager.ButtonState.Held;
        }
        else
        {
            // button not pressed last frame, but is now, so the button has been pressed down on this frame
            CurrentState = InputManager.ButtonState.PressedDown;
        }
    }
    else
    {
       // now update if the button is not pressed
       if (pressedLastFrame)
       {
           // was pressed last frame, but no longer pressed, so it was released
           CurrentState = InputManager.ButtonState.Released;
       }
       else
       {
            // was not pressed last frame and still not pressed, so nothing
            CurrentState = InputManager.ButtonState.None;
       }
    }
}

I’ve included comments to clarify the logic.

Note: always detect input in Update(), never in FixedUpdate(). FixedUpdate() does not run on the same timescale as Update(), and you will therefore risk some input being missed.

LateUpdate()

Finally, add this simple LateUpdate() method:


private void LateUpdate()
{
    // store the state from the last frame so it can be compared to the next frame's state to check if it has changed
    pressedLastFrame = pressedDown;
}

This simply stores the current state of the button in the pressedLastFrame variable to be compared to the new state in the next frame. While this single line of code could be placed at the end of the Update() method, I prefer to use LateUpdate() to make the code’s intention clearer.

The Full Code

Here’s the full TouchButton code you can paste into your script (we will add some more code to this script later):


using UnityEngine;
using UnityEngine.UI;

public class TouchButton : MonoBehaviour
{
    bool pressedDown;
    bool pressedLastFrame;

    public InputManager.ButtonState CurrentState;

    public void PressDown()
    {
        pressedDown = true;
    }

    public void Release()
    {
        pressedDown = false;
    }

    void Update()
    {
        // update the state based on the change since the last frame

        // update the state when the button is pressed
        if (pressedDown)
        {
            if (pressedLastFrame)
            {
                 // was pressed in the previous frame and is still pressed, so the button is considered held
                 CurrentState = InputManager.ButtonState.Held;
            }
            else
            {
                // button not pressed last frame, but is now, so the button has been pressed down on this frame
                CurrentState = InputManager.ButtonState.PressedDown;
            }
        }
        else
        {
            // now update if the button is not pressed
            if (pressedLastFrame)
            {
                 // was pressed last frame, but no longer pressed, so it was released
                 CurrentState = InputManager.ButtonState.Released;
            }
            else
            {
                // was not pressed last frame and still not pressed, so nothing
                CurrentState = InputManager.ButtonState.None;
            }
       }
    }

    private void LateUpdate()
    {
        // store the state from the last frame so it can be compared to the next frame's state to check if it has changed
        pressedLastFrame = pressedDown;
    }
}

Create a Touch Button

Now let’s create our first touch button.

Back in Unity…

  1. Create an empty GameObject in the scene and name it TouchControls. This will hold all the touch buttons.
  2. Add a UI Canvas component to TouchControls. Note: Unity will also automatically add an EventSystem to the scene. This is normal and required.
  3. Add an empty GameObject as a child to the Canvas, and call it Buttons.
  4. Add an empty GameObject as a child to Buttons, and call it Left.

Your TouchControls should look like this in the Hierarchy:

image

Now add the required components to the Left button:

  1. Select the Left GameObject.
  2. Add an Image component.
  3. Drag-and-drop the sprite for the left movement button into the Image component’s Source Image field.
  4. Add the TouchButton script to the object.

Next, we add the events that trigger code in the TouchInput script when the player either touches or releases the button.

  1. Add an Event Trigger component to the object.
  2. Click the Add New Event Type button in the Event Trigger component in the Inspector.
  3. Select PointerDown from the drop-down list.
  4. Click Add New Event Type again, and this time choose PointerUp from the drop-down list.

The component should look like this:

image

Now you need to tell the component what code to run when the events happen. Pointer down detects when the player touches the button, so we want it to call the PressDown method in the TouchInput script.

  1. Click the + below the ‘List is Empty’ message in the Pointer Down (BaseEventData) event.
  2. Drag-and-drop the Left GameObject from the Hierarchy into the empty field (it currently says ‘None’).
  3. In the drop-down selector on the right, select TouchInput.PressDown().

image

What you are doing here is saying that the code you want to run for this event is within the Left GameObject. Then you select the specific script (TouchButton) and the specific method (PressDown). So when this button is pressed down, the PressDown method on the TouchButton script instance on the Left GameObject is called.

Now, do that again for the PointerUp event, this time choosing TouchButton.Release as the method to run.

Here’s what it should look like when you’re finished:

image

Do the Other Buttons

Now you need to create the right, down, and up buttons. You can save yourself some work by duplicating the Left button GameObject (select it in the Hierarchy and press Ctrl-D). Duplicate it three times and rename each duplicate Up, Down, and Right.

You will also want to add different button images for each button and position them on the canvas roughly like this:

image

I recommend using ‘Scale with Screen Size’ setting for the canvas, and to anchor the buttons to the bottom-left corner. Be careful to put the correct buttons in the correct positions, or your movement will be all backwards!

5. Update the InputManager

Now that we’ve added touch buttons we need to include them in the InputManager script. What we will do is add a check on the button states to the current Input.GetAxis…code. We are therefore extending the InputManager’s capabilities without touching any other code in the project (i.e. we don’t need to change the player code – this is the beauty of modular code).

Open up InputManager.cs.

First, we want references to the four buttons we created in the previous section, so add this to the script:


[SerializeField] TouchButton upButton;
[SerializeField] TouchButton downButton;
[SerializeField] TouchButton leftButton;
[SerializeField] TouchButton rightButton;

The [SerializeField] just means we can access/assign the values in the Inspector pane, which we will do shortly. But before we do that, replace the CurrentInput property with the following code:


public Vector2 CurrentInput
{
    get
    {
        return new Vector2(HorizontalInput, VerticalInput);
    }
}

float HorizontalInput
{
    get
    {
        if(leftButton.CurrentState == ButtonState.Held || leftButton.CurrentState == ButtonState.PressedDown)
        {
            return -1;
        }
        else if(rightButton.CurrentState == ButtonState.Held || rightButton.CurrentState == ButtonState.PressedDown)
        {
            return 1;
        }
        return Input.GetAxis("Horizontal");
    }
}

float VerticalInput
{
    get
    {
        if (upButton.CurrentState == ButtonState.Held || upButton.CurrentState == ButtonState.PressedDown)
        {
            return 1;
        }
        else if (downButton.CurrentState == ButtonState.Held || downButton.CurrentState == ButtonState.PressedDown)
        {
            return -1;
        }
        return Input.GetAxis("Vertical");
    }
}

That code is not as complicated as it looks. It just checks the touch button states, and if a button is touched, it uses that for input, otherwise it falls back to the standard axis input (keyboard/gamepad). As you can see, while the code is all different, the player will still call the same CurrentInput property. This code can easily be extended further to accept mouse input or whatever else you might want (all without changing any code outside of the InputManager script, of course).

Now, with the Player GameObject selected in the Hierarchy, drag-and-drop the buttons into the Inspector fields.

image

Test It

Now everything is in place. Run the scene and test the touch buttons. You can use the mouse to click the buttons. Deploy to your phone or tablet to test the touchscreen support.

Next Steps

Now that you have the basics in place, you can extend the InputManager script quite easily. Just create new buttons for your needs – jump, punch, etc. The touch button states correspond to the Input class (e.g. Input.GetButtonDown corresponds to the PressedDown state; Input.GetButton corresponds to the Held state). Make sure each action has a gamepad button, a keyboard key, and a touch button.

Try making your touch buttons semi-transparent, and make them change their transparency when pressed.

Limitations

The touch buttons currently only have two values – pressed or not pressed, whereas the input axes can have any value between –1 and 1. If you want your player to accelerate more naturally, you may want to weight the values by the amount of time pressed. For example, you could time how long since the player started holding the button down and use this to calculate a value instead of just using –1 for left and 1 for right. Then gradually move the value towards –1 or 1 the longer the button is pressed.

Input: Detect Mouseover

 

mouseover

Unity has events that tell your scripts when the mouse cursor hovers over an object and stops hovering over an object. This can be great for UI or for prompting the player that they they can interact with something.

OnMouseEnter()

The OnMouseEnter() method will run when the mouse cursor first enters the object’s collider area (the object must have a collider for this to work).


void OnMouseEnter()
{
   // do something, e.g. change the sprite or make a sound
}

OnMouseExit()

The reverse method to OnMouseEnter(), OnMouseExit() is called when the mouse cursor exits the objects collider area.


void OnMouseExit()
{
   // do something, e.g. change the sprite or make a sound
}

Sample Script

This following script contains an example of what you can do with this functionality. Add this script to any object with the following:

  • A collider
  • A SpriteRenderer with a default sprite
  • Add a second sprite to the mouseOverSprite inspector field (the SpriteRenderer will show this sprite when the mouse cursor is over the GameObject).

using UnityEngine;
using System.Collections;

public class MouseOver : MonoBehaviour
{

[SerializeField] private Sprite mouseOverSprite;
private Sprite defaultSprite;
private SpriteRenderer sRenderer;

void Start ()
{
     defaultSprite = gameObject.GetComponent&amp;lt;SpriteRenderer&amp;gt;().sprite;
     sRenderer = gameObject.GetComponent&amp;lt;SpriteRenderer&amp;gt;();
}

void OnMouseEnter()
{
    sRenderer.sprite = mouseOverSprite;
}

void OnMouseExit()
{
    sRenderer.sprite = defaultSprite;
}
}

Expanding This

The Unity documentation has more details of this functionality (http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnMouseOver.html). You can get inspiration for how to use this from the games you play.

For games with a lot of UI this technique can bring those menus to life. You can do all kinds of transform tricks with it, such as:

  • Adjust an object’s scale
  • Add a slight rotation
  • Make a subtle sound
  • Animate the object.