Search Unity

OnMouseDown for right click

Discussion in 'Scripting' started by shaun, Nov 7, 2007.

Thread Status:
Not open for further replies.
  1. shaun

    shaun

    Joined:
    Mar 23, 2007
    Posts:
    728
    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
     
    Shani_T8 likes this.
  2. minevr

    minevr

    Joined:
    Mar 4, 2008
    Posts:
    1,018
    Hi,shaun....I see you....haa~~

    I need OnMouseDown for right click, too.
     
  3. Yhoko_legacy

    Yhoko_legacy

    Joined:
    Feb 19, 2010
    Posts:
    37
    Code (csharp):
    1. function Update()
    2. {
    3.    if(Input.GetMouseButtonDown(0)) Debug.Log("Pressed left click.");
    4.    if(Input.GetMouseButtonDown(1)) Debug.Log("Pressed right click.");
    5.    if(Input.GetMouseButtonDown(2)) Debug.Log("Pressed middle click.");
    6. }
    7.  
    See the docs.
     
  4. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    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
     
  5. devans770

    devans770

    Joined:
    Nov 25, 2010
    Posts:
    45
    Havn't tried but would this work?

    Code (csharp):
    1.  
    2. function OnMouseDown  ()
    3. {
    4.    if(Input.GetMouseButtonDown(0)) Debug.Log("Pressed left click.");
    5.    if(Input.GetMouseButtonDown(1)) Debug.Log("Pressed right click.");
    6.    if(Input.GetMouseButtonDown(2)) Debug.Log("Pressed middle click.");
    7. }
    8.  
    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..
     
    ortenbergmaksim likes this.
  6. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    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:

    Code (csharp):
    1. function OnMouseOver () {
    2.     If(Input.GetMouseButtonDown(1)){
    3.         //do stuff here
    4.     }
    5. }
     
    Last edited: Jan 6, 2011
  7. V-Portela

    V-Portela

    Joined:
    Nov 7, 2013
    Posts:
    6
    Great Idea ;)
    Thanks!
     
  8. hellaciousphlegm

    hellaciousphlegm

    Joined:
    Mar 18, 2020
    Posts:
    2
    im sorry but thats not what we need we need it so if we click THE OBJECT
     
  9. wpetillo

    wpetillo

    Joined:
    May 23, 2017
    Posts:
    24
    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:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [CreateAssetMenu(menuName = "Playcraft/Basic Data Types/Tag", fileName = "Tag")]
    4. public class TagSO : ScriptableObject { }
    2. 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:

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.Events;
    4.  
    5. namespace Playcraft
    6. {
    7.     public class RespondToEventID : MonoBehaviour
    8.     {
    9.         [SerializeField] EventResponse[] elements = default;
    10.      
    11.         [SerializeField] bool locked = false;
    12.         public void SetLock(bool value) { locked = value; }
    13.  
    14.         public void Input(TagSO value)
    15.         {
    16.             if (locked) return;
    17.              
    18.             foreach (var item in elements)
    19.                 if (item.id == value)
    20.                     item.Response.Invoke();
    21.         }
    22.      
    23.         [Serializable] struct EventResponse
    24.         {
    25.             #pragma warning disable 0649
    26.             public TagSO id;
    27.             public UnityEvent Response;
    28.             #pragma warning restore 0649
    29.         }
    30.     }
    31. }
    3. 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:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. // Input: external trigger, optional event tag
    4. // Process: check if mouse is over a valid collider
    5. // Output: RaycastHit (if any), relay event tag to hit if it has and attached RespondToEventID
    6. namespace Playcraft
    7. {
    8.     public class MouseRaycast : MonoBehaviour
    9.     {
    10.         #pragma warning disable 0649
    11.         [SerializeField] RaycastHitEvent Output;
    12.         [SerializeField] LayerMask layerMask;
    13.         [SerializeField] QueryTriggerInteraction triggerInteraction;
    14.         #pragma warning restore 0649
    15.  
    16.         public void GetHit(TagSO id = null)
    17.         {
    18.             var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    19.             RaycastHit hit;
    20.          
    21.             if (!Physics.Raycast(ray, out hit, Mathf.Infinity, layerMask, triggerInteraction)) return;
    22.             Output.Invoke(hit);
    23.              
    24.             if (id == null) return;
    25.             var relay = hit.collider.GetComponent<RespondToEventID>();
    26.             if (relay) relay.Input(id);
    27.         }
    28.     }
    29. }
    4. Put this script anywhere in your project:

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.Events;
    4.  
    5. namespace Playcraft
    6. {
    7.     public enum PressType { Down, Up, Continuous }
    8.     public enum MouseButton { None, Left, Right, Center, Any }
    9.  
    10.     [Serializable] class MouseClickInput
    11.     {
    12.         #pragma warning disable 0649
    13.         [SerializeField] MouseButton button;
    14.         [SerializeField] PressType pressType;
    15.         [SerializeField] UnityEvent Output;
    16.         #pragma warning restore 0649
    17.                          
    18.         public void Update()
    19.         {
    20.             var id = MouseStatics.GetIntFromButton(button);
    21.             bool active = false;
    22.                  
    23.             switch (pressType)
    24.             {
    25.                 case PressType.Down: active = Input.GetMouseButtonDown(id); break;
    26.                 case PressType.Up: active = Input.GetMouseButtonUp(id); break;
    27.                 case PressType.Continuous: active = Input.GetMouseButton(id); break;
    28.             }
    29.                  
    30.             if (active) Output.Invoke();
    31.         }
    32.     }  
    33. }
    34.  
    5. 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:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. // Input: Game Engine
    4. // Process: continuous check for mouse button clicks
    5. // Output: event triggers per type
    6. namespace Playcraft
    7. {
    8.     public class GetMouseInput : MonoBehaviour
    9.     {
    10.         [SerializeField] MouseClickInput[] clickInput = default;
    11.  
    12.         private void Update()
    13.         {          
    14.             foreach (var input in clickInput)
    15.                 input.Update();              
    16.         }
    17.     }
    18. }
    6. 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.

    7. 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.
     
  10. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,205
    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.

    https://docs.unity3d.com/2019.1/Documentation/ScriptReference/EventSystems.IPointerClickHandler.html
    Code (csharp):
    1. using UnityEngine;
    2. using UnityEngine.EventSystems;
    3.  
    4. public class Foo : MonoBehaviour, IPointerClickHandler
    5. {
    6.     public void OnPointerClick(PointerEventData eventData)
    7.     {
    8.         if (eventData.button == PointerEventData.InputButton.Right)
    9.             Debug.Log("Right button pressed.");
    10.     }
    11. }
     
    Last edited: Aug 9, 2020
    kyleloii, NickOKC, swimswim and 17 others like this.
  11. unity_S5sbHsTF0N3uRA

    unity_S5sbHsTF0N3uRA

    Joined:
    May 31, 2021
    Posts:
    3
    upload_2021-6-17_12-15-30.png

    Perhaps this option may be suitable.
     
  12. itsjustoneguy

    itsjustoneguy

    Joined:
    Jun 21, 2015
    Posts:
    8
    I had this exact problem and made this video as the solution. It's a lot simpler that what I see here.
     
  13. AFriendlyUnityDeveloper

    AFriendlyUnityDeveloper

    Joined:
    Dec 26, 2018
    Posts:
    33
    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
     
  14. RadRedPanda

    RadRedPanda

    Joined:
    May 9, 2018
    Posts:
    1,648
    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.
     
    Last edited: Jun 30, 2022
    SeerSucker69 likes this.
  15. lackhand

    lackhand

    Joined:
    Aug 30, 2021
    Posts:
    1
    @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?
     
    RadRedPanda likes this.
  16. RadRedPanda

    RadRedPanda

    Joined:
    May 9, 2018
    Posts:
    1,648
    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.
     
  17. FullMeltNick

    FullMeltNick

    Joined:
    Oct 8, 2018
    Posts:
    3
    genius
     
  18. joan-bdm

    joan-bdm

    Joined:
    Mar 9, 2015
    Posts:
    2

    This is the proper answer. Thanks!
     
    Jilbarkus likes this.
  19. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    The proper way to say thanks is to click the Like button. This thread is 16 years old. Please don't necropost threads.

    Thanks.
     
Thread Status:
Not open for further replies.