Unity3d Unity,在自制的消息框类中等待

Unity3d Unity,在自制的消息框类中等待,unity3d,Unity3d,我设法通过Canvas,用文本和按钮预制了一个简单的消息框,然后通过构造函数实例化它 public class MessageBox { public MessageBox(string msg) { GameObject obj = (GameObject)MonoBehaviour.Instantiate(Resources.Load(@"MsgBox")); obj.GetComponentInChildren<Text>().

我设法通过
Canvas
,用
文本和
按钮预制了一个简单的消息框,然后通过构造函数实例化它

public class MessageBox
{
    public MessageBox(string msg)
    {
        GameObject obj = (GameObject)MonoBehaviour.Instantiate(Resources.Load(@"MsgBox"));

        obj.GetComponentInChildren<Text>().text = msg;
    }
}
这一切都很好,但我希望将其更改为与普通MessageBox类似的状态,在用户单击“确定”或“取消”按钮之前,代码被挂起,但未被锁定

我通过在调用脚本中调用一个coroutine
实现了这一点

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!");
}
(创建预制件时,必须将
MsgBoxClicked
设置为
false
,当然,单击按钮时必须将其设置为
true
。)

但这意味着每次我需要使用消息框时,我都需要调用一个协同程序

不管你怎么看,这都是超低效的

因此,我尝试将协同程序移动到
MessageBox
类本身中

但现在问题来了

MessageBox
不是从
monobhavior
继承的

没有它,你就不能称之为合作伙伴

我曾试图将
消息框
继承自
monobhavior
,但Unity警告我
这是不允许的
,每次我尝试新建它时!尽管比赛进行得很顺利

我甚至尝试了新的
monobhavior
本身,并调用它的
StartCouroutine
,但当然,同样的警告出现了!而这一次,游戏甚至不会运行

我还试图使用旧的
自动重置事件
,但它锁定了整个事件并使我的游戏崩溃

那么,有人能这么好,教我如何避开它吗


非常感谢

如评论中所述,只需将其设置为事件驱动

我甚至会更进一步,你可以直接告诉
MessageBox
当“完成”时该做什么

public enum MessageBoxResponse
{
确认,
拒绝,
取消
}
公共类消息框
{
//你可以给动作任何你喜欢的参数,例如。
已采取的公共行动;
//如果您仍然希望在例程中使用它,则需要附加标志
公共bool IsDone{get;private set;}
公共消息框(字符串消息,操作onDone)
{
IsDone=false;
var obj=(GameObject)monobhavior.Instantiate(Resources.Load(@“MsgBox”);
obj.getComponentChildren(true).text=msg;
//现在,这将简单地告诉按钮调用SetDone
//(由于这是在运行时添加的,因此不会出现在检查器中)
obj.getComponentChildren(true).onClick.AddListener(确认);
完成+=onDone;
}
私人无效确认()
{
设置完成(MessageBoxResponse.confirm);
}
私有void SetDone(MessageBoxResponse响应)
{
如果(IsDone)返回;
IsDone=true;
完成?调用(响应);
}
}
然后,在创建长方体时,可以直接将回调作为lambda表达式传入

var msgBox=newmessagebox(“示例”,响应=>
{
Log(“使用响应完成”+响应);
}
);
或与方法调用相同

var msgBox=newmessagebox(“示例”,OnMessageDone);
私有void OnMessageDone(MessageBoxResponse响应)
{
Log(“使用响应完成”+响应);
}
您还可以在以后使用添加回调

msgBox.done+=OnMessageDone;
//还是兰姆达
msgBox.done+=response=>{Debug.Log(“使用response完成”+response);};
单击按钮时,
消息框
本身将自动调用
SetDone
并调用所有侦听器,而无需任何例程等待它

如果您仍然想使用它来暂停例程,您可以使用

yield返回新的WaitUntil(()=>msgBox.IsDone);
但这意味着每次我需要使用消息框时,我都需要调用一个协同程序

我不认为这是个问题。正如引用的那样。那么,对于您的应用程序来说,计算成本真的那么高吗

但是,有许多方法可以从另一个类调用协同路由方法。基本上,这一切都归结为有一个上下文引用,即对任何
monobhavior
实例的引用

public static void InvokeCoroutine(MonoBehaviour context, IEnumerator coroutine)
{
    context.StartCoroutine(coroutine);
}

为什么不举办“onclicked”活动,从there@BugFinder你能再详细一点吗!?我们创建一个事件,这样“onclicked”就可以被订阅该事件的任何人响应event@BugFinder好吧,让我仔细考虑一下。谢谢我测试了你的代码,效果很好!谢谢但是代码没有“挂起”(或者有没有其他合适的方式来表示!)。也就是说,
新消息框(…)
后面的代码没有等到我点击按钮!你能这么好心,教我怎么做吗!?非常感谢!不会的,因为它不再使用协同程序。。正如所说,事件驱动。我需要一些代码等待消息关闭,然后将其移动到
onDone
回调中。谢谢!我明白你的意思。但我的想法是,让它像VS中的MessageBox一样,你可以把它放在if语句中,然后检查哪个按钮被点击了。背后的任何事情都必须等待!你能帮我指一下正确的方向吗!?非常感谢!我把答案扩大了一点。基本上,您可以向
操作
回调传递您喜欢的任何参数。侦听器方法只需实现相应的签名。当然,您必须相应地为每个按钮设置侦听器。在这里,我建议您使用合适的类,如
confirButton
CancelButton
等,这样您就可以简单地找到using
GetComponentChildren
谢谢!让我去测试一下!
public static void InvokeCoroutine(MonoBehaviour context, IEnumerator coroutine)
{
    context.StartCoroutine(coroutine);
}