How can I highlight objects when moving the mouse cursor above them ? OnMouseEnter never fire.

I have a Camera in the Hierarchy called Map Camera.
On the Map Camera I attached a script called Map.

And I have also in the Hierarchy a Space Station and as child a _Level and under _Level there are 20 childs.
I want that when the game is running in the game view window when I will move the mouse cursor over one of the 20 childs the current child the mouse cursor is above will highlight. The idea is to create kind of real time map.

This is the Map script:
In the Map script I’m adding to each child under _Level a script name MapHighlight and a component BoxCollider. So when I’m running the game for example the child Corridor_Window_Part_05 under _Level have also the script MapHighlight and also a box collider.

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

public class Map : MonoBehaviour
{
    public Camera mapCamera;

    private Camera[] cameras;

    // Use this for initialization
    void Start()
    {
        cameras = Camera.allCameras;

        GameObject levels = GameObject.Find("_Level");
        foreach (Transform child in levels.transform)
        {
            child.gameObject.AddComponent<MapHighlight>();
            child.gameObject.AddComponent<BoxCollider>();
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.M))
        {
            if (mapCamera.enabled == false)
            {
                foreach (Camera cam in cameras)
                {
                    cam.enabled = false;
                }
                mapCamera.enabled = true;
            }
            else
            {
                foreach (Camera cam in cameras)
                {
                    cam.enabled = true;
                }
                mapCamera.enabled = false;
            }
        }
    }
}

And this is the MapHighlight script:

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

public class MapHighlight : MonoBehaviour
{
    private Color startcolor;

    private void OnMouseEnter()
    {
        startcolor = GetComponent<Renderer>().material.color;
        GetComponent<Renderer>().material.color = Color.white;
    }

    private void OnMouseExit()
    {
        // Remove the white color.
    }
}

When I’m running the game and moving the mouse cursor over one of the childs it’s never getting to the OnMouseEnter. I tried to use a break point on the line:

startcolor = GetComponent<Renderer>().material.color;

But it’s never get there.

This is a screenshot when the game is running you can see for example on the child Corridor_Window_Part_05 the MapHighlight script and the box collider:

In the game view on the bottom left it’s the space station using the Map Camera.
When I’m moving the mouse over the space station I want that the objects child under _Level to be highlighted.

I tried to add also a box collider to the Map Camera I tried to play with the box collider Is Trigger change it on/off on the map camera and also on the children. But nothing worked so far.

Just to confirm, you have a real mouse cursor on the screen? You’re not hiding the cursor?

The most likely issue is that there’s something else in front of the object you’re trying to mouse over. For example, consider this Capsule in front of a Cylinder:

The Cylinder has a script with OnMouseOver/OnMouseEnter methods on it, which get called when the mouse is over a pixel that belongs to the cylinder. However, if the mouse is over part of the Capsule that’s covering the cylinder, OnMouseOver/OnMouseEnter doesn’t get called. It gets blocked.

This thread probably has some approaches you can use, either by adjusting your collider settings, or using a raycast to detect whether the object is anywhere “through” the screen under the mouse:

1 Like

I’m hiding the mouse cursor when the game is running but then I’m pressing escape to bring the mouse cursor again. Maybe this is the problem ?

Hiding the cursor alone should not stop OnMouseOver. lockState can have an effect on it instead.

Personally, I’ve never used OnMouseOver so I don’t know how it works, but sounds like the following solution could solve your problems. What it does is, gets mouse position and raycasts forward from it. First thing it hits is the object you can manipulate. You can also give it an extra overload method to check for specific layers only, or filter them out with.
This implementation is also easy to convert in to a touch input solution(just change Input.mousePosition to Input.GetTouch(0).position:

GameObject mouseOvered;

void Update{
bool rcHit;
Vector3 mouse = Input.mousePosition;
Ray castPoint = Camera.main.ScreenPointToRay(mouse);
RaycastHit hit;
if (Physics.Raycast(castPoint, out hit, Mathf.Infinity)){
            rcHit = true;
            if (mouseOvered != hit.collider.gameObject){
                        mouseOvered = hit.collider.gameObject;
            }
            //do your thing here to apply/change the material
}
if (!rcHit && mouseOvered != null){
            //do your thing to undo the material change
            mouseOvered = null;
}
}

You can also give it an extra overload method to check for specific layers only, or filter them out with:

layer = LayerMask.GetMask("YourLayer");
...
.
.
.
...
if (Physics.Raycast(castPoint, out hit, Mathf.Infinity, layer))
1 Like

This way it’s working but the ray laser is coming out from my player and not the Map Camera.
The script Map is attached to the Map Camera.

So i turned off the Main Camera on my first person player.
Now I don’t see any laser of the ray coming out from the Map Camera:

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

public class Map : MonoBehaviour
{
    public Camera mapCamera;

    private Camera[] cameras;
    private GameObject mouseOvered;

    // Use this for initialization
    void Start()
    {
        cameras = Camera.allCameras;
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.M))
        {
            if (mapCamera.enabled == false)
            {
                foreach (Camera cam in cameras)
                {
                    cam.enabled = false;
                }
                mapCamera.enabled = true;
            }
            else
            {
                foreach (Camera cam in cameras)
                {
                    cam.enabled = true;
                }
                mapCamera.enabled = false;
            }
        }

        bool rcHit = false;
        Vector3 mouse = Input.mousePosition;
        Ray castPoint = mapCamera.ScreenPointToRay(mouse);
        RaycastHit hit;
        Debug.DrawRay(mapCamera.transform.position, mapCamera.transform.forward * Mathf.Infinity, Color.magenta);
        if (Physics.Raycast(castPoint, out hit, Mathf.Infinity))
        {
            rcHit = true;
            if (mouseOvered != hit.collider.gameObject)
            {
                mouseOvered = hit.collider.gameObject;
            }
            print(mouseOvered.name);
            //do your thing here to apply/change the material
        }
        if (!rcHit && mouseOvered != null)
        {
            //do your thing to undo the material change
            mouseOvered = null;
        }
    }
}

I added the line:

Debug.DrawRay(mapCamera.transform.position, mapCamera.transform.forward * Mathf.Infinity, Color.magenta);

But I don’t see this DrawRay magenta.

And when the ray hit the space station parts it’s printing the name:

print(mouseOvered.name);

But not all the time it’s not smooth. I mean it’s not hitting everything and all the time.
I’m pressing escape and then moving the mouse cursor around only in some specific places it’s hitting the objects.