Coroutine stoppt, wenn Time.timeScale = 0 ist


7

Ich habe eine Coroutine, die eine Variable in meiner Benutzeroberfläche reibungslos ändert, aber wenn ich das Spiel pausiere, pausiert auch die Coroutine. Wie kann ich das beheben?

Code:

using UnityEngine;
using System.Collections;

public class HUDController : MonoBehaviour {
    public void PauseGame() {
        FreezeTime();
        StartCoroutine(ShowPauseMenu());
    }

    private void FreezeTime() {
        Time.timeScale = 0;
    }

    private IEnumerator ShowPauseMenu() {
        var pauseMenuCanvasGroup = GameObject.FindWithTag("PauseMenu").GetComponent<CanvasGroup>();
        var alphaValue = 1f;
        var velocity = 0f;
        var time = 0.15f;

        while (!Mathf.Approximately(pauseMenuCanvasGroup.alpha, alphaValue)) {
            pauseMenuCanvasGroup.alpha = Mathf.SmoothDamp(pauseMenuCanvasGroup.alpha, alphaValue, ref velocity, time);
            yield return null;
        }

        pauseMenuCanvasGroup.alpha = 1; // Since float is not accurate, manually set the alpha to 1
        pauseMenuCanvasGroup.interactable = true;
    }
}

Ich bin nicht in der Lage, dieses Problem in Unity 5 zu reproduzieren. In meinen Tests kann ich das korrigieren yield return nulloder new WaitForEndOfFrame()weiter summen, wenn Time.timeScale = 0- es ist nur yield return new WaitForSeconds(delay)diese Pause. Können Sie bestätigen, welche Version von Unity Sie ausführen?
— DMGregory

@ DMGregory 5.2.3f1
— Milen

Wie sicher sind Sie sich, dass die Zeitskala die Ursache ist? Haben Sie versucht, die Zeitskala nicht auf Null zu setzen und trotzdem die Coroutine auszuführen?
— Athos vk

Ja, ich habe die Zeitskala entfernt und sie läuft
— Milen

Kann jemand helfen?
— Milen

Antworten:


13

Dies ist sicher, weil geschah Mathf.SmoothDampAnwendungen Time.deltaTimein Standardberechnung. Wenn Sie Time.timeScale = 0dann einstellen, Mathf.SmoothDampwird nicht wiederholt der erwartete Wert, sondern nur der erste Wert angegeben.

Sie können dies weiter überprüfen, indem Sie den Alpha-Wert auf die Konsole drucken und ihn in Ihrer whileSchleife drucken, damit Sie ihn durch die unbegrenzten Protokolle mit demselben Wert bestätigen können.

Hier ist die Dokumentation zu Mathf.SmoothDamp .

Sie können dies beheben, indem Sie Ihre eigene deltaTime übergeben, um zu verhindern, dass die Standardeinstellung verwendet wird Time.deltaTime. Fügen Sie am Ende des Aufrufs einfach einen weiteren Parameter hinzu:

pauseMenuCanvasGroup.alpha = Mathf.SmoothDamp(
  pauseMenuCanvasGroup.alpha, 
  alphaValue, 
  ref velocity, 
  time,
  1000,          // <-- Fifth parameter Optionally allows you to clamp the maximum speed.
  1.0f/30.0f);   // <-- Add a sixth parameter representing your framerate.

Sie können eine Funktion verwenden, die die verstrichene Echtzeit anstelle einer Konstanten misst, wenn Ihre Rendering-Framerate variabel ist.


3
Lieben Sie es nicht, wenn Methoden aus völlig vernünftigen (wenn auch schwer zu erkennenden) Gründen etwas völlig Unerwartetes tun?
— Draco18s vertraut SE am

Es funktioniert nicht. Es gibt immer noch nur den ersten Wert.
— Milen

@Milen yup, das war dort ein wenig falsch, eigentlich sollte das der 6. Parameter sein anstatt der 5., 5. ist die Höchstgeschwindigkeit. Überprüfen Sie die Änderungen
— Hamza Hasan

@Milen jetzt ist der Code gründlich getestet :) Probieren Sie es aus :)
— Hamza Hasan

0

Ich hatte dieses Problem und die Situation war so, und ich habe es gelöst . Der Benutzer drückt die Pause-Taste, dann gehen einige Objekte aus (diese Objekte haben Couroutine (s)). DAS IST DAS PROBLEM. Ich darf diese Spielobjekte nicht ausschalten . Die Coroutinen funktionieren einwandfrei, während das Spielobjekt eingeschaltet ist und wenn Sie sie ausschalten, wird alles durcheinander sein.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.