- Home /
How to avoid multiple mouse clicks registering in OnGUI?
I have a character portrait with GUI.Box that when clicked hides the portrait and disables the box, and then shows the character's inventory with a new GUI.Box in the same space as before that when clicked does the opposite (hide inventory, disable box, show portrait again).
Now, since OnGUI plays multiple times per frame, it registers my mouseclick twice and thus if I click on the portrait it enters inventory mode for a fraction of a second (actually too fast to even see) and then immediately hides it again because the new box in the inventory mode also gets activated by the same mouseclick, which is kinda annoying.
Is there any way to avoid this issue?
Edit: I cleaned up the code somewhat. It should have been mouse 1 both times, so it indeed registers twice for some reason even though the new box isn't there at the time the old one is clicked.
var Portrait : Texture2D;
function OnGUI()
{
if(ShowInventory == false && HidePortrait == false)
{
GUI.DrawTexture (Rect (100, 100, Portrait.width, Portrait.height), Portrait);
var CharacterPortrait = new Rect(100, 100, Portrait.width, Portrait.height);
GUI.Box(CharacterPortrait,"Portrait");
if (CharacterPortrait.Contains(Event.current.mousePosition))
{
if(Event.current.type == EventType.MouseDown && Event.current.button == 1)
{
ShowInventory = true;
HidePortrait = false;
}
}
}
if(ShowInventory == true)
{
GUI.DrawTexture (Rect 100, 100, Portrait.width, Portrait.height), Portrait);
var CharacterPortraitInv = new Rect(100, 100, Portrait.width, Portrait.height);
GUI.Box(CharacterPortraitInv,"Portrait");
if (CharacterPortraitInv.Contains(Event.current.mousePosition))
{
if(Event.current.type == EventType.MouseDown && Event.current.button == 1)
{
ShowInventory = false;
HidePortrait = false;
}
}
}
}
I can see a few problems here.
1: Define variable outside of functions (top of script)
2: You had the same texture assigned for portrait and inventory (both were portrait)
3: Declare your non dynamic Rectangles in awake or start
4: You had if() statements inside of other if() statements that didn't belong.
The biggest issue here for me is, you didn't post your full script. If this IS your full script, that is also a problem ;)
All you need in OnGUI() is the GUI code itself.
Try this:
#pragma strict
var CharacterPortrait : Rect;
var CharacterPortraitInv : Rect;
var Portrait : Texture2D;
var Inventory : Texture2D;
var PortraitWidth : int;
var PortraitHeight : int;
var ShowInventory : boolean = false;
var HidePortrait : boolean = false;
var $$anonymous$$ousePosition : Vector2;
function Awake()
{
CharacterPortrait = new Rect(100, 100, PortraitWidth, PortraitHeight);
CharacterPortraitInv = new Rect(100, 100, PortraitWidth, PortraitHeight);
}
function Update()
{
$$anonymous$$ousePosition = new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y);
if(!ShowInventory && !HidePortrait)
{
if(CharacterPortrait.Contains($$anonymous$$ousePosition))
{
if(Input.Get$$anonymous$$ouseButtonDown(0))
{
ShowInventory = true;
HidePortrait = false;
}
}
}
if(ShowInventory)
{
if (CharacterPortraitInv.Contains($$anonymous$$ousePosition))
{
if(Input.Get$$anonymous$$ouseButtonDown(1))
{
ShowInventory = false;
HidePortrait = false;
}
}
}
}
function OnGUI()
{
if(!ShowInventory && !HidePortrait)
{
GUI.DrawTexture (CharacterPortrait, Portrait);
GUI.Box(CharacterPortrait,"Portrait");
}
if(ShowInventory)
{
GUI.DrawTexture (CharacterPortraitInv, Inventory);
GUI.Box(CharacterPortraitInv,"Inventory");
}
}
Yes, This is not the full script, of course it's all in OnGUI(). I just added it to show what I mean in my description. Apparently the game has problems if a mouseclick in a box changes a value that makes the box disappear, but then makes another one appear that would change the same value on another mouseclick, because the first mouseclick registers twice.
Edit:
So now I tested your suggestion and put in the mouse click checks into the Update() function, but the same exact same problem still persists :((
$$anonymous$$ust be something else in your code. Post the full code in order for me to be able to test in Unity, reproduce the problem, troubleshoot, and resolve. The code I posted works flawlessly on my end, so there is something else obviously underlying.
I think the issue is different than you believe. While OnGUI gets called multiple times per frame, you only get one call of type 'EventType.$$anonymous$$ouseDown'. Right now I don't see how your behavior is happening because line 9 and line 22 process different buttons (left vs right mouse buttons). But if as some point they were the same mouse mouse button, your code would have processed the same mouse click twice. With the poor indentation and incomplete code, I cannot tell for sure, but putting on 'else' on line 14 might solve the problem.
Thanks, I edited the code in question. The script indeed processes the same mouse click twice for some reason, no matter what I do :(
As usual @whydoidoit has a great suggestion for solving your problem. But you are still processing the same mouse click twice. So 'ShowInventory' is false on line 5 and drops down to line 14 which sets 'ShowInventory' to true. Now with it true, you hit line 20 which drop you down to line 27 and you check the event a second time. Try putting a 'return' just below line 15.
Hey, adding return behind every mouseclick event solved the problem, thanks!
Answer by whydoidoit · Aug 20, 2013 at 01:40 PM
Use Event.current.Use to use the event after you have consumed it - then nothing else will be able to see it. Clearly this means that the order in which you structure you OnGUI function will dictate the order in which events are detected which is kind of backwards because they draw in the opposite order - this can mean adding a detection phase separate to the drawing phase in some circumstances.
Thanks a lot, your suggestion worked. I put Event.current.Use(); at the end of the if query that checks if a mouse button event has happened.
Example:
if(Event.current.type == EventType.$$anonymous$$ouseDown && Event.current.button == 1)
{
ShowInventory = false;
HidePortrait = false;
Event.current.Use();
}
A "return;" ins$$anonymous$$d of "Event.current.Use();" also seems to work.
Thanks again, Thanks as well for your Unity Serializer which I downloaded although I haven't tried it yet.
Return can work - but "other" things can get to use the event in other OnGUI methods or components...
Your answer
Follow this Question
Related Questions
How to I get an object to disappear when I use the mouse to click on it? 1 Answer
instantiate object at mouse position clicked 1 Answer
Trackpad and Mouse can't fix scroll speed! 1 Answer
OnGUI() and key pressing problems. 2 Answers
Different action if a key is pressed when the mouse is clicked 2 Answers