0
\$\begingroup\$

I am working in unity and I have a group of buttons that I activate/deactivate at various times in the game. However, I have noticed that when I call button.SetActive(true) the button doesn't appear in the scene right away. In one particular circumstance, I need the button the appear before the next line of code is run. Is there a way to force the button/scene to update immediately?

Edit: To give some context, I am working on a card game similar to Magic the Gathering where there are different types of mana and there are some cards with a neutral cost. When a player plays one of these cards I activate 5 buttons (one for each mana type), and I want the player to click a button to spend one mana of that color, and to repeat that process until the neutral cost is met.

When I try to use a while loop or a coroutine to essentially pause execution until a user clicks a button (or multiple, depending on the card's cost), I cause an infinite loop because even though I set the buttons to active before the loop/coroutine, they don't actually activate by the time the loop starts.

\$\endgroup\$
  • 1
    \$\begingroup\$ Can you explain why you need the scene to visually change between lines of code? That is generally not supported in Unity's model. The scene updates its rendering according to docs.unity3d.com/Manual/ExecutionOrder.html, in the "Scene Rendering" block. You'll notice that block comes after the "Game logic" block, where your code is likely executing. \$\endgroup\$ – Chris Mills-Price Feb 25 at 8:50
  • \$\begingroup\$ I believe you can't do that in unity but you could use Coroutin which will enable the button and wait for the next frame then execute the rest of the code. As @Chris Mills-Price Logic block executes first then the Rendering scene comes in. \$\endgroup\$ – Swati Feb 25 at 9:30
  • 1
    \$\begingroup\$ Why do you need the button to appear in between 2 lines of code? That information is required in order to answer this question properly... My guess is that you want its position(layout) to be set, rather then actually somehow rendering it between 2 lines of code. If so, LayoutRebuilder.ForceRebuildLayoutImmediate should work for that purpose I think. \$\endgroup\$ – troien Feb 25 at 10:51
  • \$\begingroup\$ @troien I've edited the original post to provide some context. This is my first time trying to use coroutines, so it is very possible I'm misunderstanding how they work/how to use them. \$\endgroup\$ – Alakazooom Feb 25 at 18:27
  • \$\begingroup\$ This sounds like a bug in how you've written your coroutine. Please post your code so we can help you fix this issue. \$\endgroup\$ – DMGregory Feb 25 at 18:51
2
\$\begingroup\$

I try to use a while loop or a coroutine to essentially pause execution until a user clicks a button

This approach won't work. If you pause the execution of your game, you also pause the renderer, UI system and everything else the engine does. Even if you could force the engine to immediately render the button (it will only want to do that for the next frame), the player couldn't click on the button because the event system won't have an opportunity to process the click until your update has finished.

What you should do instead is use the concept of different game states.

  • During the "select a card" state, the player can click on any card in their hand attempting to play it. All other controls are inactive or disabled. When the player selected a card to play, the game switches to the "spend mana" state.
  • During the "spend mana" state, the 5 mana buttons activate for the player to click them. When the player spent enough mana, the game switches to the "execute card" state. You might also want to add some way to cancel the process and return to the "select a card" state without paying mana. All other controls are inactive or disabled.
  • During the "execute card" state, you play the animation to play the card and the resolution of its effects. All controls are disabled. When the card has finished, you return to the "select a card" state.

A good way to implement this in Unity is to put everything you need to be active for each state into a separate game object. This includes game mechanics scripts, spatial game objects and a separate UI canvas for any UI controls you want to be visible during that state. When you switch from one state to another, set all state game objects to inactive and set the object for that specific state to active.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Throwing it here because the specific term doesn't show up, but is relevant/google-able: "state machine" \$\endgroup\$ – Mars Feb 26 at 2:29
  • \$\begingroup\$ Great idea. This extremely helpful, I will try to implement this tonight! \$\endgroup\$ – Alakazooom Feb 26 at 17:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.