【问题标题】:WaitForSeconds() Coroutine causes Game to freeze Indefinitely (Edited)WaitForSeconds() 协程导致游戏无限期冻结(已编辑)
【发布时间】:2016-12-04 20:20:10
【问题描述】:

我的游戏有四个场景、一个菜单场景、一个加载场景和两个游戏场景。一切都很好,当我从菜单场景切换到游戏场景时,每当我从游戏场景切换回菜单场景或重新加载游戏场景时,加载场景都会停止响应。只有当我尝试重新加载当前活动的游戏场景时,我才会收到一条警告消息,显示 “NetworkManager 在编辑器中检测到脚本重新加载。这导致网络关闭”这个问题在我玩构建时也存在!我使用打印语句来追踪我的代码停止运行的位置,我发现是 Yield Return New WaitForSeconds() 导致了游戏冻结。这是为什么呢?

我有两个控制过渡的脚本。 在 UIButtons 上调用的一个简单脚本告诉在预加载场景中调用的第二个更复杂的脚本来加载它应该加载的场景并创建动画。我已确保我正在加载到正确的场景,并且所有场景都已添加到我的构建设置中。

以下图片显示加载场景没有响应。第一张图显示了我尝试重新加载当前游戏场景时发生的情况,第二张图显示了我尝试加载菜单场景时发生的情况:

我的加载场景脚本:

public class LoadingScreenManager : MonoBehaviour {

[Header("Loading Visuals")]
public Image loadingIcon;
public Image loadingDoneIcon;
public Text loadingText;
public Image progressBar;
public Image fadeOverlay;

[Header("Timing Settings")]
public float waitOnLoadEnd = 0.25f;
public float fadeDuration = 0.25f;

[Header("Loading Settings")]
public LoadSceneMode loadSceneMode = LoadSceneMode.Single;
public ThreadPriority loadThreadPriority;

[Header("Other")]
// If loading additive, link to the cameras audio listener, to avoid multiple active audio listeners
public AudioListener audioListener;

AsyncOperation operation;
Scene currentScene;

public static int sceneToLoad = -1;
// IMPORTANT! This is the build index of your loading scene. You need to change this to match your actual scene index
static int loadingSceneIndex = 1;

public static void LoadScene(int levelNum) {                
    Application.backgroundLoadingPriority = ThreadPriority.High;
    sceneToLoad = levelNum;
    SceneManager.LoadScene(loadingSceneIndex);
}

void Start() {
    if (sceneToLoad < 0)
        return;

    fadeOverlay.gameObject.SetActive(true); // Making sure it's on so that we can crossfade Alpha
    currentScene = SceneManager.GetActiveScene();
    StartCoroutine(LoadAsync(sceneToLoad));
}

private IEnumerator LoadAsync(int levelNum) {
    ShowLoadingVisuals();

    yield return null; 

    FadeIn();
    StartOperation(levelNum);

    float lastProgress = 0f;

    // operation does not auto-activate scene, so it's stuck at 0.9
    while (DoneLoading() == false) {
        yield return null;

        if (Mathf.Approximately(operation.progress, lastProgress) == false) {
            progressBar.fillAmount = operation.progress;
            lastProgress = operation.progress;
        }
    }

    if (loadSceneMode == LoadSceneMode.Additive)
        audioListener.enabled = false;

    ShowCompletionVisuals();
  //THE PRINT STATEMENT WORKS FINE RIGHT HERE! The value of waitOnLoadEnd is only 1
    yield return new WaitForSeconds(waitOnLoadEnd);
 //THE PRINT STATEMENT STOPS RUNNING RIGHT HERE!  
    FadeOut();

    yield return new WaitForSeconds(fadeDuration);

    if (loadSceneMode == LoadSceneMode.Additive)
        SceneManager.UnloadScene(currentScene.name);
    else
        operation.allowSceneActivation = true;
}

private void StartOperation(int levelNum) {
    Application.backgroundLoadingPriority = loadThreadPriority;
    operation = SceneManager.LoadSceneAsync(levelNum, loadSceneMode);


    if (loadSceneMode == LoadSceneMode.Single)
        operation.allowSceneActivation = false;
}

private bool DoneLoading() {
    return (loadSceneMode == LoadSceneMode.Additive && operation.isDone) || (loadSceneMode == LoadSceneMode.Single && operation.progress >= 0.9f); 
}

void FadeIn() {
    fadeOverlay.CrossFadeAlpha(0, fadeDuration, true);
}

void FadeOut() {
    fadeOverlay.CrossFadeAlpha(1, fadeDuration, true);
}

void ShowLoadingVisuals() {
    loadingIcon.gameObject.SetActive(true);
    loadingDoneIcon.gameObject.SetActive(false);

    progressBar.fillAmount = 0f;
    loadingText.text = "LOADING...";
}

void ShowCompletionVisuals() {
    loadingIcon.gameObject.SetActive(false);
    loadingDoneIcon.gameObject.SetActive(true);

    progressBar.fillAmount = 1f;
    loadingText.text = "LOADING DONE";
}

}

调用上述脚本的 UIButtons 上的脚本:

 public class LoadingSceneButton : MonoBehaviour {

public void LoadSceneWithLoadingScreen(int sceneNumber){
    if (sceneNumber < 0 || sceneNumber >= SceneManager.sceneCountInBuildSettings) {
        Debug.LogWarning ("Can't Load Scene, because It Doesn't Exist!");
    }

    LoadingScreenManager.LoadScene (sceneNumber);
}
}

【问题讨论】:

标签: c# performance debugging testing unity3d


【解决方案1】:

(1) 不要使用“打印”,请使用这个:

  Debug.Log("fadeDuration is ....... " , fadeDuration.ToString("f4");

在您调用FadeOut 之前添加该行代码,也请在FadeOut 中添加它


(2) CrossFadeAlpha 的问题

请注意,CrossFadeAlpha 非常难以使用!这是一个真正的痛苦!它只适用于UnityEngine.UI.Graphic,与协程一起使用时会很棘手。

public static void FadeOut(this Graphic g)
    {
    g.GetComponent<CanvasRenderer>().SetAlpha(1f);
    g.CrossFadeAlpha(0f,.15f,false);
    }

(3) 在 Unity5 中加载场景的问题!!!

是的,有一个

已知问题

卡在 0.9 的地方。也许这是手头的主要问题。

退房...http://answers.unity3d.com/answers/1146173/view.html

和...http://answers.unity3d.com/answers/1073667/view.html

一些基本的工作代码示例......

public void LaunchSoundboard()
    {
    StartCoroutine(_soundboard());
    }
private IEnumerator _soundboard()
    {
    Grid.music.Duck();

    yield return new WaitForSeconds(.2f);

    AsyncOperation ao;
    ao = UnityEngine.SceneManagement
       .SceneManager.LoadSceneAsync("YourSceneName");

    while (!ao.isDone)
        {
        yield return null;
        }

    // here, the new scene IS LOADED
    SoundBoard soundBoard = Object.FindObjectOfType<SoundBoard>();
    if(soundBoard==null) Debug.Log("WOE!");
    soundBoard.SomeFunctionInSoundboardScript();
    }

请注意,您等待“.isDone”,而不是观看浮动。


(4) #你实际上必须有一个名为“preload”的场景,它只能预加载。

不幸的是,菜单场景不是您的预加载场景。

您实际上必须有一个单独的预加载场景,除了“预加载”之外什么都不做。

请注意,您拥有的任何“游戏管理器”都必须在预加载场景中。这有点烦人,但就是这样。

“预加载”场景的目的是容纳您拥有的任何游戏管理器。

您标记为“加载时不破坏”的only场景必须是only“预加载”场景。就这么简单。

这有点麻烦,但非常简单可靠。

【讨论】:

  • 我现在用来加载场景的功能 SceneManager.LoadSceneAsync 不可以达到这个目的吗?我不知道有任何其他方法可以做到这一点。 @JoeBlow docs.unity3d.com/ScriptReference/…
  • 我确实想等到下一帧,我知道 yield return null 和 yield break 之间的区别。
  • 嗨 Aaron,您确实必须有一个“预加载”场景:除了保存您的持久组件(声音效果等)之外,它什么也不做。也许阅读这个最新的书面解释......stackoverflow.com/a/35891919/294884
  • 好的,但是为什么 WaitForSeconds() 会导致游戏死机? @JoeBlow
  • “好的,但是为什么 WaitForSeconds() 会导致游戏死机”正如我所说,放入 Debug.Log 语句,并告诉我们结果
猜你喜欢
  • 1970-01-01
  • 2020-11-15
  • 2018-03-30
  • 2013-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-20
  • 1970-01-01
相关资源
最近更新 更多