- Home /
The question is answered, right answer was accepted
How can I prevent my raycast from passing through UI?
Hello Unity Community!
I have this piece of code here:
private void CheckTap(){
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began){
//if(EventSystem.current.IsPointerOverGameObject()){
RaycastHit h;
Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
if(Physics.Raycast(ray,out h,15.0f,lmask)){
if(h.transform.gameObject.tag=="Square") {
h.transform.gameObject.GetComponent<script_SquareHub>().OnHit();
}
else if(h.transform.gameObject.tag=="Bumper"){
bumperHit.Play();
switch(livesRemaining){
case 3: l3.GetComponent<Image>().color=new Color32(205,191,172,150);
livesRemaining=2;
break;
case 2: l2.GetComponent<Image>().color=new Color32(205,191,172,150);
livesRemaining=1;
break;
case 1: l1.GetComponent<Image>().color=new Color32(205,191,172,150);
livesRemaining=0;
break;
case 0: _timeRemaining=0.0f;
break;
}
}
}
//}
}
}
It works fine on detecting various objects using touch. However, the ray goes through UI, so when I try to pause my game the ray will hit my "Bumper" and cause the player to lose a life.
How can I prevent my ray from passing through the UI? As you can see I've tried using IsPointerOverGameObject, but to no success, and setting the layer mask lmask
to include UI doesn't yield the results that I want. Any solution to this?
doesn't yield the results that I want
explain?
Layermask should be the perfect solution.
Could you detail here, how you set up your layermask?
Well, my layermask (`lmask` in the code) is a public layermask, that I set in the editor to contain only the UI, Square, and Bumper layers. Here's how it looks in the editor:
Canvas has UI set as its layer by default, and I manually set up the Bumper and Squares layers. $$anonymous$$y ray interacts with those, but ignores UI.
Answer by fafase · Oct 09, 2015 at 07:58 PM
You had it going well but were missing one extra info.
private int fingerID = -1;
private void Awake()
{
#if !UNITY_EDITOR
fingerID = 0;
#endif
}
private void Update()
{
if (EventSystem.current.IsPointerOverGameObject(fingerID)) // is the touch on the GUI
{
// GUI Action
return;
}
// Your raycast code
}
The problem is in editor the parameter for the IsPointerOverGameObject needs to be -1.
Thanks for your answer. But what does EventSystem.current.IsPointerOverGameObject() actually show me? I'm just interested in running my raycast code when I'm not over UI, since I handle the UI functionality from somewhere else. Also, it only needs to only work in the build, I'm not going to be using the editor anymore since this is the final issue that I have to solve before publishing my project.
EventSystem is the class taking care of all the interfaces concerning the UI (pointer dragged, enter, exit and so on). The method returns true if your pointer is over the UI. As a result, the raycast is not happening since there is a return in the if-statement. If the pointer is not over a UI element, then it is false and the raycast is performed. Since you are dealing with UI elsewhere, nothing else but the return happens.
You can also turn it the other way:
if (EventSystem.current.IsPointerOverGameObject(fingerID) == false){
// Raycast
}
The parameter is different in Editor and mobile (dunno about standalone). So for the same system to work on mobile, it requires the 0 parameter.
Yes, this works perfectly! Thank you! You, Bored$$anonymous$$ormon and AngryBurritoCoder helped me a lot with my first project, and now it's complete. You guys rock!
@fafase, as a side note: am I the only one that thinks this method is horribly named compared to what it does? You'd think IsPointerOver*GameObject*(fingerID) == true means that the pointer IS over an object so you should raycast without worry, when ins$$anonymous$$d, it's just the opposite. At least that's what the name suggests.
I guess it is meant to be over a relevant game object, a UI game object in that case. But yes, it could be confusing. When you build something as big as Unity, comes the times when you run out of appropriate na$$anonymous$$g.
This didn't work for me. $$anonymous$$y agent only moves toward UI elements and can't see touches on the map. What am I doing wrong?
public class $$anonymous$$ovement : $$anonymous$$onoBehaviour { public GameObject RallyPoint; private int fingerId = -1;
private void Awake()
{
if !UNITY_EDITOR
fingerID = 0;
endif
}
void Update()
{
if (Input.touchCount > 0)
{
RaycastHit hit;
Touch touch = Input.GetTouch(0);
Vector3 touchPosition = touch.position;
Ray ray = Camera.main.ScreenPointToRay(touchPosition);
if (Physics.Raycast(ray, out hit, $$anonymous$$athf.Infinity))
{
if (EventSystem.current.IsPointerOverGameObject(fingerId))
{
Vector3 newPosition = new Vector3(hit.point.x, hit.point.y, hit.point.z);
RallyPoint.transform.position = newPosition;
}
}
}
}
}
Answer by meat5000 · Oct 09, 2015 at 02:19 PM
Physics raycast doesnt work on new UI I do believe.
You need a Graphic Raycaster
How could I use it? The Canvas has a graphics raycaster by default. How should I modify my current code to accommodate this change?
Looking at the Scripting API, it appears you need to pass it some Pointer Event Data.
http://docs.unity3d.com/ScriptReference/UI.GraphicRaycaster.Raycast.html
Perform a base raycast but ins$$anonymous$$d of Physics.Raycast, use GraphicRaycaster.Raycast
But if I use this method won't the graphic raycaster ignore my objects?
Works for me with this adaption: public static bool IsPointerOverGameObject() { //check mouse if (Input.touchCount == 0 && EventSystem.current.IsPointerOverGameObject()) { return true;
}
// Check touches
for (int i = 0; i < Input.touchCount; i++)
{
var touch = Input.GetTouch(i);
if (touch.phase == TouchPhase.Began)
{
if (EventSystem.current.IsPointerOverGameObject(touch.fingerId))
{
Debug.Log(touch.position);
return true;
}
}
}
return false;
}
Answer by Kiwasi · Oct 09, 2015 at 09:49 PM
This may also help
Yeah, I saw your video before I posted this question. I was using method 1, the quick and dirty one, but I was using it incorrectly. But thank you for your help. You, fafase and AngryBurritoCoder all helped me a lot with my first project!
Follow this Question
Related Questions
if ( Physics.Raycast ( ray, out hit, Mathf.Infinity, LayerMask ) ) not working? 2 Answers
How to get PointerEventDatas[]? 0 Answers
raycasting and layermask question 2 Answers
Holding down UI Button and shooting raycast from touch position doesn't work simultaneously:(( 0 Answers
How to touch select 3D objects 2 Answers