Home > Net >  Unity - Make a Sync Method that waits for user input
Unity - Make a Sync Method that waits for user input

Time:01-03

I have basic knowledge of C# with WinForms and WPF. But I am new to Unity. I want to make a series of Message Boxes those appear one after another(once user close current than next box will show). It is very easy to use MessageBox.Show("Hello World"); in WinForms.

void myFun(){
    MessageBox.Show("Hello World1");//First Box
    //Some Code
    MessageBox.Show("Hello World2");//Another

    MessageBox.Show("Hello World3");//Finally Results
}

In WinForms(or WPF) Code after MessageBox.Show(); will not Executed before we Give input to close.

I want to make same MessageBox in unity with GameObject where code will not execute before GameObject is SetActive(False); by user command(mouse Click on Background or Yes/No Buttons).

Thanks in Advance

sorry for bad English

CodePudding user response:

To make each line run after the previous one finishes, you can use the 'Action' keyword.

https://learn.microsoft.com/en-us/dotnet/api/system.action-1?view=net-7.0


private void MessageBox(string mesagge, Action<bool> onPopUpClosed = null)
{
  // Your code here

  //Once you close popup
  onPopUpClosed?.Invoke()
}

MessageBox.Show("Hello World1", () =>
{
    MessageBox.Show("Hello World2", () =>
    {
        MessageBox.Show("Hello World3");
    });
});

CodePudding user response:

One of the best approaches becoming popular in Unity the last years is an Async approach. So I highly recommend you to learn this to have even more powerful tool than Coroutines and to avoid Callback Hell in case of Action usage.

Let's implement it this Async approach together.

Firstly, we need that MessageBox implementation. Let's say it has 2 buttons: Confirmation and Cancellation. Here's it:

public MessageBox : MonoBehaviour
{
    [SerializeField]
    private Button _confirmationButton;
    [SerializeField]
    private Button _cancelButton;
    
    private TaskCompletionSource<bool> _tcs = new TaskCompletionSource<bool>();

    public void OnConfirmationButtonClick()
    {
        // we're passing `true` if user clicks `Confirm`
        _tcs.SetResult(true);
    }
    
    public void OnCancellationButtonClick()
    {
        // we're passing `false` if user clicks `Cancel`
        _tcs.SetResult(false);
    }

    public async Task<bool> ShowAsync()
    {
        gameObject.SetActive(true);
        
        _tcs = new TaskCompletionSource<bool>();
        
        // the execution stops here ASYNCHRONOUSLY, so the UI thread is not blocked.
        // It just awaits until we set any result to `_tcs`
        await _tcs.Task;

        gameObject.SetActive(false);
    }
}

And now we can show a few message boxes and await for their input. Moreover, we may know what exactly button was clicked: Confirmation or Cancellation:

public async Task YourOwnMethodAsync()
{
    // Let's assume you've instantiated 3 message boxes already and have their references

    var resultOfFirstMessageBox = await _messageBox1.ShowAsync();
    Debug.Log($"Showing the first message box shown. Result: {resultOfFirstMessageBox}");
    
    var resultOfSecondMessageBox = await _messageBox2.ShowAsync();
    Debug.Log($"Showing the second message box shown. Result: {resultOfSecondMessageBox}");

    var resultOfThirdMessageBox = await _messageBox3.ShowAsync();
    Debug.Log($"Showing the third message box shown. Result: {resultOfThirdMessageBox}");
}

If you need even more detailed description, just let me know.

  • Related