Home > Software engineering >  Unity: OnMouseEnter() and OnMouseExit() are repeatedly called while OnMouseDrag()
Unity: OnMouseEnter() and OnMouseExit() are repeatedly called while OnMouseDrag()

Time:09-22

While onm ouseDrag() is called, if I move mouse fast then onm ouseEnter() and onm ouseExit() are repeatedly called, so I made a new script but the same problem happens. If I move mouse slowly, they aren't called. I don't know what's the problem. Anyone can help me?

I hope they are not called while dragging. While I drag, the object is attached to the mouse so I think onm ouseEnter() and onm ouseExit() shouldn't be called.

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

public class NewBehaviourScript : MonoBehaviour
{
    private void onm ouseEnter()
    {
        // If mouse enters the object, the color of the object becomes red and prints "Enter"
        Debug.Log("Enter");
        GetComponent<SpriteRenderer>().color = Color.red;
    }

    private void onm ouseExit()
    {
        // If mouse exits the object, the color of the object becomes white and prints "Exit"
        Debug.Log("Exit");
        GetComponent<SpriteRenderer>().color = Color.white;
    }

    private void onm ouseDrag()
    {
        // If I click the object and drag, it follows mouse
        // Then onm ouseEnter() and onm ouseExit() is called repeatedly
        // and the color becomes red and white and both "Enter" and "Exit" are printed
        // Utilities.MousePos has the position of mouse, and it doesn't have any problem.
        transform.position = Utilities.MousePos;
    }
}

CodePudding user response:

It happens because OnMouseEnter() and OnMouseExit() is handled before OnMouseDrag(). So every frame there are things like this happen:

  1. You move your mouse and Unity handle that its position changed
  2. Unity checked the mouse and object positions and see, that mosue moved outside the object, so OnMouseExit() is being called. As your metion it happens if you move your mouse fast enough to make it leave object with one frame
  3. Unity hande drag event and call OnMouseDrag(). The position of object changed in it.
  4. Cause position of object changing Untiy again checking for mouse and object positions and find out that mouse cursor is over the object. And call OnMouseEnter()

The workaround, that I cant suggest is to implement own dragging logic like this:

using UnityEngine;

public class DraggableObj : MonoBehaviour
{

    private bool _hovered;
    private bool _dragged;
    
    private bool Hovered {
        set
        {
            _hovered = value;
            UpdateState();
        }
        get => _hovered;
    }
    
    private bool Dragged {
        set
        {
            _dragged = value;
            UpdateState();
        }
        get => _dragged;
    }
    
    private void onm ouseEnter()
    {
        Hovered = true;
    }
    
    private void onm ouseExit()
    {
        Hovered = false;
    }

    private void onm ouseDown()
    {
        Dragged = true;
    }

    private void onm ouseUp()
    {
        Dragged = false;
    }

    private void UpdateState()
    {
        if (Hovered || Dragged)
            gameObject.GetComponent<Renderer>().material.color = Color.red;
        else 
            gameObject.GetComponent<Renderer>().material.color = Color.white;
    }

    private void FixedUpdate()
    {
        if (Dragged)
        {
            // Here you should implement your positioning logic. This one is just for example.
            transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition   Vector3.forward * 10f);
        }
    }
}

  • Related