OnMouseDown/etc won’t work in scenes with multiple cameras and one being Orthographic.
I think I’ve solved some of them (still need to add a LayerMask), but I’m not sure how do the OnMouseEnter/Exit properly. The issue is just sending the message once.
I was thinking just store the hoveredGO at all times, and check if it changes, but I’m not sure how to get the OnMouseExit to work doing this:
public GameObject hoveredGO;
void Update()
{
RaycastHit hitInfo = new RaycastHit();
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
// OnMouseDown
if (Input.GetMouseButtonDown(0))
{
if (Physics.Raycast(ray, out hitInfo))
{
hitInfo.collider.SendMessage("OnMouseDown", SendMessageOptions.DontRequireReceiver);
}
}
// OnMouseUp
if (Input.GetMouseButtonUp(0))
{
if (Physics.Raycast(ray, out hitInfo))
{
hitInfo.collider.SendMessage("OnMouseUp", SendMessageOptions.DontRequireReceiver);
}
}
// OnMouseOver
if (Physics.Raycast(ray, out hitInfo))
{
hitInfo.collider.SendMessage("OnMouseOver", SendMessageOptions.DontRequireReceiver);
}
// OnMouseEnter
if (Physics.Raycast(ray, out hitInfo))
{
if (hitInfo.collider.gameObject != hoveredGO)
{
hitInfo.collider.SendMessage("OnMouseEnter", SendMessageOptions.DontRequireReceiver);
hoveredGO = hitInfo.collider.gameObject;
}
}
}
The way you have it now works, but I’d write it a little differently - All you need to do is have a way to remember what the mouse was doing in the previous frame, be it with a boolean or anything. I just chose to use an enum because the names make it simple to look at.
public GameObject hoveredGO;
public enum HoverState{HOVER, NONE};
public HoverState hover_state = HoverState.NONE;
void Update () {
RaycastHit hitInfo = new RaycastHit();
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out hitInfo)){
if(hover_state == HoverState.NONE){
hitInfo.collider.SendMessage("OnMouseEnter", SendMessageOptions.DontRequireReceiver);
hoveredGO = hitInfo.collider.gameObject;
}
hover_state = HoverState.HOVER;
}
else{
if(hover_state == HoverState.HOVER){
hoveredGO.SendMessage("OnMouseExit", SendMessageOptions.DontRequireReceiver);
}
hover_state = HoverState.NONE;
}
if(hover_state == HoverState.HOVER){
hitInfo.collider.SendMessage("OnMouseOver", SendMessageOptions.DontRequireReceiver); //Mouse is hovering
if(Input.GetMouseButtonDown(0)){
hitInfo.collider.SendMessage("OnMouseDown", SendMessageOptions.DontRequireReceiver); //Mouse down
}
if(Input.GetMouseButtonUp(0)){
hitInfo.collider.SendMessage("OnMouseUp", SendMessageOptions.DontRequireReceiver); //Mouse up
}
}
}
You don’t need to use this, but the key here is just having a way to remember what the mouse was doing in the previous frame like the other person commented, so you can check if it only just entered or exited, or is staying over the object.
This is what I used for multi-touch raycasting in a 2D game. It supports many types of messages.
Since I’m very new to programing, I’m interested in any comments and advice on my code.
What I notice in both codes proposed above is that OnMouseDown, OnMouseOver, etc. messages are used. According to this post:
its not good too use OnMouse events in mobile development (Unity has to dance through fiery hoops in every frame to make it work). Therefore IMO its better to use custom messages.
public class TouchInput2D : MonoBehaviour {
public LayerMask touchInputMask;
private Camera cam;
private List<GameObject> touchList = new List<GameObject>();
private List<GameObject> touchListOld = new List<GameObject>();
private RaycastHit2D hit;
void Start ()
{
cam = this.GetComponent<Camera>();
}
void Update ()
{
#if UNITY_EDITOR || UNITY_STANDALONE
if (Input.GetMouseButton(0) || Input.GetMouseButtonDown(0) || Input.GetMouseButtonUp(0))
{
touchListOld.Clear();
touchListOld.AddRange(touchList);
touchList.Clear();
hit = Physics2D.Raycast(cam.ScreenToWorldPoint(Input.mousePosition), Vector2.zero, 1f, touchInputMask);
if (hit.collider != null)
{
GameObject recipent = hit.transform.gameObject;
touchList.Add(recipent);
if (Input.GetMouseButtonDown(0))
{
recipent.SendMessage("OnTouchDown", hit.point, SendMessageOptions.DontRequireReceiver);
}
if (Input.GetMouseButtonUp(0))
{
recipent.SendMessage("OnTouchUp", hit.point, SendMessageOptions.DontRequireReceiver);
}
if (Input.GetMouseButton(0) && Input.GetMouseButtonDown(0) == false &&touchListOld.Contains(recipent) == false)
{
recipent.SendMessage("OnTouchEntered", hit.point, SendMessageOptions.DontRequireReceiver);
}
if (Input.GetMouseButton(0))
{
recipent.SendMessage("OnTouchStay", hit.point, SendMessageOptions.DontRequireReceiver);
}
}
foreach (GameObject g in touchListOld)
{
if (!touchList.Contains(g) && g != null)
{
g.SendMessage("OnTouchExit", hit.point, SendMessageOptions.DontRequireReceiver);
}
}
}
#endif
#if UNITY_IOS
if (Input.touchCount > 0)
{
touchListOld.Clear();
touchListOld.AddRange(touchList);
touchList.Clear();
Touch[] currentTouches = Input.touches;
for (int i = 0; i < Input.touchCount; i++)
{
hit = Physics2D.Raycast(cam.ScreenToWorldPoint(currentTouches*.position), Vector2.zero, 1f, touchInputMask);*
if (hit.collider != null) { GameObject recipent = hit.transform.gameObject; touchList.Add(recipent);
internal class test : MonoBehaviour
{
public GameObject hoveredGO;
public enum HoverState { HOVER, NONE };
public HoverState hover_state = HoverState.NONE;
public bool colour_Changed = false;
private void Awake()
{
hoveredGO = gameObject;
}
void Update()
{
RaycastHit hitInfo = new RaycastHit();
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hitInfo))
{
if (hover_state == HoverState.NONE && hitInfo.collider.gameObject == hoveredGO)
{
colour_Changed = true;
gameObject.GetComponent<Renderer>().material.color = Color.red;
hitInfo.collider.SendMessage("OnMouseEnter", SendMessageOptions.DontRequireReceiver);
hoveredGO = hitInfo.collider.gameObject;
}
hover_state = HoverState.HOVER;
}
else
{
if (hover_state == HoverState.HOVER && colour_Changed == true)
{
hoveredGO.SendMessage("OnMouseExit", SendMessageOptions.DontRequireReceiver);
gameObject.GetComponent<Renderer>().material.color = Color.blue;
colour_Changed = false;
}
hover_state = HoverState.NONE;
}
if (hover_state == HoverState.HOVER)
{
hitInfo.collider.SendMessage("OnMouseOver", SendMessageOptions.DontRequireReceiver); //Mouse is hovering
if (Input.GetMouseButtonDown(0) && hitInfo.collider.gameObject == hoveredGO)
{
hitInfo.collider.SendMessage("OnMouseDown", SendMessageOptions.DontRequireReceiver); //Mouse down
gameObject.GetComponent<Renderer>().material.color = Color.yellow;
}
if (Input.GetMouseButtonUp(0) && hitInfo.collider.gameObject == hoveredGO)
{
hitInfo.collider.SendMessage("OnMouseUp", SendMessageOptions.DontRequireReceiver); //Mouse up
gameObject.GetComponent<Renderer>().material.color = Color.green;
}
}
}
}
However, this script can be used with more object without the problem that when you have 2 or more different gameobjects with the first script it becomes both objects red also if your mouse is only on one of this.