OnMouseDown for right click

Why is OnMouseDown() only called on the left button?
I’m not sure about general Mac users, but on Windows, the right button is used for context sensitive functionality in almost all apps.

Thanks
Shaun

2 Likes

Hi,shaun…I see you…haa~~

I need OnMouseDown for right click, too.

function Update()
{
   if(Input.GetMouseButtonDown(0)) Debug.Log("Pressed left click.");
   if(Input.GetMouseButtonDown(1)) Debug.Log("Pressed right click.");
   if(Input.GetMouseButtonDown(2)) Debug.Log("Pressed middle click.");
}

See the docs.

7 Likes

He’s referring to the OnMouseDown() event handler that you can use when hovering over GUIElements and colliders, which only gets triggered by the left mouse button.

http://unity3d.com/support/documentation/ScriptReference/MonoBehaviour.OnMouseDown.html

2 Likes

Havn’t tried but would this work?

function OnMouseDown  () 
{
   if(Input.GetMouseButtonDown(0)) Debug.Log("Pressed left click.");
   if(Input.GetMouseButtonDown(1)) Debug.Log("Pressed right click.");
   if(Input.GetMouseButtonDown(2)) Debug.Log("Pressed middle click.");
}

If it doesn’t another way would be to have a cript attached to say your camera that captures the Input.GetMouseButton(1) in the update and raycasts into the scene. You could then invoke SendMessage(“OnRightMouseButtonDown”,SendMessageOptions.DontRequireReceiver) to the colliders that are hit. You can then implement the function OnRightMouseButtonDown in scripts that are attached to the objects in your scene…

1 Like

Devans, that wouldn’t work, because OnMouseDown is only trigger by a left mouse click… so you’d basically have to be holding both mouse buttons. You could however do this:

function OnMouseOver () {
    If(Input.GetMouseButtonDown(1)){
        //do stuff here
    }
}
32 Likes

Great Idea :wink:
Thanks!

im sorry but thats not what we need we need it so if we click THE OBJECT

I’ve come up with a solution to this, which extends to interactions and mouse input generally, that takes some work to set up but is easy to use and quite powerful once you have it going.

  1. Put this in your project and create scriptable objects for right click, left click, and whatever other event identifiers you need:
using UnityEngine;

[CreateAssetMenu(menuName = "Playcraft/Basic Data Types/Tag", fileName = "Tag")]
public class TagSO : ScriptableObject { }
  1. Attach this script to the object in your scene (must also have a collider attached) that you want to respond to mouse clicks. Note that this script can also be used for any event-driven system, kind of like what’s described in the Unite Austin 2017 talk “Game Architecture with Scriptable Objects” but with less overhead and allowing for multiple instances to act independently while following the same structure:
using System;
using UnityEngine;
using UnityEngine.Events;

namespace Playcraft
{
    public class RespondToEventID : MonoBehaviour
    {
        [SerializeField] EventResponse[] elements = default;
      
        [SerializeField] bool locked = false;
        public void SetLock(bool value) { locked = value; }

        public void Input(TagSO value)
        {
            if (locked) return;
              
            foreach (var item in elements)
                if (item.id == value)
                    item.Response.Invoke();
        }
      
        [Serializable] struct EventResponse
        {
            #pragma warning disable 0649
            public TagSO id;
            public UnityEvent Response;
            #pragma warning restore 0649
        }
    }
}
  1. Attach this script to any object in your scene, preferably the Camera, and make sure the layer mask field is set to everything, or includes whatever layer your object is on:
using UnityEngine;

// Input: external trigger, optional event tag
// Process: check if mouse is over a valid collider
// Output: RaycastHit (if any), relay event tag to hit if it has and attached RespondToEventID
namespace Playcraft
{
    public class MouseRaycast : MonoBehaviour
    {
        #pragma warning disable 0649
        [SerializeField] RaycastHitEvent Output;
        [SerializeField] LayerMask layerMask;
        [SerializeField] QueryTriggerInteraction triggerInteraction;
        #pragma warning restore 0649

        public void GetHit(TagSO id = null)
        {
            var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
          
            if (!Physics.Raycast(ray, out hit, Mathf.Infinity, layerMask, triggerInteraction)) return;
            Output.Invoke(hit);
              
            if (id == null) return;
            var relay = hit.collider.GetComponent<RespondToEventID>();
            if (relay) relay.Input(id);
        }
    }
}
  1. Put this script anywhere in your project:
using System;
using UnityEngine;
using UnityEngine.Events;

namespace Playcraft
{
    public enum PressType { Down, Up, Continuous }
    public enum MouseButton { None, Left, Right, Center, Any }

    [Serializable] class MouseClickInput
    {
        #pragma warning disable 0649
        [SerializeField] MouseButton button;
        [SerializeField] PressType pressType;
        [SerializeField] UnityEvent Output;
        #pragma warning restore 0649
                          
        public void Update()
        {
            var id = MouseStatics.GetIntFromButton(button);
            bool active = false;
                  
            switch (pressType)
            {
                case PressType.Down: active = Input.GetMouseButtonDown(id); break;
                case PressType.Up: active = Input.GetMouseButtonUp(id); break;
                case PressType.Continuous: active = Input.GetMouseButton(id); break;
            }
                  
            if (active) Output.Invoke();
        }
    }  
}
  1. Attach this script to any object in your scene, again the Camera would make sense. Note that this script (combined with the one above) can be used for anything that needs to respond to mouse clicks and the pattern can be used as the basis for any input system:
using UnityEngine;

// Input: Game Engine
// Process: continuous check for mouse button clicks
// Output: event triggers per type
namespace Playcraft
{
    public class GetMouseInput : MonoBehaviour
    {
        [SerializeField] MouseClickInput[] clickInput = default;

        private void Update()
        {          
            foreach (var input in clickInput)
                input.Update();              
        }
    }
}
  1. Now it’s time to wire it all together in the inspector. Start with the GetMouseInput component, expand the Click Input array to include all of the mouse click events you are interested in, and for each of them call MouseRaycast.GetHit, sending in identifying TagSO scriptable objects.

  2. On the RespondToEventID component of the scene object with the collider, add elements to the array for each mouse event you want to respond to and fill in the corresponding UnityEvent list for what you want to have happen when each of those conditions.

This code and an example usage can be found on a public repository I maintain here: https://github.com/Will9371/Character-Template/tree/master/Assets/Playcraft/UI/Example. This project includes a host of other Quality of Life scripts, as well as template character controllers for 1st person, 3rd person, VR, a simple dialog controller, object pooling, and other more work-in-progress systems.

This is a very old thread and I’m guessing IPointerClickHandler didn’t exist back when it was created. Below is the easiest solution to this problem though it does require the camera have a PhysicsRaycaster component, the object itself have a collider component, and an EventSystem in the scene with the appropriate UI input module.

Chances are very good though you will have most of the above if not all of it already present in the scene.

using UnityEngine;
using UnityEngine.EventSystems;

public class Foo : MonoBehaviour, IPointerClickHandler
{
    public void OnPointerClick(PointerEventData eventData)
    {
        if (eventData.button == PointerEventData.InputButton.Right)
            Debug.Log("Right button pressed.");
    }
}
20 Likes

Perhaps this option may be suitable.

I had this exact problem and made this video as the solution. It’s a lot simpler that what I see here.

I dont think that will work, will it?

That “OnMouseOver” only gets called the first time the user mouses over the object. So if they mouse over and THEN click it won’t work.

ie:

  • User mouses over collider
  • OnMouseOver fires, button is not down so nothing happens
  • THEN the user clicks a few frames later
  • Nothing happens because OnMouseOver doesn’t get called again

OnMouseOver() runs every frame the mouse is over the object, so it should work.

EDIT: OnMouseExit only runs on the frame after the mouse exits the collider.

Also, OnMouseExit() also runs every frame that the mouse is not on the object. I definitely think the name of this method could’ve had a little more work, as it’s not what you might expect.

OnMouseEnter() however, runs on the single frame it enters, as you might’ve thought OnMouseOver() did.

1 Like

@RadRedPanda , OnMouseExit runs only on the frame where the mouse leaves the object – not every mouseless frame. I just tested it.
Maybe there’s some other circumstance that can trigger the weird behavior you described?

1 Like

That’s interesting, you’re correct as I tested it as well. I don’t recall the reason I would have specifically called it out incorrectly though, so I guess I’ll chalk it up to being a mistake on my part.

genius

This is the proper answer. Thanks!

1 Like

The proper way to say thanks is to click the Like button. This thread is 16 years old. Please don’t necropost threads.

Thanks.