0
\$\begingroup\$

I was wondering how if(GUILayout.Button(..)) actually works internally.

It is a weird construction, since it returns "true" when the user presses the button, but on the other hand, it also creates a button and then just jumps to the next block of code, so this statement doesn't actually block execution. Then again, it's not of a known asynchronous model. How is this wired internally?

\$\endgroup\$
1
  • \$\begingroup\$ The answer troien seems correct. If you look through the code in the Unity CS Reference github you will see that Unity internally creates an state machine for checking to see what was done during the last OnGUI call. That is why the button is able to execute on the first frame it is pressed rather than every frame until it is released. \$\endgroup\$ Commented Oct 14, 2020 at 5:43

1 Answer 1

1
\$\begingroup\$

Well, it actually does block execution. It is just called every frame (Or more then once actually), and when you press the button in one frame, it will return true that frame, all other frames it will return false.

For instance, this peace of code will completely fill up your console in no-time:

private void OnGUI()
{
    Debug.Log($"Frame: {Time.frameCount}, current onGUI type: {Event.current.type}");
}

This is because it is executed once with the 'layout' event, and once with the 'repaint' event every frame. Then other events like 'mousedown' and 'mouseup' also invoke OnGUI an additional time in the frames that these events occur.

Now how it is actually implemented, you'd have to check unity's reference on github. This is the part of interest, although it gets pretty complicated the deeper you go ;)

But to get an idea of how it somewhat works. Sinse it is called every frame, it can check Input.GetMouseButtonDown every frame just like you can, it can also check if the mouse position is inside the buttons rect (which you either provide in GUI.Button() or let unity create in the layout pass of OnGUI when you use GuiLayout.Button()). It then uses GUIUtility.hotControl to handle whether a button is clicked (both mousedown and mouseup event happened on the same button)

As you also might see in the implementation btw. GUILayout.Button always returns false in the layout and repaint passes, it will only return true in the mouseup pass. Which makes sense, because the code you place inside that if should only be executed once when you press it, not once for every event that frame (layout, repaint, mouseup).

On a sidenote, this (And everything that uses the OnGUI callback) is what Unity calls IMGUI, which is currently not recommended by unity to use for runtime game UI. See the documentation so see in which sutuations IMGUI is recommended.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks, I didn’t know we could browse this. Your answer demystified a ton. And yes it makes sense this api only suits devmode things. \$\endgroup\$ Commented Oct 14, 2020 at 21:20

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.