思考
在做游戏开发时常常会遇到这样一个业务模型,需要弹出一个简单的 模态窗体,提供若干选项(一般就是两个:是与否/确认与取消),并且只有玩家做出选择后才会继续其它流程,如结束游戏的二次确认(离开or留下),敏感操作的二次确认(确定or再考虑)。这种业务对应的一般是一个窗体模板,我之前的做法是某个业务在创建窗体的同时向该窗体的按钮控件传递响应的回调函数以达到响应玩家选择的效果,这是大概一种比较传统的做法,其实通常来讲回调优于轮询
, 因为轮询的性能影响和面向状态编程的不可靠性,但是此处却可以尝试换一种思路,将轮询过程隐匿在一个异步等待的流程中。这样就可以将async/await流程整合到玩家的一次选择应答流程中,尽管有上述缺陷,但不失为降耦合的一种思路。
代码
代码只大概贴了下关键部分仅供参考思路
public class TipForm : Form {
/// <summary>主要选择按钮</summary>
public Button primaryButton;
/// <summary>次要选择按钮</summary>
public Button secondaryButton;
/// <summary>玩家本次应答的选择</summary>
private volatile bool replyResult = false;
/// <summary>是否已应答</summary>
private volatile bool isReplied = false;
/// <summary>
/// 在初始化过程中绑定按钮和应答的对应关系(同时绑定销毁)
/// </summary>
public override void Init() {
base.Init();
primaryButton.onClick.AddListener(() => {
isReplied = true;
replyResult = true;
base.Close();
});
secondaryButton.onClick.AddListener(() => {
isReplied = true;
replyResult = false;
base.Close();
});
}
/// <summary>异步获取玩家应答(实际是开一个线程轮询结果) </summary>
public async Task<bool> GetReplyAsync() {
return await Task.Run<bool>(() => {
while (true) {
if (isReplied)
return replyResult;
}
});
}
}
此时假设一个购买场景,实现一个点击回调
/// <summary>点击购买按钮</summary>
public async void OnClickPurchase() {
//创建二次确认的窗体以询问是否确认购买操作
TipForm tipForm = UIManager.CreateForm<TipForm>();
//异步等待玩家的响应
bool replyResult = await tipForm.GetReplyAsync();
if (replyResult) {
//确认购买操作
}
else {
//取消购买操作
}
}
如有错误欢迎指正交流!