设计一个显示消息、返回自定义对象并等待用户响应的对话框

问题描述 投票:-1回答:1

我正试图在unity中设计一个自定义对话框,以便在所有平台上运行(在我的例子中是Android和webplayer)。

我已经成功地显示了一个对话框,并获得了用户的响应和更新这个响应。但是我不知道当从其他方法类外部使用对话框时,如何调用display the dialog box并在它返回一个值之前等待。

这是我显示对话框的代码。

            public void ShowDialogBox(string title, string message, DialogBoxButtons buttons)
            {
                StartCoroutine(ShowDialogBoxHelper(title, message, buttons));
            }

            public void ShowDialogBox(string title, string message)
            {
                StartCoroutine(ShowDialogBoxHelper(title, message, DialogBoxButtons.OK));
            }

            public IEnumerator ShowDialogBoxHelper (string title, string message, DialogBoxButtons buttons)
            {
                Response = DialogResponse.NONE;

                Title.text = title;
                Message.text = message;

                ButtonSet = buttons;
                HandleButtonSet(ButtonSet);

                _canvasGroup.alpha = 1;
                _canvasGroup.interactable = true;
                transform.SetAsLastSibling();

                _apprearenceMode = ApprearenceMode.Shown;

                 yield return StartCoroutine(WaitForButtonResponse());

                Debug.Log("user response : " + Response);

            }

Coroutine "WaitForButtonResponse() "是这样声明的。

IEnumerator WaitForButtonResponse()
            {
                Debug.Log("waiting in the enumerator, responded: " + Response);

                yield return new waitForUserAction(() => Response != DialogResponse.NONE);

                Debug.Log("done waiting in the enumerator, responded: " + Response);

            }

而 "waitForUserAction() "这个coroutine是一个自定义的,继承自 "WaitForUserAction()"。自定义收益率指令(CustomYieldInstruction)

[System.Serializable]
    class waitForUserAction : CustomYieldInstruction
    {
        Func<bool> m_Predicate;

        public override bool keepWaiting { get { return !m_Predicate(); } }

        public waitForUserAction(Func<bool> predicate) { m_Predicate = predicate; }
    }

When ShowDialogBox is called, the choice is "NONE"

About to click on "NO"

After clicking on the choice, the dialog closes and the choice is correctly logged

当我调用ShowDialogBox方法时,对话框如期出现,当我点击其中一个选项时,响应正确更新。但是,如果我想让ShowDialogBox返回一个响应,并等待用户点击一个对话框按钮后再返回,我该如何实现呢?

希望得到的行为。

 public DialogResponse ShowDialogBox(string title, string message, DialogBoxButtons buttons)
            {
                StartCoroutine(ShowDialogBoxHelper(title, message, buttons));
                return Response;
            }

以及这样的用法。

 if (ShowDialogBox("test", "testing dialog box behaviour", DialogBoxButtons.YES_NO_CANCEL) == DialogResponse.YES)
                {
                    //do something
                }

现在的问题是,"返回Response; "没有等待 "StartCoroutine(ShowDialogBoxHelper(title, message, buttons)); "更新用户的选择,而是返回Response的旧值,而不是用户当前选择的内容。

预先感谢您在这方面的任何帮助!

干杯。

Ani

c# unity3d coroutine
1个回答
1
投票

你不需要立即评估结果,而是需要实际等待并告诉例程当有响应时要做什么。

我会使用一个 Action<DialogResponse> 为像。

// Here you can actually use an overload with optional parameter
// If you don't pass in the "buttons" it simply has the default value `OK`
// And additionally pass in the action to invoke once a response was given
// If you don't pass it then simply nothing happens ;) 
public void ShowDialogBox(string title, string message, DialogBoxButtons buttons = DialogBoxButtons.OK, Action<DialogResponse> onResponse = null)
{
    StartCoroutine(ShowDialogBoxHelper(title, message, buttons, onResponse));
}

public IEnumerator ShowDialogBoxHelper (string title, string message, DialogBoxButtons buttons, Action<DialogResponse> onResponse)
{
    Response = DialogResponse.NONE;

    Title.text = title;
    Message.text = message;

    ButtonSet = buttons;
    HandleButtonSet(ButtonSet);

    _canvasGroup.alpha = 1;
    _canvasGroup.interactable = true;
    transform.SetAsLastSibling();

    _apprearenceMode = ApprearenceMode.Shown;

    // Here rather use the Unity built-in
    yield return new WaitWhile(() => Response == DialogResponse.NONE);

    Debug.Log("user response : " + Response);

    onResponse?.Invoke(Response);
}

你可以用一个lambda表达式,如:

ShowDialogBox("test", "testing dialog box behaviour", DialogBoxButtons.YES_NO_CANCEL, response => 
    {
        if(response == DialogResponse.YES)
        {
            // Do something
        }
    });

或者用同样的方法

ShowDialogBox("test", "testing dialog box behaviour", DialogBoxButtons.YES_NO_CANCEL, HandleResponse);

private void HandleResponse(DialogResponse response)
{
    if(response == DialogResponse.YES)
    {
        // Do something
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.