# Unity, WaitUntil in a self-made message box class

I managed to make a simple message box prefab with a Text and a Button through Canvas, and then instantiate it through the constructor.

public class MessageBox
{
public MessageBox(string msg)
{

obj.GetComponentInChildren<Text>().text = msg;
}
}


So when another script needed it, simply do

MessageBox mb = new MessageBox("This is a test message!");


This all worked fine, but then I wish to change it to like normal MessageBox where the code was suspended, but not locked, until the user click the OK or Cancel button.

I managed to do it by calling a coroutine in the calling script.

void Start()
{
StartCoroutine("Do");
}

IEnumerator Do()
{
MessageBox mb = new MessageBox("This is also a test message!");

yield return new WaitUntil(() => GlobalVariables.MsgBoxClicked == true);
//GlobalVariables is a separate class containing some static variables.
Debug.Log("Done!");
}


(You have to set the MsgBoxClicked to false when the prefab is created and set it to true when the button is clicked, of course.)

But that means every time I needed to use the message box, I need to call a coroutine!

And that's super inefficient no matter how you looked at it!

So I tried to move the coroutine into the MessageBox class itself.

But now here comes the problem!

The MessageBox does NOT inherit from MonoBehaviour!

And you can't call a coroutine without it!

I had tried to make the MessageBox inherited from MonoBehaviour, but the Unity warned me This is not allowed every time I tried to new it! Even though the game ran smoothly.

I even tried to new the MonoBehaviour itself and call its StartCouroutine, but of course, the same warning popped up! And this time the game won't even run!

I also tried to use the old AutoResetEvent, but it locked the whole thing and crashed my game!

So, could somebody be so kind and teach me how to get around it!?

Much appreciated!

Unity doesn’t really support modal dialogs in the way you want, but there are some workaround, like setting the time scale to zero while it’s displayed, and adding a click-blocking later between the message box and everything underneath it.

There are also better ways to wait for the message box to be dismissed than a coroutine, such as a UnityEvent.

That said, if you just want to move your coroutine into the MessageBox class, it should be pretty simple: (warning: untested)

public class MessageBox : MonoBehaviour
{
private System.Action onDismiss;
public static void ShowMessage(string msg, System.Action onDismiss)
{

obj.GetComponentInChildren<Text>().text = msg;
MessageBox msg = obj.AddComponent<MessageBox>(); //or this component could be added to the prefab in the inspector.
msg.onDismiss = onDismiss;
}

void Start()
{
StartCoroutine("Do");
}

IEnumerator Do()
{
yield return new WaitUntil(() => GlobalVariables.MsgBoxClicked);
//GlobalVariables is a separate class containing some static variables.
if (onDismiss != null)
onDismiss();
}
}


And then the code that wants to show the message can simply use

MessageBox.ShowMessage("This is a test message!", () => {
Debug.Log("Done!");
});


Basically, MonoBehaviour objects can’t exist on their own. They are components that must be attached to a GameObject, which is what the call to AddComponent is doing.

• msg.onComplete = onDismiss; won't work! There is NO onComplete! Could you please be so kind and fix it!? Much appreciated! – PiggyChu001 Oct 9 at 14:23
• Whoops. I accidentally used onDismiss in one place and onComplete in another. Try onDismiss in all places. – Ed Marty Oct 9 at 19:04