0
\$\begingroup\$

How do I detect Input.GetMouseButtonUp outside a specific GameObject's area in Unity? Are there any Unity Assets for this?

enter image description here

\$\endgroup\$
2
  • \$\begingroup\$ Your question currently is not clear enough. Try editing it with more info. For instance, it's not clear what you mean by "outside a specific GameObject's area". \$\endgroup\$
    – MAnd
    Commented Feb 21, 2016 at 8:38
  • \$\begingroup\$ @MAnd question edited \$\endgroup\$
    – user78900
    Commented Feb 21, 2016 at 9:01

2 Answers 2

1
\$\begingroup\$

You could do it using Vector3.Distance(...), checking the distance between the mouse click position and the object(s). For simplicity though, I would suggest using colliders (sized according to your selection area) and casting rays from the mouse position.

void Update()
{
    if(Input.GetMouseButtonUp(0))
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RayHit hit;
        if(Physics.Raycast(ray, out hit))
        {
            // do what you want
        }
    }
}

You can exclude certain object layers by passing an argument to the physics raycast call. Alternatively, just check that the collider you've hit belongs to a relevant object by checking it's tag, layer, name or one of its components.

Excluding certain layers using a layer mask would be my approach.

Edit: Just to be clear, if you're checking that the click wasn't within one of the non-detection areas, you could use a layer mask to detect only these special colliders and then do:

if(!Physics.Raycast(ray, 1000, layerMask))
{
    // ok
}

Where 1000 is some max distance and the layerMask is used to exclude non-relevant layers.

http://docs.unity3d.com/ScriptReference/LayerMask.html

\$\endgroup\$
2
  • \$\begingroup\$ I personally wouldn't use layerMasks for a single object. hit.gameObject.tag or hit.gameObject.name will work as well to determin, if the object was clicked. \$\endgroup\$
    – user67808
    Commented May 27, 2016 at 6:18
  • \$\begingroup\$ I see what you're saying. As you already suggested, the result will be the same. However, if you end up having a scene with overlapping objects or collision domains, a layer mask would offer superior flexibility for being able to filter out objects as well as a possible speed benefit as the ray can entirely ignore objects not on that layer (Unity specifics not withstanding) \$\endgroup\$
    – zcabjro
    Commented May 27, 2016 at 8:26
0
\$\begingroup\$

Approach one

If this is a 2D game then I would suggest creating a quad and placing it below the rest of your objects. Then whenever GetMouseButtonUp is called fire a RayCast at the quad from the camera. If it hits the quad then you can progress the code. If it is stopped by another collider (i.e. collider defining do not detect here, then stop the code).

This approach I have decided would be worse to implement, I would go for the one below but have kept it in for the sake of completeness.

Approach two

Alternatively, for any areas where you do not want to have detection occurring assign them a layer i.e. NoMouseDetectionLayer then use the raycast and if it doesn't hit one perform the code.

public class GetInputs : Monobehaviour {
     int blockInputMask;
     // Range of the raycast (value not that important)
     public int camRayRange = 200f; 

     void Start(){
         int blockInputMask = LayerMask.GetMask("NoMouseDetectionLayer");
     }

     void Update(){
         if(Input.GetMouseButtonUp()){
              Ray camRay = Camera.main.ScreenPointToRay(Input.mousePosition);

              RaycastHit floorHit;

              if (!Physics.Raycast(camRay, out floorHit, camRayRange, blockInputMask)) {
                   // If it doesn't hit an object on the layer perform the code.
              }
              else{
                   // It hit the object so don't do anything.
              }
         }
    }
}

This has the benefit that it is easy to assign new areas, all you need to do is create a new object with a collider and set its layer as NoMouseDetectionLayer which is done in the top right of the inspector.

\$\endgroup\$
7
  • \$\begingroup\$ Where do I attach this script to? \$\endgroup\$
    – user78900
    Commented Feb 25, 2016 at 11:47
  • \$\begingroup\$ Where you call Input.GetMouseButtonUp you add the code for the raycast and you change the layer of whatever object you want to stop input to "NoMouseDetectionlayer". Let me edit it so it is a bit clearer \$\endgroup\$
    – Malrig
    Commented Feb 25, 2016 at 11:57
  • \$\begingroup\$ Added some more code to make it clear how you would add the code to a script. Also noticed that this is pretty much the same answer as the one provided by Jack \$\endgroup\$
    – Malrig
    Commented Feb 25, 2016 at 12:08
  • \$\begingroup\$ I'm having difficulties with implementing your script. Can you please upload an example project? \$\endgroup\$
    – user78900
    Commented Feb 25, 2016 at 14:00
  • \$\begingroup\$ I can do so later but cannot at the moment. The earliest I can promise is this evening but I might not get it done until tomorrow. \$\endgroup\$
    – Malrig
    Commented Feb 25, 2016 at 14:04

You must log in to answer this question.