在使用timeScale 0f暂停游戏时,如何暂停/恢复协程? [英] How can I pause/resume a Coroutine when pausing the game with timeScale 0f?
问题描述
例如此协程.假设我有一个ui按钮可以暂停游戏:
For example this Coroutine. Let's say I have a ui button that pause the game :
Time.timeScale = 0f;
但是timeScale在协程上不起作用.
But timeScale is not working on Coroutines.
如果我在游戏中有很多协程,有没有办法找到所有的协程,然后在它们上循环并暂停它们,还是我需要在每个协程中添加一个暂停循环?
And if I have many Coroutines in the game is there a way to find all the Coroutines and then loop on them and pause them or do I need to add a pause loop to each Coroutine ?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.PostProcessing;
public class DepthOfField : MonoBehaviour
{
public UnityEngine.GameObject player;
public PostProcessingProfile postProcessingProfile;
public bool dephOfFieldFinished = false;
public LockSystem playerLockMode;
private Animator playerAnimator;
private float clipLength;
private Coroutine depthOfFieldRoutineRef;
void Start()
{
if (depthOfFieldRoutineRef != null)
{
StopCoroutine(depthOfFieldRoutineRef);
}
playerAnimator = player.GetComponent<Animator>();
AnimationClip[] clips = playerAnimator.runtimeAnimatorController.animationClips;
foreach (AnimationClip clip in clips)
{
clipLength = clip.length;
}
var depthOfField = postProcessingProfile.depthOfField.settings;
depthOfField.focalLength = 300;
StartCoroutine(changeValueOverTime(depthOfField.focalLength, 1, clipLength));
postProcessingProfile.depthOfField.settings = depthOfField;
}
IEnumerator changeValueOverTime(float fromVal, float toVal, float duration)
{
playerLockMode.PlayerLockState(true, true);
float counter = 0f;
while (counter < duration)
{
var dof = postProcessingProfile.depthOfField.settings;
if (Time.timeScale == 0)
counter += Time.unscaledDeltaTime;
else
counter += Time.deltaTime;
float val = Mathf.Lerp(fromVal, toVal, counter / duration);
dof.focalLength = val;
postProcessingProfile.depthOfField.settings = dof;
yield return null;
}
playerAnimator.enabled = false;
dephOfFieldFinished = true;
depthOfFieldRoutineRef = null;
}
}
推荐答案
您可以使用观察者模式并为游戏创建一组状态,例如:LoadingGame
,Paused
,LoadingLevel
等,并使用事件来掌握状态变化并采取适当的措施.
You could use the Observer Pattern and create a set of states for the game like: LoadingGame
, Paused
, LoadingLevel
etc and use events to hook into state changes and take appropriate action.
例如:
public enum GameState {
LoadingGame,
LoadingLevel,
Paused,
...
}
然后在全局管理器中,在状态更改时触发一个事件:
Then in a global manager, fire off an event when the state changes:
public event Action<GameState, GameState> OnGameStateChange;
public void SwitchGameState (GameState to) {
previousState = CurrentState;
CurrentState = to;
switch (to) {
case GameState.Paused:
...
break;
...
}
OnGameStateChange?.Invoke (previousState, CurrentState);
}
任何其他组件,例如您的DepthOfField
,都可以监听事件并采取适当的措施:
Any other components, like your DepthOfField
can listen to the event and take appropriate action:
void Awake () {
gameManager.OnGameStateChange += HandleGameStateChange;
}
void HandleGameStateChange (GameState from, GameState to) {
switch (to) {
case GameState.Paused:
// stop or pause couroutine etc
StartCoroutine(coroutine);
break;
}
}
这篇关于在使用timeScale 0f暂停游戏时,如何暂停/恢复协程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!