Tag Archives: ui

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.

Simple Script for Gamepad UI Navigation

For my upcoming game, Mouse Dreams, I need to support gamepad input as well as keyboard and touch. It turns out this is not quite as simple as I first thought. The big issue with supporting UI with different input methods is how it will appear to the user. With touch or mouse input, the user simply presses a button, but with controller or keyboard input, you need to indicate to the player which button is currently selected.

Unity’s UI can easily implement colour changes when a button is selected, but this can look weird with touch input, and is not always easy to see. Unity’s UI also doesn’t work with controller input if no UI object is currently selected (or a default set), which is a pain.

I wrote a simple script to help with these problems. It simply scales the currently selected UI button to be a bit larger than the others. The scaling amount can be adjusted in the Inspector, and you can set a default UI object to be selected when the scene starts, which in turn enables controller input.

The Code


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class ButtonHighlighter : MonoBehaviour
{
    private Button previousButton;
    [SerializeField] private float scaleAmount = 1.4f;
    [SerializeField] private GameObject defaultButton;

void Start()
{
    if (defaultButton != null)
    {
        EventSystem.current.SetSelectedGameObject(defaultButton);
    }
}
void Update()
{
    var selectedObj = EventSystem.current.currentSelectedGameObject;

    if (selectedObj == null) return;
    var selectedAsButton = selectedObj.GetComponent<Button>();
    if(selectedAsButton != null && selectedAsButton != previousButton)
    {
        if(selectedAsButton.transform.name != "PauseButton")
        HighlightButton(selectedAsButton);
    }

    if (previousButton != null && previousButton != selectedAsButton)
    {
        UnHighlightButton(previousButton);
    }
    previousButton = selectedAsButton;
}
void OnDisable()
{
    if (previousButton != null) UnHighlightButton(previousButton);
}

void HighlightButton(Button butt)
{
    if (SettingsManager.Instance.UsingTouchControls) return;
    butt.transform.localScale = new Vector3(scaleAmount, scaleAmount, scaleAmount);
}

void UnHighlightButton(Button butt)
{
    if (SettingsManager.Instance.UsingTouchControls) return;
    butt.transform.localScale = new Vector3(1, 1, 1)
}
}

How to Use

Just add the script to a UI canvas with multiple buttons. I coded the script specifically for buttons, but you can easily adjust it to work with different UI objects if you need to.

For improved scaling, you can implement some tweening or lerping.

Set the scaling to an appropriate amount. The default is 1.4f, which may be a bit large for some uses. You need to find a balance between looking good and being noticeable to the player.

Set a default button in the Inspector. This will be selected automatically when the scene starts, which has the side effect of enabling controller input.

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.