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;
    }
}
Milen
quelle
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.

Hamza Hasan
quelle
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.

ebrahim.mr
quelle