[英]How can I waitwhile or waituntil in IEnumerator and then continue the coroutine?
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class NaviConversations : MonoBehaviour
{
public ObjectsManipulation op;
public Scaling scaling;
public ConversationTrigger conversationTrigger;
private void Update()
{
if (DOFControl.hasFinished == true)
{
ConversationTrigger.conversationsToPlay.Add(0);
StartCoroutine(NaviScaling());
DOFControl.hasFinished = false;
}
}
public IEnumerator NaviScaling()
{
// Scaling Up
if (scaling.objectToScale.transform.localScale == scaling.minSize)
{
op.Scaling();
}
yield return new WaitUntil
op.Scaling();
}
}
在這一部分:
yield return new WaitUntil
我要等待縮放的對象完成縮放:
scaling.objectToScale.transform.localScale == scaling.maxSize
如果是這樣,則繼續繼續並執行以下操作:
conversationTrigger.PlayConversations();
然后再次等待,直到:
conversationTrigger.conversationEnd
是真的。
如果確實如此,請縮減:
op.Scaling();
步驟應為:
添加對話索引以播放。
放大。 並等待放大完成。
開始對話。 然后等待對話結束。
縮小。
我正在嘗試找到最簡單的等待方法,以及一種可以從任何地方調用public IEnumerator NaviScaling()方法的方法。
更新中的部分:
if (DOFControl.hasFinished == true)
游戲開始時發生一次。
這是op.Scaling使用的腳本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectsManipulation : UnityEngine.MonoBehaviour
{
//Camera
public Camera playerCamera;
//Scaling
public bool canScale = true;
private Scaling scaling;
//Lights
public DimLights dimlights;
private Coroutine lightCoroutine;
//Colors
private Colors colors;
//Rotating
public bool stopRotation = false;
private Rotating rotating;
private void Start()
{
scaling = GetComponent<Scaling>();
scaling.Inits();
colors = GetComponent<Colors>();
colors.Start();
rotating = GetComponent<Rotating>();
}
// Use this for initialization
void Update()
{
if (playerCamera != null)
{
//Scaling
if (Input.GetKeyDown(KeyCode.F) && canScale == true)
{
Scaling();
}
}
//Rotate
if (Input.GetKey(KeyCode.R) && !scaling.scaleUp)
{
rotating.x += Time.deltaTime * rotating.rotationSpeed;
scaling.objectToScale.transform.localRotation = Quaternion.Euler(0, 0, rotating.x);
rotating.keyPressed = true;
}
if (Input.GetKeyUp(KeyCode.R))
{
rotating.keyPressed = false;
}
if (!rotating.keyPressed && !scaling.scaleUp && rotating.rotateBack == false
&& DetectInteractable.detected == false)
{
scaling.objectToScale.transform.rotation = Quaternion.LookRotation(playerCamera.transform.forward);
}
if (DetectInteractable.detected == true && !scaling.scaleUp && stopRotation == false)
{
rotating.x += Time.deltaTime * rotating.rotationSpeed;
scaling.objectToScale.transform.localRotation = Quaternion.Euler(0, 0, rotating.x);
}
}
public void Scaling()
{
//Flip the scale direction when F key is pressed
scaling.scaleUp = !scaling.scaleUp;
//Stop old coroutine
if (scaling.scaleCoroutine != null)
StopCoroutine(scaling.scaleCoroutine);
if (lightCoroutine != null)
StopCoroutine(lightCoroutine);
//Scale up
if (scaling.scaleUp)
{
//Start new coroutine and scale up within 5 seconds and return the coroutine reference
rotating.rotateBack = false;
scaling.scaleCoroutine = StartCoroutine(scaling.scaleOverTime(scaling.objectToScale, scaling.maxSize, scaling.duration, playerCamera));
if (dimlights.lightsOnOff == false)
lightCoroutine = StartCoroutine(dimlights.dimLightOverTime(1, scaling.duration));
}
//Scale Down
else
{
//Start new coroutine and scale up within 5 seconds and return the coroutine reference
rotating.rotateBack = true;
scaling.scaleCoroutine = StartCoroutine(scaling.scaleOverTime(scaling.objectToScale, scaling.minSize, scaling.duration, playerCamera));
if (dimlights.lightsOnOff == false)
lightCoroutine = StartCoroutine(dimlights.dimLightOverTime(0, scaling.duration)); ;
}
}
}
要使用WaitUntil
,您將需要為其提供一種檢查其等待條件的方法。 這是通過將委托傳遞給其構造函數來完成的。
因此,要等到對象仍在縮放時,您將執行以下操作:
yield return new WaitUntil(() => scaling.objectToScale.transform.localScale == scaling.minSize);
注意條件之前的() =>
,這會將您的表達式轉換為匿名函數,該函數允許WaitUntil在每個幀上重新評估條件。
您還可以傳遞一個方法作為委托,它看起來很漂亮!
private bool IsFinishedScaling () {
return scaling.objectToScale.transform.localScale == scaling.minSize;
}
public IEnumerator Example () {
yield return new WaitUntil(IsFinishedScaling);
Debug.Log("Scaling has finished!");
}
這應該可以滿足您的需求:
public IEnumerator NaviScaling()
{
if (scaling.objectToScale.transform.localScale == scaling.minSize)
{
op.Scaling();
}
while (scaling.objectToScale.transform.localScale != scaling.maxSize)
{
yield return null;
}
conversationTrigger.PlayConversations();
while (!conversationTrigger.conversationEnd)
{
yield return null;
}
op.Scaling();
}
我對到目前為止給出的答案不太滿意。
基本上,問題是如何使用WaitUntil
,它甚至沒有被接受的答案使用 (順便說一句,它提供了一個真正的梅西代碼。)
另一個仍然可以擴展的原因是,兩個答案都基於使用==
來檢查相等性。 但是對於Vector3
這只是假設
Vector3.Distance(vectorA, vectorB) <= 0.00001f
通常,這對於位置之間的距離非常有用,但對於比例尺,您可能更希望更精確的值。
如果那是目標,並且您不需要比堅持下去更精確。
否則,我寧願使用Mathf.Approximately
進行檢查,例如將其作為擴展方法,例如
public static class Vector3Extensio s
{
public static bool IsSameValue(this Vector3 a, Vector3 b)
{
return Mathf.Approximately(Vector3.Distance(a,b), 0f);
}
}
比使用
yield return new WaitUntil(() => scaling.objectToScale.transform.localScale.IsSameValue(scaling.maxSize));
當然,這很大程度上取決於op.Scaling
工作方式,而您並未展示。
或者:(我更願意)
不幸的是,您沒有顯示op.Scaling()
功能。 最簡單的方法實際上是使其也成為IEnumerator
,因為您可以簡單地讓它yield return
另一個IEnumerator
,這使它執行並自動等待直到僅一行完成。
假設您進行op.Scaling
例如
public IEnumerator Scaling(Vector3 targetScale, float duration)
{
// Get current scale
var startScale = transform.localScale;
var timePassed = 0f;
do
{
transform.localScale = Vector3.Lerp(startScale, targetScale, timePassed / duration);
timePassed += Time.deltaTime;
yield return null;
} while(timePassed <= duration);
transform.localScale = targetScale;
}
你可以做
public IEnumerator NaviScaling()
{
// Scale up in 1 second and wait
yield return op.Scaling(scaling.maxSize, 1f);
// As you can see again this could be a Coroutine so you could directly yield it
// instead of having to wait for the bool value to turn true
conversationTrigger.PlayConversations();
yield return new WaitUntil(() => conversationTrigger.conversationEnd);
// Scale down in 1 second and wait
yield return op.Scaling(scaling.minSize, 1f);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.