这几天折腾一个和米仔一起玩的桌游,是丢骰子走路的游戏。
虽然是用Unity开发,但是里面遇到一些问题处理不是很方便。
例如丢骰子,行走到一个格子上触发事件,播放动画后执行逻辑。这些东西并不复杂,但是逻辑都是异步的,用delegate回调写起来总觉得绕圈,容易出错。
一直在想有没有办法用协程来实现这个功能,我希望的主逻辑函数能这么写:
void Function()
{
丢骰子
走几步
如果有出发事件,处理事件
播放相机切换动画,换下一个角色
}
正常的阻塞式函数是没法这么写的,因为会被动画等操作卡住。但是用协程处理起来就方便多了。
Unity只支持它特定的几个函数,没法写做到丢完骰子后走几步,因为丢骰子是有物理动画的。
几年前问过Unity中国的程序,如何定制协程函数,给的答案是要改源代码。
在网上搜了搜,没想到Unity从5.3版本加入了一个新的类CustomYieldInstruction,从它派生就好了。
在Unity的文档中还专门举了个例子:
public class WaitUntil : CustomYieldInstruction
{
Func<bool> action_ = null;
public WaitUntil(Func<bool> action)
{
action_ = action;
}
public override bool keepWaiting
{
get
{
return action_();
}
}
}
这是个通用的等待函数,那么我的代码就可以这么写了
IEnumerator Function()
{
dice.Throw();
yield return new WaitUntil(()=> dice.animation == false);
dino.Walk();
yield return new WaitUntil(()=>dino.stop == true);
if (current_pos.HasEvent())
DoEvent();
camera.SwitchPlayer();
yield return new WaitUntil(()=>camera.stop == true);
}
这逻辑写起来清晰多了。在一个函数中描述完成所有的行为,不用将控制代码分散到各处了,连状态控制都省了。
最后派生IEnumerator这个接口也可以。