¿Cómo ejecuto el código por un período de time y luego return al comportamiento normal?

Quiero ejecutar un código para mi poder especial durante cinco segundos solamente y luego volver a mi funcionamiento normal. cuando ese poder se activa estoy cambiando el material de mi jugador y quiero volver a mi material anterior después de esos cinco segundos. este es el código que probé:

void Start () { transform.GetComponent<Renderer> ().material.mainTexture = texts [0]; } void Update () { if (condition) { for (int t1 = 0; t1 < 5; t1 += (int)Time.deltaTime) { transform.GetComponent<Renderer> ().material = mats [0]; } transform.GetComponent<Renderer> ().material.mainTexture = texts [0]; } } 

este código rompe el juego, creo, porque la unidad se congela cuando se cumple la condición.

Sí, este código congela el juego, porque es un bucle infinito. Parece que tiene dos ideas erróneas que parecen haberlo llevado a escribir este código:

  1. Unity procesa cada método de Update en una amenaza independiente de ejecución. ¡Eso está mal! Mientras se ejecuta un método de Update , no sucede nada más en el motor. Por lo tanto, es importante que sus methods de Update (así como cualquier otro manejador de posts) regresen rápidamente.
  2. Cuando un método de Update demora un time, Time.deltaTime aumenta. ¡También está mal! Le da el time en segundos que tardó en completar el último cuadro, por lo que solo cambiará entre las Update .

Casting Time.deltaTime to int lo networkingondeará hacia abajo. Time.deltaTime solo cambia entre las Update y casi siempre será muy inferior a 1.0 . eso significa que 0 se agrega a t1 una y otra vez. Este for-loop funcionará para siempre y no permitirá que Unity haga nada más. Si quieres que Unity pueda reanudar el juego normal mientras el poder especial está activo, debes devolver el flujo de ejecución del progtwig al motor dejando tu método de Update .

Hay varios patrones que puede usar para implementar esto.

Componente temporal

Puedes implementar tu efecto especial como un Component que agregas al gameObject cuando se activa el efecto especial. Programe el componente para que se elimine automáticamente cuando finalice el time del efecto. Puede hacerlo tomando el time que se creó y haciendo que el método de actualización compruebe si ha transcurrido el time.

 public class ActiveSpecialPower : MonoBehaviour { private float startTime; private static readonly float POWER_DURATION_IN_SECONDS = 5.0f; void Start() { startTime = Time.time; // code which happens on activation of the special power } void Update () { if (Time.time > startTime + POWER_DURATION_IN_SECONDS) { // code which happens on deactivation of special power Destroy(this); } } } 

Código para activar el poder especial:

 gameObject.AddComponent<ActiveSpecialPower>(); 

Código para verificar si la energía especial está actualmente activa:

 if(gameObject.GetComponent<ActiveSpecialPower>() != null) { 

Componente permanente

O puede tener su componente SpecialPower permanentemente en su object de juego jugador y tener un método para activarlo:

 public class SpecialPower : MonoBehaviour { public float remainingTime; private static readonly float POWER_DURATION_IN_SECONDS = 5.0f; public void Activate() { // code which happens on activation of the special power remainingTime = POWER_DURATION_IN_SECONDS; } void Update () { if (remainingTime > 0.0f) { // code which happens every update while the power is active remainingTime -= Time.deltaTime; if (remainingTime <= 0.0f) { // code which happens on deactivation of special power } } } } 

Código para activar el poder especial:

 gameObject.GetComponent<SpecialPower>().Activate(); 

Código para verificar si la energía especial está actualmente activa:

 if(gameObject.GetComponent<SpecialPower>().remainingTime > 0.0f) { 

Corutina

Otra opción es implementar su efecto especial como una Corutina . Una coroutine puede usar el yield return WaitForSeconds(n) construcción yield return WaitForSeconds(n) para devolver el flujo de progtwig al motor y continuarlo después de que haya pasado el time dado. Tal método de corrutina podría verse así:

 private IEnumerator ActivateSpecialPowerCoroutine() { // code which happens on start of special power yield return new WaitForSeconds(POWER_DURATION_IN_SECONDS); // code which happens on end of special power } 

Código para activar el poder especial:

 StartCoroutine(ActivateSpecialPowerCoroutine()); 

Lamentablemente, no hay una buena manera de comprobar si una coroutine se está ejecutando actualmente.