Unity中可以用Coroutine进行分段延时处理。比如在游戏中经常用到的进度条
我最近就做了一个这样的进度条,利用Coroutine函数隔一段时间更新进度条的进度,这样实现进度条的功能。就是用进度条来表示获取PowerUp(中文是宝物,法宝?)后该PowerUp持续多长时间。
private IEnumerator updatePowerUpProgress()
{
inGamePowerUpData.startTime = Time.time;
float progress = getCurrentProgress();
float progressStep = 0.05f / inGamePowerUpData.duration;
while (progress < 1) {
progress += progressStep;
setCurrentProgress(progress);
yield return inGamePowerUpProgressWaitForSeconds;//这个inGamePowerUpProgressWaitForSeconds在外面已经定义为 new WaitForSeconds(0.05f);
}
//deactivate the powerup
}
另一方面,假设我们要处理暂停操作。就是说当用户玩游戏,获取了powerup,进度条出现,然后用户暂停。这时候我们要重新计算Duration,以便下次用户开始游戏后进度条能正常运行。一般是可以这样做的:
void calcuateNewDuration() { duration -= Time.time - startTime; }
这样下次用户暂停时,程序停止执行updatePowerUpProgress,并重新计算duration,等用户再开始游戏时,程序重新调用updatePowerUpProgress就可以了。
但是注意到涉及到进度条,考虑分段延时后这样做就有可能出现很诡异的现象。就是当进度条临近结束的时候用户暂停,然后等用户开始游戏后会发现,原本快结束的进度条尽然沿反方向递增!看起来很诡异。其实这也是因为分段计时的累计误差导致的。因为进度条临近结束时,实际执行时间是略大于duration的:
Time.time - startTime > duration
这时候用户暂停,然后调用calcuateNewDuration重新计算duration必然会导致duration为负值。这样下次用户开始后程序调用到updatePowerUpProgress的代码,就会使得progress的进度相反了!!
所以,我们应该改写一下calculateNewDuration这个方法:
public void calculateNewDuration_PowerUp(float reverseProgress)
{
_duration = reverseProgress * _originalDuration;
}
这里_originalDuration指的是一开始付给这个进度条的duration。传入的参数reverseProgress = 1 - 用户暂停时的progress。