Unity披萨餐厅游戏中WaitForPizza协程无法停止的问题求助
Fixing Your WaitForPizza Coroutine Stop Issue
Hey there! Let's break down why your WaitForPizza coroutine won't stop when you deliver the pizza, and fix it step by step.
The Core Problem
Your current code has two big issues with how you handle coroutine instances:
- Mismatched Coroutine References: You initialize
WAIT = WaitForPizza()inStart(), but every time you callStartCoroutine(WaitForPizza())inUpdate(), you're creating a new coroutine instance. TheWAITvariable points to the original (unused) instance, soStopCoroutine(WAIT)does nothing to the actually running coroutines. - Repeated Coroutine Starts: The
Update()loop checks your condition every frame, so it's starting dozens ofWaitForPizzacoroutines over time—even if one's already running. Stopping a single reference won't kill all those duplicates.
Fixed Code Implementation
Here's the revised code with comments explaining the key changes:
// Use Coroutine type to track actively running coroutines (not just IEnumerator) private Coroutine currentWaitCoroutine; private Coroutine currentEatCoroutine; private Coroutine currentPayCoroutine; private void Start() { // No need to pre-initialize IEnumerators—we'll create coroutines when needed } private void OnTriggerEnter(Collider other) { if (other.gameObject.CompareTag("Pizza")) { canEat = true; // Stop the wait coroutine immediately when pizza is delivered StopWaitCoroutine(); } if (other.gameObject.CompareTag("Out")) { Destroy(this.gameObject); } } void Update() { if (isEating) { if (Vector3.Distance(transform.position, agent.destination) <= 1f) { anim.SetTrigger("sit"); isEating = false; } } // Only start WaitForPizza if it's not already running and conditions are met if (!isEating && !isPaying && !isOut && !canEat && currentWaitCoroutine == null) { currentWaitCoroutine = StartCoroutine(WaitForPizza()); } // Start EatPizza when canEat is true, and ensure we don't start multiple instances if (!isEating && !isPaying && !isOut && canEat && currentEatCoroutine == null) { currentEatCoroutine = StartCoroutine(EatPizza()); } if (isPaying) { isEating = false; anim.SetTrigger("walk"); agent.destination = checkoutTarget.position; if (Vector3.Distance(transform.position, agent.destination) <= 1f) { anim.SetTrigger("wait"); if (ifCashier) { // Throw money logic here isPaying = false; isOut = true; } if (!ifCashier && currentPayCoroutine == null) { currentPayCoroutine = StartCoroutine(WaitForTheCase()); } } } if (isOut) { anim.SetTrigger("walk"); isEating = false; isPaying = false; agent.destination = outTarget.position; // Clean up coroutines when leaving StopAllCoroutines(); currentWaitCoroutine = null; currentEatCoroutine = null; currentPayCoroutine = null; } } // Helper method to safely stop the wait coroutine private void StopWaitCoroutine() { if (currentWaitCoroutine != null) { StopCoroutine(currentWaitCoroutine); currentWaitCoroutine = null; } } IEnumerator WaitForTheCase() { anim.SetTrigger("wait"); yield return new WaitForSeconds(randomFloatWait); angry.SetActive(true); isEating = false; isPaying = false; isOut = true; currentPayCoroutine = null; } IEnumerator EatPizza() { angry.SetActive(false); happy.SetActive(true); yield return new WaitForSeconds(randomFloatWait); happy.SetActive(false); isEating = false; isPaying = true; isOut = false; currentEatCoroutine = null; } IEnumerator WaitForPizza() { yield return new WaitForSeconds(randomFloatWait); // Only trigger angry state if we still haven't received pizza if (!canEat) { angry.SetActive(true); isEating = false; isPaying = false; isOut = true; } currentWaitCoroutine = null; }
Key Changes Explained
- Coroutine Tracking: We switched from
IEnumeratorvariables toCoroutinevariables. This lets us track the actual running instance of each coroutine, so we can stop it reliably. - Single Instance Checks: We add checks like
currentWaitCoroutine == nullbefore starting a new coroutine, preventing multiple duplicate coroutines from running at once. - Helper Stop Method: The
StopWaitCoroutine()method ensures we only stop the coroutine if it's actually running, avoiding null reference errors. - Cleanup: We reset coroutine references to
nullonce they finish, so we can start them again later if needed. - Simplified WaitForPizza: Removed the while loop (it was causing infinite waits if
canEatnever triggered) and added a check after the wait to only trigger anger if the pizza still hasn't been delivered.
This should fix your issue—when the pizza is delivered, the WaitForPizza coroutine will be stopped immediately, and EatPizza will take over as expected.
内容的提问来源于stack exchange,提问作者Dcnsll
相关产品推荐
相关产品推荐

