- Home /
[SOLVED] GUI.RepeatButton returns true-false-true-false..
I have following code in my OnGUI
state = GUI.RepeatButton(rect, controlContent);
and it returns not true-true-true-true, as I expected, but true-false-true-false (the problem was that I was not able to detect an exact moment a button was pressed, because when current state was TRUE then a previous state always was FALSE, but I was expected a current=true and old=true at this moment).
Ok, I found that this is an as-designed behavior, and even some explanations about why so... and now I compare current with before last state (instead of last one) to detect if user just pressed or already holds buttons for some time...
...and It seems all right, but I worry about stability of this solution... Is there any assurance that it always will return TRUE-FALSE-TRUE-FALSE when held? Is this behavior documented somewhere? Couldn't it become the "TRUE-TRUE" or "TRUE-FALSE-FALSE-TRUE-FALSE-FALSE" or something else in future Unity version?
P.S. Of cause I now about the solution where I could just change state in OnGUI and react it in Update ( http://forum.unity3d.com/threads/repeatbutton-true-false.19527/ ), but I'm trying to avoid an Update in script attached to about 500 gameobjects (my own gui system is based on gameobject hierarchy) because of overhead (I haven`t made the performance tests but I already believe the opinion that "any Reflection is overhead, especially for mobile platform", and Update, FixedUpdate and others are called via reflection afaik).
EDIT2: I removed previous "EDIT" because I wrote them with misunderstanding about a key of the answers.. sorry :)
If you're worried about the overhead of calling Update() then you shouldn't even be using GUI.*** in the first place - all GUI functions perform horribly. If you can, upgrade to 4.6 and start using UI ins$$anonymous$$d.
Actually I have just one OnGUI in parent, and children subscribes to parent's delegate.
and what about 4.6`s UI - I've thought about it but no! in my next project I definitely would, but in this it's too late and it would be too hard already...
GUI functions don't perform horribly. Having Update in 500 objects vs. a single OnGUI function isn't remotely comparable. Update is found via reflection and then cached, although it's still better not to call it if you don't have to.
Didn't know that Update and others are cached and we have reflection overhead only for first call. Thanks for this.
But imho, and as you said, its better not to have Update in 500 GO if it possible :).
Answer by Eric5h5 · Dec 23, 2014 at 11:03 PM
Check the value of state
in Update, or during the repaint event.
function OnGUI () {
state = GUI.RepeatButton(rect, controlContent);
if (Event.current.type == EventType.Repaint) {
Debug.Log ("OnGUI: " + state);
}
}
function Update () {
Debug.Log ("Update: " + state);
}
Yes, I wrote in P.S about this solution and why I prefer not to use it (because it leads to 500 Updates, and you recommended not to have 500 updates if it possible :) )
But thanks anyway :)
Do you have 500 OnGUIs? Did you read the first part of the answer, about checking Event.current.type?
Whooops! Sorry, I've lost part about repaint event. Yes, this solution returns "true-true-true"! Thanks a lot! :)
Answer by AdamScura · Dec 24, 2014 at 07:23 AM
To answer your question, no, your solution is not stable.
RepeatButton only returns true on the "Repaint" and "MouseUp" events. If the user drags the mouse while holding the button, the true-false-true-false pattern breaks.
Run this code to see what I mean:
public void OnGUI()
{
EventType eventType = Event.current.type;
bool isPressed = GUILayout.RepeatButton("Button");
Debug.Log(eventType + ": " + isPressed);
}
The output will look like:
Layout: False
MouseDown: False
Layout: False
Repaint: True
Layout: False
MouseDrag: False
Layout: False
Repaint: True
Layout: False
MouseUp: True
Like @Eric5h5 said, you need to update state on the repaint event. The correct solution is:
public bool state;
public void OnGUI()
{
bool isPressed = GUILayout.RepeatButton("Button");
if (Event.current.type == EventType.Repaint)
state = isPressed;
if (state)
OnClickActions();
else
OnHoldActions();
}
Thanks a lot, I really havent got a key of @Eric5h5's answer, but now it's clear for me.
Sorry for I cant accept 2 answers as right, but my vote is yours too :)
Answer by bubzy · Dec 23, 2014 at 11:07 PM
bool oldState;
state = GUI.RepeatButton(rect, controlContent);
if(state != oldState)
{
// do the thing
oldState = state;
}
you can try this, haven't got the time to test but the theory is there :D
it works if RepeatButton returns true-true-true when held, but it doesn't return like this (it returns true-false-true-false).
And my question was even not about "how to handle this", because as I wrote, I solved this by using state, lastState and beforeLastState. Ok, let me show how I've solved it...
public bool state = false;
protected bool lastState = false, beforelastState = false;
protected void SGTDraw(){
beforelastState= lastState;
lastState = state;
state = GUI.RepeatButton(rect, controlContent, controlStyle);
if(state && !beforelastState)
OnClickActions();
if(state)
OnHoldActions ();
}
It works, and I don't ask to help me solve this, because this is not so hard :) $$anonymous$$y question was - is this solution stable? Is this sequence (true-false-true-false) of RepeatButton documented somewhere? Will it be the same in future versions or behavior may change?
Then this is a question for the developers on the forum not for people here
question closed, because another stable solution found. Thanks for concern :)
Your answer
Follow this Question
Related Questions
GUI.RepeatButton funcionality with new Unity UI (4.6.x) 2 Answers
GUI Repeat Button problem 1 Answer
How to tell when a RepeatButton is done being Pressed 3 Answers
RepeatButton Problem 1 Answer
GUI.repeatbutton crazy? 1 Answer