I remember seeing this on the Alpha list and now I see it in a project I’m working on. I have a GUI window with a vertical ScrollBar / scroll view inside it. If I click on the scroll bar, the mouse clicks are picked both at the scroll bar and in the 3D game view. Is this a bug? Is there a work around for this?
you can put your code in an OnGUI instead of Update use Events. try to make sure the code you put there is only user input based though or else it can cause problems. some of my example:
function OnGUI ()
{
if (LevelC.userInput == false)
{
return;
}
if (Event.current.type == EventType.mouseDown)
{
if (Event.current.button == 0)
{
var ray : Ray = Camera.main.ScreenPointToRay (Input.mousePosition);
var hit : RaycastHit;
if (Physics.Raycast (ray, hit))
{
if (LevelC.waiting == true hit.transform.tag == "Block")
{
LevelC.waiting = false;
block = hit.transform;
block.BroadcastMessage ("Grab");
OrientBlock (0.2);
GrabBlock (block);
}
else if (holding)
etc...
; )
Nifty idea, but unfortunately doesn’t cover things like OnMouseDown() functions on other objects. I took the approach of having a global flag that’s set when a window is open, which I check in other scripts as necessary so the functions don’t do anything. Kinda clumsy but it works in this case I think.
–Eric
in my game i have icons (in draggable GUI windows) that are always on screen - it wasn’t my idea nicholas helped me out with it ; )
EDIT: oh so this method doesn’t kill mouse down events on other objects - i’ll have to test that (i wasn’t aware of this as my game doesn’t use them - thanks, good to know)
IMO, this is a bug in the GUI system - for now you can work around it, but I would very much like to fix this in next update, so if you don’t get OnMouseDown if the GUI takes your click.
So anybody, try not to make code that depends on this behaviour
In a project of mine, I automatically instantiated invisible GUITextures to eat up mouse events behind the Unity 2.0 GUI… you might want to try that in the mean time.
Cheers,
-Jon
I ran into this when making the Splume level editor and used a combination of two solutions to work around it. I had a number of dialogs where I wanted to suppress all input events behind them, so I used a function like below (javascript):
function isModalDialogEnabled()
return (helpDialog.enabled || editDialog.enabled || saveDialog.enabled);
I also had static GUI elements on the screen and wanted to avoid clicks creating balls behind them. For this, I just saved all of the Rects for the GUILayout Areas into an array and created a function isPointOverGUI(point:Vector3) to check if a screen point was within any of those Rects. Then when I handled mouse input it would look something like:
if(Input.GetMouseButtonDown(0) !isPointOverGUI(mouseGUI) !isModalDialogEnabled())
// handle mouse click
// for keypresses don't care if the mouse is over the GUI
if(Input.GetKeyDown("d") !isModalDialogEnabled())
// handle keypress
Note that mouseGUI here isn’t just Input.mousePosition, because this uses coordinates with 0,0 in the lower left, while the GUI has 0,0 in the upper left. Converting should be simple though.
IMO, this is a bug in the GUI system - for now you can work around it, but I would very much like to fix this in next update, so if you don’t get OnMouseDown if the GUI takes your click.
So anybody, try not to make code that depends on this behaviour
The change you suggest is a major one, and not consistent with Unity 1.x beavior either. I’m confident that if they “fix” this it will be optional.
It’s not “they” - I wrote the GUI system
Being consistent with 1.6 is irrelevant: UnityGUI is a completely new subsystem, so there really is no consistency to maintain ![]()
The main thing is that this is such a bad behaviour, that I want to get the fix out ASAP - before people begin shipping titles that depend on this. I got 5 people coming up to me at Unite saying “why do I get an OnMouseDown in my scene when I hit a button”. More people had seen this, but made some really funky workarounds. (Hi Aarku)
If somebody ships a game before we can change this, we will test. If we can’t get them to update prior to a fix, we will maintain the behaviour for things published before the fix. Either way, you should not depend on this bug being present ![]()
EDIT: Re-reading your post, it seems like you have a use case where you would want this behaviour. Care to share?
I hope / plan to have a beta version of my first commercial application with Unity in the next 30 days. Is there any chance you will be releasing a fix for this before then?
EDIT: Re-reading your post, it seems like you have a use case where you would want this behaviour. Care to share?
Thanks for asking. The answer is mostly no- In my ignorance I was imagining the GUI to be an extension of the old GUITexture. The behavior for those was to allow clicks to pass through. That was the compatibility concern; I could see someone relying on that behavior in 1.x.
As long as the behavior change is limited to the new GUI system you can probably change it at this early date, as you suggest. Having said that, if someone wanted to use the GUI system to implement a translucent heads up display, wouldn’t they want the option to have clicks travel through?
I’m not too concerned though. With a little effort either behavior can be implemented, even if the opposite behavior is what’s built-in. And I agree that the default behavior most people will want is to have the GUI keep the events that it uses. But if it’s easy to let the developer configure which behavior they want, then why not.
but made some really funky workarounds. (Hi Aarku)
Yeah… yeah
It was a case of having to have something big working in the next couple of hours, and after that I forgot to report it.
EDIT: Re-reading your post, it seems like you have a use case where you would want this behaviour. Care to share?
Personally, I would like the ability to not have GUI elements eat mouse events. I can’t give you a specific use, but in general I’d like to have partially translucent indicator widgets (think translucent viewfinder) and still be able to easily click on the stuff behind it. I think something as simple as a GUI.eatUpMouseEvents bool (named better) defaulting to true would work. Something in the same style as GUI.enabled.
-Jon
Hey Nicholas,
Could you perhaps share what you would currently consider a good workaround for this problem?
I’ve read about making an old style GUITexture behind the gui, and about checking based on rects if you’re lucky enough your gui stays at the same rects most of the time.
Do you see any other (better?) workarounds than these?
Thanks, Lucas
@Lucas: I’m not sure exactly what you are asking about? If it’s letting clicks go through the GUI, then a button press will never travel through to the background (you can naturally cast a ray against the scene and use SendMessage on whatever you hit)
Could you elaborate on what you want to do?
I have a chatbox in which you can enter text.
in order to give it focus, I click on it.
but that click also gets registered by a monobehaviour that interpets it as a command to “walk here”.
I’m looking for the “official” (ahem
), way to make clicks on my gui elments go only to my gui, and clicks on my scene only go to my monobehaviours.
I’m currently using GetMouseButtonDown() in my monobehaviour.
Maybe I’m just adding to an ancient thread whose issue has already been fixed without me having realized it :).
Bye, Lucas
If you check for GetMouseButtonDown inside an Update function, that will tell you that the mouse button was pressed - no matter whether there’s GUI that’s also using the click.
UnityGUI will block OnMouseDown events sent to objects, but to do the other thing, the easiest way is to do it inside the GUI code. Try something like:
void OnGUI () {
/// Other GUI code here
/// you will only get mousedown events here if none of the other GUI has
/// used the mousedown
if (Event.current.type == EventType.MouseDown) {
Vector2 pos = Event.current.mousePosition;
// flip coordinates for camera.
pos.y = Screen.height - pos.y;
RaycastHit r;
if (Physics.Raycast (Camera.main.ScreenPointToRay (pos), out r)) {
Debug.Log ("hit " + r.collider.name);
}
}
}
Just typed into Safari, but you get the idea ![]()
Thanks Nicholas. Excuse my ignorance, I was unaware of OnMouseDown.
Great,
Lucas
Here’s one of the silliest workarounds I’ve done so far:
Make a plane and place it right in front of your main camera where your gui element is. Turn off the mesh renderer and there ya go. The raycast will hit the plane, you won’t see it cause it’s invisible.
The only problem with this is that the size of my gui elements changes with different screen proportions, and the plane doesn’t change in the same way.
Note that the plane needs to be right on top of the camera so that none of your scene elements gets in front of it (and then becomes clickable)
Any improvements with the problem of proportions will lick this sucker.
@Vimalakirti I’m using your workaround right now. My gui stays the same size which is convenient, but my problem is that if you move around with the gui open, the planes catch on other game objects that I walk right next to stop my character from moving. I know there’s a layer to ignore raycast but still be a collider, but is there a reverse of that, ie not be a collider but still block raycast.
Ok I just answered my own question. Make it “Is Trigger”.
The only problem with this is that the size of my gui elements changes with different screen proportions, and the plane doesn’t change in the same way.
Did you ever work out a way of scaling the plane to match the GUI when you change the screen resolution?