Detect right clicks on game objects in Unity3D

The problem

I’ve seen a lot of people asking for help on forums on how to detect right clicks in a Unity3D game. It’s indeed not that easy as no native method is really made for it.

We have the good oldĀ OnMouseDown method that can be used on any game object having a collider component but it only handles the left clicks šŸ™

Web games warning: first disable context menu!

By default, when you build your game for web player, right clicks on the game frame will open the context menu.

You can easily disable this behavior by setting theĀ disableContextMenu parameter to true in your web page’s javascript code.

SeeĀ web player’s behavior documentation for more details.

The easy way

The solution

As mentionned by Eric5h5 in his answer to my unity3D forum thread, thereā€™s a very easy way to detect right clicks on a game objects in Unity3D.

The principles is to combine OnMouseOver and Input.GetMouseButtonDown methods.

The first one is triggered when the mouse cursor is dragged over current game object. Every left/right/middle mouse button click on our game object will occur while the mouse cursor is over it. So this is our first filter.

The second one will return true if one of the mouse button as been pressed during the frame it’s being called. The first (integer) parameter of this methodĀ specifies which mouse button you want to track (0 for left button, 1 for right button, 2 for the middle button). This is how we know if a right click as occur on our game object.

The code

<br />
function OnMouseOver()<br />
{<br />
    if (Input.GetMouseButtonDown(1))<br />
    {<br />
        // Right button clicked on this object<br />
    }<br />
}<br />

Pros and cons

The advantage of this method is that it’s easy to implement and it also works on GUI texts and textures.

The counterpart is that the code will have to be executed on every game object you want to listen for right clicks.

Simply put, it is the best solution for most of the cases but you could need to optimize your code and want to scan clicks only once per frame. The next chapter presents another solution which is recommenced for scenes with a lot of game objects tracking right clicks.

TheĀ complicated/optimizedĀ way

Detect mouse button clicks

The right way to detect right (and middle) clicks is to use the Input class and especially its GetMouseButtonDown method.

As the Unity3D script reference documentation states it, the first (integer) parameter of this method specifies the mouse button you want to track (0 for left button, 1 for right button, 2 for the middle button). All right, so now we know when the left/right/middle mouse button is clicked! … but wait, what has been clicked ?

Find the targeted game object

Our new problem is to know which game object was targeted during the click we just detected. Indeed, unlike the OnMouseDown method, the GetMouseButtonDown is a method of the Input class, which isn’t “linked” to any game object in particular.

The way we’ll solve this problem is pretty simple: draw a line from camera to mouse position and continue drawing until our pen hits something (our target). There’s a very useful tool present in Unity3D which will help us to perform it: ray casting (simply put, “ray” = “line” and “casting” = “drawing” šŸ™‚ ), and more precisely the Physics.RayCast method.

But first we have to build this ray. We know current mouse position thanks to the Input.MousePosition vector. We also know where our main camera is placed as we can access its transform component.

We could build it using those 2 informations but there’s an easier way to do it:Ā the Camera.ScreenToPointRay method. Simply set the mouse position as first parameter of this method and magic! you have your ray.

Final step is to find which game object has been hit by the ray we just casted. Once again it’s pretty simple as the Physics.RayCast method takes a pointer/modifiableĀ parameter name “hitinfo”. This parameter will be filled with a RaycastHit object, containing the transform of the targeted game object. Add a “.gameObject” to the result and you get your target!

[Advanced] Wait not this one, the one behind it

Maybe you just want to listen for clicks on your main character and don’t want to trigger anything when clicking on the robot passing by between your camera and your character. Or you still want your click to be detected when he moved behind a tree. You can do it by using Unity3D’s layer filtering feature.

By chance, the Physics.RayCast method handles it perfectly šŸ™‚ Just set the correct layer mask has fourth parameter and you’re done: ray will only hit game objects of the layer(s) you specified.

ClickDetector.cs

Here’s the script I use on several of my Unity3D projects for mouse click detection. It can be reused on any project as it doesn’t rely on any other specific class.

It’s based on the SendMessage method usage and is fully customizable (see exposed parameters in Unity3D editor).

Simply drag it to only one game object in your scene and define the OnLeft/Right/Middle methods on the game objects you want to handle clicks.

Download this script or copy it from following source:

<br />
using UnityEngine;<br />
using System.Collections;<br />
public class ClickDetector : MonoBehaviour<br />
{<br />
	public bool HandleLeftClick = true;<br />
	public bool HandleRightClick = true;<br />
	public bool HandleMiddleClick = false;<br />
	public string OnLeftClickMethodName = &quot;OnLeftClick&quot;;<br />
	public string OnRightClickMethodName = &quot;OnRightClick&quot;;<br />
	public string OnMiddleClickMethodName = &quot;OnMiddleClick&quot;;<br />
	public LayerMask layerMask;<br />
	void Update()<br />
	{<br />
		GameObject clickedGmObj = null;<br />
		bool clickedGmObjAcquired = false;<br />
		// Left click<br />
		if (HandleLeftClick &amp;&amp; Input.GetMouseButtonDown(0))<br />
		{<br />
			/*if (!clickedGmObjAcquired)<br />
			{*/<br />
				clickedGmObj = GetClickedGameObject();<br />
				clickedGmObjAcquired = true;<br />
			/*}*/<br />
			if (clickedGmObj != null)<br />
				clickedGmObj.SendMessage(OnLeftClickMethodName, null, SendMessageOptions.DontRequireReceiver);<br />
		}<br />
		// Right click<br />
		if (HandleRightClick &amp;&amp; Input.GetMouseButtonDown(1))<br />
		{<br />
			if (!clickedGmObjAcquired)<br />
			{<br />
				clickedGmObj = GetClickedGameObject();<br />
				clickedGmObjAcquired = true;<br />
			}<br />
			if (clickedGmObj != null)<br />
				clickedGmObj.SendMessage(OnRightClickMethodName, null, SendMessageOptions.DontRequireReceiver);<br />
		}<br />
		// Middle click<br />
		if (HandleMiddleClick &amp;&amp; Input.GetMouseButtonDown(2))<br />
		{<br />
			if (!clickedGmObjAcquired)<br />
			{<br />
				clickedGmObj = GetClickedGameObject();<br />
				clickedGmObjAcquired = true;<br />
			}<br />
			if (clickedGmObj != null)<br />
				clickedGmObj.SendMessage(OnMiddleClickMethodName, null, SendMessageOptions.DontRequireReceiver);<br />
		}<br />
	}<br />
	GameObject GetClickedGameObject()<br />
	{<br />
		// Builds a ray from camera point of view to the mouse position<br />
		Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);<br />
		RaycastHit hit;<br />
		// Casts the ray and get the first game object hit<br />
		if (Physics.Raycast(ray, out hit, Mathf.Infinity, layerMask))<br />
			return hit.transform.gameObject;<br />
		else<br />
			return null;<br />
	}<br />
}<br />

Demo project

A demo is worth a thousand words so here’s a project showing how to use it all.

Awaiting your comments and feedbacks! šŸ˜‰


Related posts:

13 Responses to Detect right clicks on game objects in Unity3D
  1. Jonathan Fryxelius Reply

    Hi! I am new to Unity3D and I am presently trying to create my first game. This explanation of the Right-Mouse-Button problem and the Demo project has greatly helped me. Just wanted you to know that, and to say a great Thank You!

    • GFX47 Reply

      You’re welcome, glad I could help! šŸ˜‰

  2. Nireas Reply

    You are a god (not really, but close :)). Very helpful and informative for new Unity users

    • GFX47 Reply

      Comment approved! XD

  3. Zinon Reply

    Hello good sir,
    Can you explain to a new Unity user a bit more how to use this nice piece of code that you so unselfishly share it with us?
    For example: I have created a tile grid and I have tile objects and unit objects on the map (as you may have guessed it’s a turn-based strategy wanna be game). How can I use your ClickDetector?
    I have put your script on an empty object in my scene, but what next? Do I have to put any code in my “tile” and “unit” objects? I can understand most of the code, but the variables at the top before the update functions and the SendMessage confuse me.
    Thank you for your code and it would be really nice, if you could help me šŸ™‚

    • Zinon Reply

      Just something more to ask. Do you think that your script is a good solution to handle mouse clicks for my project or shall I try to find something different?

  4. Jay Borman Reply

    If you’re using the right click and don’t want that menu in your face:

    File > Build Settings > Player Settings > “Resolution and Presentation” > WebPlayer Template” > “No Context Menu”

  5. Gary G Reply

    I downloaded the ClickDetect.cs code but not having any luck getting it to work. The Raycast() in GetClickedGameObject() is always returning null.

    • Gary G Reply

      I also have the demo project which works. Is there a camera setting that I am missing?

      • Gary G Reply

        I copy one of the cubes from the demo scene to my scene. Clicking on the cube works, but still nothing for the objects I have created. In the editor my object is the same as cube. What am I missing?

        • Ujn Hunter Reply

          Make sure you copy the MyClickHandler.js to the object you want to be clickable. Also make sure the “Layer Filter” is setup properly in the ClickDetector.cs object. Hope this helps.

  6. Ujn Hunter Reply

    Thanks for your help. I’m not familiar with JavaScript, is there a reason you’re using C# mixed with JavaScript? I’d love to be able to change the MyClickHandler.js to MyClickHandler.cs so that I can add more code… alas I don’t know how to change the JavaScript to C# code.

Leave a Reply

Your email address will not be published. Please enter your name, email and a comment.