Best way to "highlight" an object on mouse over

Lets say I have like 25 different objects in the scene which are always visible for the camera with quite complex colliders. I then want to highlight whatever object I’m hovering over (with the mouse) by changing the texture or whatever.

Which is the best way to do this?

I guess I could send out raycasts every frame and change the texture whenever it hits something, but that seems quite expensive? Is there any other way?

How about changing the material color?

4 Answers

4

This will be attached to all the things that can be highlighted with hovering.

Color startcolor;

void OnMouseEnter ()
{
    startcolor = renderer.material.color;
    renderer.material.color = Color.yellow;
}

void OnMouseExit ()
{
    renderer.material.color = startcolor;
}

color.yellow won't work for me. I've tried color.#... I've tried color.antiqueBlue; etc etc you get where I'm going here. I just want to highlight a gameObject OnMouseClick or another event perhaps! The rest of the script seems fine in MonoDevelop for Unity. Including caps where it's supposed to be caps etc. Could someone help with this please?

using UnityEngine; using System.Collections; public class textcolour : MonoBehaviour { private Color startcolor; void OnMouseEnter() { startcolor = renderer.material.color; renderer.material.color = Color.red; } void OnMouseExit() { renderer.material.color = startcolor; } } this is what i tried but it didnt work!! what did i do wrong?

you need a renderer with a material and a collider for the mouse to see. do you have errors? that code should work.

Can anyone with sufficient privileges fix the original answer's typos? The type color does not exist; should be Color.

I fixed it.

Okay so your problem with OnMouseEnter and _Exit is that you are setting yourself up to be confused if you are porting to a VR platform, or a platform that has a pointer controller. If you want to keep your project open ended and not only have it releasable for PC, you can do something like below:

Create a main game object that doesn’t get destroyed so that you have a scene manager object between scenes. Make a main game script, we will pretend it’s called MainGameScript.cs and it’s class name is MainGameScript and put this inside of it, above it’s class:

[System.Serializable]
public class MainInput_Ray
{
	public Ray ray = new Ray ();
	public RaycastHit hit;
	public bool hittingSomething { get; set; }
}

Then goes in your main game script’s start:

public MG_Ray mainInput_Ray;

void Start ()
{
    mainInput_Ray = new MainInput_Ray();
}

…and then this goes in your main game script’s update AFTER the scene is fully loaded and playing:

void Update ()
{ 
    mainInput_Ray.ray = MG_Camera.GetComponent<Camera> ().ScreenPointToRay (Input.mousePosition);
    mainInput_Ray.hittingSomething = Physics.Raycast (mainInput_Ray.ray, out mainInput_Ray.hit, 1000);
}

Now in your object’s script you can go like:

private MainGameScript mainGameScript;

void Start ()
{
    mainGameScript = GameObject.Find("MainGameScript"); //gameobject find is okay if it's in your start method
   //make sure you set your main game script's script execution order to FIRST
}

void Update()
{
    if (mainGameScript.mainInput_Ray.hittingSomething && (mainGameScript.mainInput_Ray.hit.transform == this.transform.parent.transform)) {
   }
}

Then throughout your entire project whenever you need to check if something is hit you do mainInput_Ray.hittingSomething == true???, check the results, throw an && in the if statement, just make sure the scene if fully loaded. Personally I have a state machine in my main game object that handles the loading screen, saving and loading of data and has a ‘SceneActive’ state I check against first.

Now if you have a VR controller you just have to replace this part:

mainInput_Ray.ray = MG_Camera.GetComponent<Camera>().ScreenPointToRay(Input.mousePosition);

This code is optimized just like OnMouseEnter, because you aren’t creating a new ray all together each and every frame, there is only one global ray you check against.

I’m updating the answer since a lot of links trace to this post despite it being depreciated.

Color _startcolor;
[SerializeField] Renderer _renderer;

void OnMouseEnter ()
{
    _startcolor = _renderer.material.color;
    _renderer.material.color = Color.red;
}

void OnMouseExit ()
{
    _renderer.material.color = _startcolor;
}

Hey! I know this thread is pretty old, but it gave me the jumpstart I needed to get my colour change script working. I am VERY new to C#, so please let me know if this seems like a bad way of doing it.

Essentially I was able to get the OnMouseOver portion to work from the other replies, but not the OnMouseExit – the colour wouldn’t return to the startColour. I found that getting the startColour in Start fixed this. See below:

public class Highlight : MonoBehaviour
{
    private Color startColour;

    private void Start()
    {
        startColour = GetComponent<Renderer>().material.color; 
    }
    private void OnMouseOver()
    {
        GetComponent<Renderer>().material.color = new Color(1, 0, 0, 1);
    }

    private void OnMouseExit()
    {
        GetComponent<Renderer>().material.color = startColour;
    }
}