我正试图在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; }
}
当我调用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
你不需要立即评估结果,而是需要实际等待并告诉例程当有响应时要做什么。
我会使用一个 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
}
}