c# - Unity 中的队列方法和协程
问题描述
我正在尝试创建一个方法队列,一旦前一个方法完全执行,该方法就会开始执行下一个方法,该方法队列对于除 IEnumerator 返回类型一之外的所有场景都可以正常工作。
以下是我尝试一个接一个执行的方法列表。
public void CallMethod()
{
UnityMainThreadDispatcher.Schedule(() =>
{
ShowMessage("Minimum!");
}
, 0.3f);
Debug.Log("Winner of this round is " + winnerPlayer.GetName());
UnityMainThreadDispatcher.Schedule(() =>
{
scoreboardPopup.ShowPopup();
}
, 5.0f);
UnityMainThreadDispatcher.Schedule(() =>
{
CardDistributionAnimation.instance.PlayCardDistributionAnimation(false);
}, 0.5f);
UnityMainThreadDispatcher.Schedule(() => StartNextRound(),0.5f);
Debug.Log("Call Minimum Completed");
}
UnityMainThread 类
public class UnityMainThreadDispatcher : MonoBehaviour
{
private Queue<IEnumerator> coroutineQueue = new Queue<IEnumerator>();
public delegate void Task();
public static void Schedule(Task task, float delay)
{
Debug.Log("Task Scheduled " + task.Method);
//Instance().Enqueue(task, delay);
Instance().coroutineQueue.Enqueue(DoTask(task, delay));
}
private static IEnumerator DoTask(Task task, float delay)
{
Debug.Log("Inside DoTask Coroutine");
yield return new WaitForSeconds(delay);
task();
}
IEnumerator CoroutineCoordinator()
{
while (true)
{
while (coroutineQueue.Count > 0)
yield return StartCoroutine(coroutineQueue.Dequeue());
yield return null;
}
}
private static UnityMainThreadDispatcher _instance = null;
public static bool Exists()
{
return _instance != null;
}
public static UnityMainThreadDispatcher Instance()
{
if (!Exists())
{
throw new Exception("UnityMainThreadDispatcher could not find the UnityMainThreadDispatcher object. Please ensure you have added the MainThreadExecutor Prefab to your scene.");
}
return _instance;
}
private void Start()
{
StartCoroutine(CoroutineCoordinator());
}
}
CoroutineQueue 只会在其队列中启动下一个方法,一旦前一个方法成功执行,除了以下方法外,它对所有方法都正常工作
CardDistributionAnimation.instance.PlayCardDistributionAnimation(false);
这是因为 PlayCardDistributionAnimation 在 Coroutine 方法上执行。
PlayCardDistributionAnimation 方法
public void PlayCardDistributionAnimation(bool isNewGame)
{
generateCards(isNewGame);
StartCoroutine(DistributeCardsToPlayer());
}
public void generateCards(bool isNewGame)
{
int size = 0;
if (generatedCards.Count > 0)
generatedCards.Clear();
GameObject distributionobject = GameObject.Find("CardDistributionObject");
if (isNewGame)
size = playersPosition.Count * 2;
else
size = playersPosition.Count;
for (int i = 0; i < size; i++)
{
GameObject vector2 = Instantiate(cardsBack, distributionobject.transform);
generatedCards.Add(vector2);
vector2.SetActive(true);
}
}
private IEnumerator DistributeCardsToPlayer()
{
Debug.Log("Inside Distribute Cards To Player");
for(int i=0;i< generatedCards.Count();i++)
{
var cover = Instantiate(cardsBack, generatedCards[i].transform.position, Quaternion.identity, generatedCards[i].transform);
cover.GetComponent<RectTransform>().localScale = Vector3.one;
var tween = cover.transform.DOMove(playersPosition[i%(playersPosition.Count)].transform.position, 0.5f);
tween.OnComplete(() => Destroy(cover));
yield return new WaitForSeconds(0.6f);
}
yield return new WaitForSeconds(1f);
//playersPosition.First().SetActive(true);
foreach (GameObject gameObject in generatedCards)
Destroy(gameObject);
isCardDistributionCompleted = true;
Debug.Log("Card Distribution method executed succussfully");
}
在我的协程完全执行之前,我不确定我如何无法停止其他方法的执行。我尝试了几种方法,但到目前为止都没有奏效,任何建议都会非常有帮助。
解决方案
首先,您的委托Task
非常令人困惑.. 已经有一个Task
用于运行异步任务的类。
这也是非常不必要的,因为已经有一个参数较少的委托类型 void: Action
;)
然后我会创建一个重载,它只需要协程,就像
public class UnityMainThreadDispatcher : MonoBehaviour
{
private Queue<IEnumerator> coroutineQueue = new Queue<IEnumerator>();
public static void Schedule(IEnumerator routine, float delay)
{
Instance().coroutineQueue.Enqueue(DoTask(routine,delay));
}
public static void Schedule(Action task, float delay)
{
Debug.Log("Task Scheduled " + task.Method);
//Instance().Enqueue(task, delay);
Instance().coroutineQueue.Enqueue(DoTask(task, delay));
}
private static IEnumerator DoTask(Action task, float delay)
{
Debug.Log("Inside DoTask Coroutine");
yield return new WaitForSeconds(delay);
task();
}
private static IEnumerator DoTask(IEnumerator task, float delay)
{
Debug.Log("Inside DoTask Coroutine");
yield return new WaitForSeconds(delay);
yield return StartCoroutine(task);
}
private IEnumerator Start()
{
while (true)
{
while (coroutineQueue.Count > 0)
yield return StartCoroutine(coroutineQueue.Dequeue());
yield return null;
}
}
private static UnityMainThreadDispatcher _instance = null;
public static bool Exists()
{
return _instance != null;
}
public static UnityMainThreadDispatcher Instance()
{
if (!Exists())
{
throw new Exception("UnityMainThreadDispatcher could not find the UnityMainThreadDispatcher object. Please ensure you have added the MainThreadExecutor Prefab to your scene.");
}
return _instance;
}
}
然后宁愿做你的方法
public void PlayCardDistributionAnimation(bool isNewGame)
{
StartCoroutine(PlayCardDistributionAnimationRoutine(isNewGame));
}
public IEnumerator PlayCardDistributionAnimationRoutine(bool isNewGame)
{
generateCards(isNewGame);
yield return DistributeCardsToPlayer();
}
对于预定版本,请改用例程
UnityMainThreadDispatcher.Schedule(
CardDistributionAnimation.instance.PlayCardDistributionAnimationRoutine(false),
0.5f
);
有趣的是,您使用了主线程分派器——它实际上用于将来自其他线程的异步内容分派回 Unity 主线程——并将其变成完全不同的东西^^
注意:在智能手机上打字,但我希望这个想法很清楚
推荐阅读
- python - 通过预签名 URL 进行的简单 PUT 操作不断出现错误“我们计算的请求签名与您提供的签名不匹配”
- data-structures - 数据结构。未定义对“系统”的引用|
- google-cloud-platform - 启动时创建任务时的 DeadlineExceededException
- stm32 - 使用 Truestudio 调试时,在 STM32L4 上看不到 TIM15 的 CH2 的寄存器
- python - Selenium 下载适用于任何操作系统的 chromedriver
- bash - Bash:在shell脚本中将变量传递给其他服务器
- python - 超出表中每一列的范围计数
- amazon-web-services - S3 依赖未打包
- python - 在后台运行 Python 脚本
- python - Spyder 4:代码分析——约定、重构、警告和错误