【发布时间】: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);
}
}
【问题讨论】:
-
嘿亚伦!我确实进一步整理了这个答案......stackoverflow.com/a/35891919/294884我试图更清楚地解释这个过程。也许会有所帮助?
标签: c# performance debugging testing unity3d