【发布时间】:2019-03-01 17:03:16
【问题描述】:
问题
我构建的 Unity 项目面向 iOS、Android 和 Windows X64。我有两个场景,A 和 B,而 A 是我游戏的主菜单场景,场景 B 是一种关卡选择场景,用户可以在其中选择要玩的关卡。从场景 A 我可以导航到场景 B 并再次返回。在 Unity Editor 中运行游戏时,一切都按预期运行。当我在目标平台(真实设备)上运行游戏时,问题就出现了。然后,当像 A --> B --> A 那样导航时,我最终会在场景 A 中渲染为黑屏,但 FPSIndicator 游戏对象仍然在渲染并完成其工作。 FPSIndicator 游戏对象是一小段代码,它在 OnGUI 回调中将自己吸引到场景中。没有其他内容显示。
场景 A 的设置
我有一个 Unity UI 按钮(“拖放”),单击该按钮时,使用以下代码加载场景 B:
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.EventSystems;
public class GameTypeButtonController : MonoBehaviour, IPointerClickHandler
{
public ButtonSounds ButtonSounds;
public string SceneNameToLoad;
public GameType GameType;
public void OnPointerClick(PointerEventData eventData)
{
StartCoroutine(Do());
}
private IEnumerator Do()
{
var animator = gameObject.GetComponent<Animator>();
if (animator != null)
{
animator.SetTrigger("Clicked");
}
var audioSource = gameObject.GetComponent<AudioSource>();
if (audioSource != null)
{
var clip = GetRandomAudioClip(ButtonSounds);
audioSource.clip = clip;
audioSource.Play();
yield return new WaitWhile(() => audioSource.isPlaying);
}
Logger.LogInfo("[GameTypeButtonController.Do] Setting game type " + GameType);
GameManager.Instance.CurrentGameType = GameType;
SceneManager.LoadScene(SceneNameToLoad);
}
private AudioClip GetRandomAudioClip(ButtonSounds buttonSounds)
{
var numberOfAudioClips = buttonSounds.AudioClips.Length;
var randomIndex = Random.Range(0, numberOfAudioClips);
return buttonSounds.AudioClips[randomIndex];
}
}
场景是这样的:
场景 B 的设置
在场景 B 中,我在左下角有一个按钮,点击后我会回到场景 A。这不是 Unity UI 按钮,而是附加了 CircleCollider2D 的常规精灵。该按钮上的脚本如下所示:
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
public class HomeButtonController : MonoBehaviour
{
public ButtonSounds ButtonSounds;
public string SceneNameToLoad;
void OnMouseDown()
{
StartCoroutine(Do());
}
private IEnumerator Do()
{
var animator = gameObject.GetComponent<Animator>();
if (animator != null)
{
animator.SetTrigger("Clicked");
}
var audioSource = gameObject.GetComponent<AudioSource>();
if (audioSource != null)
{
var clip = GetRandomAudioClip(ButtonSounds);
audioSource.clip = clip;
audioSource.Play();
yield return new WaitWhile(() => audioSource.isPlaying);
}
SceneManager.LoadScene(SceneNameToLoad);
}
private AudioClip GetRandomAudioClip(ButtonSounds buttonSounds)
{
var numberOfAudioClips = buttonSounds.AudioClips.Length;
var randomIndex = UnityEngine.Random.Range(0, numberOfAudioClips);
return buttonSounds.AudioClips[randomIndex];
}
}
场景是这样的:
一般说明
两个对象使用DontDestroyOnLoad:GameManager 和MusicPlayer。
到目前为止我检查过的内容
- 在构建设置中正确引用了场景
- 在使用 Unity Cloud Build 时,我禁用了库缓存功能以避免旧的构建工件出现问题(因此每次构建时,我都会进行正确、干净的构建)
- 我可以在本地构建所有三个平台(Unity 将其报告为“构建成功”)。所以没有构建错误。
- 我正在使用
LoadSceneMode.Single(默认) - 我在本地和 Unity Cloud Build 中使用相同的 Unity 版本:2018.3.0f2
2019 年 2 月 19 日更新:
当我使用相同的机制(调用协程的精灵按钮)从第三个场景 C 导航回场景 A 时,我也最终进入了相同的黑屏。那么问题可能存在于场景 A 中?
2019-02-19 更新 2:
这是我的 GameManager 代码:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;
public class GameManager : MonoBehaviour
{
public EventHandler<LevelStartedEventArgs> LevelStarted;
public EventHandler<LevelFinishedEventArgs> LevelFinished;
// General
public GameType CurrentGameType;
public GameScene CurrentScene;
public int CurrentLevel;
public static GameManager Instance;
public GameLanguage Language;
public bool IsMusicEnabled;
private string gameStateFile;
void Start()
{
if (Instance == null)
{
gameStateFile = Application.persistentDataPath + "/gamestate.dat";
Load(gameStateFile);
DontDestroyOnLoad(gameObject);
Instance = this;
}
else if (Instance != this)
{
Destroy(gameObject);
}
}
public void Save()
{
Logger.LogInfo("[GameManager.Save] Saving game state to " + gameStateFile);
var bf = new BinaryFormatter();
var file = File.Create(gameStateFile);
var gameState = new GameState();
gameState.Language = Language;
gameState.IsMusicEnabled = IsMusicEnabled;
bf.Serialize(file, gameState);
file.Close();
Logger.LogInfo("[GameManager.Save] Successfully saved game state");
}
public void Load(string gameStateFile)
{
Logger.LogInfo("[GameManager.Load] Loading game state from " + gameStateFile);
if (File.Exists(gameStateFile))
{
var bf = new BinaryFormatter();
var file = File.Open(gameStateFile, FileMode.Open);
var gameState = (GameState)bf.Deserialize(file);
file.Close();
Language = gameState.Language;
IsMusicEnabled = gameState.IsMusicEnabled;
}
Logger.LogInfo("[GameManager.Load] Successfully loaded game state");
}
[Serializable]
class GameState {
public GameLanguage Language;
public bool IsMusicEnabled;
}
}
感谢任何提示!
【问题讨论】:
-
感觉是相机问题。您的游戏管理器是否以某种方式链接到相机?你说游戏管理器不会在场景中被破坏,但它所指的任何东西都会被破坏,除非它也被标记为
DontDestroyOnLoad -
@IvayloSlavov 感谢您的意见。我添加了我的 GameManager 类的代码。我在那里没有引用任何相机,只是一些枚举、字符串和布尔值。但是当 GameManager 初始化时,我从 gamestate.dat 文件中加载了一些设置(参见代码)。
-
你的代码看起来很简单。由于我没有尝试过桌面模式以外的其他模式,我可以建议您通过一些实验来找到问题。首先尝试查看禁用序列化逻辑是否会改变任何内容。也许有序列化异常会破坏其余代码?另外,请尝试更改
Awake()中的 GameManager 初始化,而不是Start()。一步一步地做这些,而不是一次,我们需要看看真正导致问题的原因。在这里和那里记录将有助于确定代码停止工作的位置。 -
@IvayloSlavov 好建议。今晚将尝试并报告成功/失败。
标签: unity3d