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
等,这样您就可以简单地找到usingGetComponentChildren
谢谢!让我去测试一下!
public static void InvokeCoroutine(MonoBehaviour context, IEnumerator coroutine)
{
context.StartCoroutine(coroutine);
}