场景在 Unity 中加载但无法加载场景 Android
Posted
技术标签:
【中文标题】场景在 Unity 中加载但无法加载场景 Android【英文标题】:Scene loads in Unity but unable to Load Scene Android 【发布时间】:2019-10-14 00:08:09 【问题描述】:我的游戏在 Unity 中运行良好,但是当我导出 apk tp android Mobile 2nd Scene 时无法正确加载并且无法运行。
请看图。这是第二个场景,未正确加载,运行按钮无法正常工作,在统一播放模式下运行良好。
enter image description here
代码如下
SCENE 1 CODE#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
#if UNITY_ANALYTICS
using UnityEngine.Analytics;
#endif
#if UNITY_PURCHASING
using UnityEngine.Purchasing;
#endif
public class StartButton : MonoBehaviour
public void StartGame()
if (PlayerData.instance.ftueLevel == 0)
PlayerData.instance.ftueLevel = 1;
PlayerData.instance.Save();
#if UNITY_ANALYTICS
AnalyticsEvent.FirstInteraction("start_button_pressed");
#endif
#if UNITY_PURCHASING
var module = StandardPurchasingModule.Instance();
#endif
SceneManager.LoadScene("main");
SCENE 2 CODE#
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
#if UNITY_ANALYTICS
using UnityEngine.Analytics;
#endif
/// <summary>
/// State pushed on the GameManager during the Loadout, when player select player, theme and accessories
/// Take care of init the UI, load all the data used for it etc.
/// </summary>
public class LoadoutState : AState
public Canvas inventoryCanvas;
[Header("Char UI")]
public Text charNameDisplay;
public RectTransform charSelect;
public Transform charPosition;
[Header("Theme UI")]
public Text themeNameDisplay;
public RectTransform themeSelect;
public Image themeIcon;
[Header("PowerUp UI")]
public RectTransform powerupSelect;
public Image powerupIcon;
public Text powerupCount;
public Sprite noItemIcon;
[Header("Accessory UI")]
public RectTransform accessoriesSelector;
public Text accesoryNameDisplay;
public Image accessoryIconDisplay;
[Header("Other Data")]
public Leaderboard leaderboard;
public MissionUI missionPopup;
public Button runButton;
public GameObject tutorialBlocker;
public GameObject tutorialPrompt;
public MeshFilter skyMeshFilter;
public MeshFilter UIGroundFilter;
public AudioClip menuTheme;
[Header("Prefabs")]
public ConsumableIcon consumableIcon;
Consumable.ConsumableType m_PowerupToUse = Consumable.ConsumableType.NONE;
protected GameObject m_Character;
protected List<int> m_OwnedAccesories = new List<int>();
protected int m_UsedAccessory = -1;
protected int m_UsedPowerupIndex;
protected bool m_IsLoadingCharacter;
protected Modifier m_CurrentModifier = new Modifier();
protected const float k_CharacterRotationSpeed = 45f;
protected const string k_ShopSceneName = "shop";
protected const float k_OwnedAccessoriesCharacterOffset = -0.1f;
protected int k_UILayer;
protected readonly Quaternion k_FlippedYAxisRotation = Quaternion.Euler (0f, 180f, 0f);
public override void Enter(AState from)
tutorialBlocker.SetActive(!PlayerData.instance.tutorialDone);
tutorialPrompt.SetActive(false);
inventoryCanvas.gameObject.SetActive(true);
missionPopup.gameObject.SetActive(false);
charNameDisplay.text = "";
themeNameDisplay.text = "";
k_UILayer = LayerMask.NameToLayer("UI");
skyMeshFilter.gameObject.SetActive(true);
UIGroundFilter.gameObject.SetActive(true);
// Reseting the global blinking value. Can happen if the game unexpectedly exited while still blinking
Shader.SetGlobalFloat("_BlinkingValue", 0.0f);
if (MusicPlayer.instance.GetStem(0) != menuTheme)
MusicPlayer.instance.SetStem(0, menuTheme);
StartCoroutine(MusicPlayer.instance.RestartAllStems());
runButton.interactable = false;
runButton.GetComponentInChildren<Text>().text = "Loading...";
if(m_PowerupToUse != Consumable.ConsumableType.NONE)
//if we come back from a run and we don't have any more of the powerup we wanted to use, we reset the powerup to use to NONE
if (!PlayerData.instance.consumables.ContainsKey(m_PowerupToUse) || PlayerData.instance.consumables[m_PowerupToUse] == 0)
m_PowerupToUse = Consumable.ConsumableType.NONE;
Refresh();
public override void Exit(AState to)
missionPopup.gameObject.SetActive(false);
inventoryCanvas.gameObject.SetActive(false);
if (m_Character != null) Addressables.ReleaseInstance(m_Character);
GameState gs = to as GameState;
skyMeshFilter.gameObject.SetActive(false);
UIGroundFilter.gameObject.SetActive(false);
if (gs != null)
gs.currentModifier = m_CurrentModifier;
// We reset the modifier to a default one, for next run (if a new modifier is applied, it will replace this default one before the run starts)
m_CurrentModifier = new Modifier();
if (m_PowerupToUse != Consumable.ConsumableType.NONE)
PlayerData.instance.Consume(m_PowerupToUse);
Consumable inv = Instantiate(ConsumableDatabase.GetConsumbale(m_PowerupToUse));
inv.gameObject.SetActive(false);
gs.trackManager.characterController.inventory = inv;
public void Refresh()
PopulatePowerup();
StartCoroutine(PopulateCharacters());
StartCoroutine(PopulateTheme());
public override string GetName()
return "Loadout";
public override void Tick()
if (!runButton.interactable)
bool interactable = ThemeDatabase.loaded && CharacterDatabase.loaded;
if(interactable)
runButton.interactable = true;
runButton.GetComponentInChildren<Text>().text = "Run!";
//we can always enabled, as the parent will be disabled if tutorial is already done
tutorialPrompt.SetActive(true);
if(m_Character != null)
m_Character.transform.Rotate(0, k_CharacterRotationSpeed * Time.deltaTime, 0, Space.Self);
charSelect.gameObject.SetActive(PlayerData.instance.characters.Count > 1);
themeSelect.gameObject.SetActive(PlayerData.instance.themes.Count > 1);
public void GoToStore()
UnityEngine.SceneManagement.SceneManager.LoadScene(k_ShopSceneName, UnityEngine.SceneManagement.LoadSceneMode.Additive);
public void ChangeCharacter(int dir)
PlayerData.instance.usedCharacter += dir;
if (PlayerData.instance.usedCharacter >= PlayerData.instance.characters.Count)
PlayerData.instance.usedCharacter = 0;
else if(PlayerData.instance.usedCharacter < 0)
PlayerData.instance.usedCharacter = PlayerData.instance.characters.Count-1;
StartCoroutine(PopulateCharacters());
public void ChangeAccessory(int dir)
m_UsedAccessory += dir;
if (m_UsedAccessory >= m_OwnedAccesories.Count)
m_UsedAccessory = -1;
else if (m_UsedAccessory < -1)
m_UsedAccessory = m_OwnedAccesories.Count-1;
if (m_UsedAccessory != -1)
PlayerData.instance.usedAccessory = m_OwnedAccesories[m_UsedAccessory];
else
PlayerData.instance.usedAccessory = -1;
SetupAccessory();
public void ChangeTheme(int dir)
PlayerData.instance.usedTheme += dir;
if (PlayerData.instance.usedTheme >= PlayerData.instance.themes.Count)
PlayerData.instance.usedTheme = 0;
else if (PlayerData.instance.usedTheme < 0)
PlayerData.instance.usedTheme = PlayerData.instance.themes.Count - 1;
StartCoroutine(PopulateTheme());
public IEnumerator PopulateTheme()
ThemeData t = null;
while (t == null)
t = ThemeDatabase.GetThemeData(PlayerData.instance.themes[PlayerData.instance.usedTheme]);
yield return null;
themeNameDisplay.text = t.themeName;
themeIcon.sprite = t.themeIcon;
skyMeshFilter.sharedMesh = t.skyMesh;
UIGroundFilter.sharedMesh = t.UIGroundMesh;
public IEnumerator PopulateCharacters()
accessoriesSelector.gameObject.SetActive(false);
PlayerData.instance.usedAccessory = -1;
m_UsedAccessory = -1;
if (!m_IsLoadingCharacter)
m_IsLoadingCharacter = true;
GameObject newChar = null;
while (newChar == null)
Character c = CharacterDatabase.GetCharacter(PlayerData.instance.characters[PlayerData.instance.usedCharacter]);
if (c != null)
m_OwnedAccesories.Clear();
for (int i = 0; i < c.accessories.Length; ++i)
// Check which accessories we own.
string compoundName = c.characterName + ":" + c.accessories[i].accessoryName;
if (PlayerData.instance.characterAccessories.Contains(compoundName))
m_OwnedAccesories.Add(i);
Vector3 pos = charPosition.transform.position;
if (m_OwnedAccesories.Count > 0)
pos.x = k_OwnedAccessoriesCharacterOffset;
else
pos.x = 0.0f;
charPosition.transform.position = pos;
accessoriesSelector.gameObject.SetActive(m_OwnedAccesories.Count > 0);
AsyncOperationHandle op = Addressables.InstantiateAsync(c.characterName);
yield return op;
if (op.Result == null || !(op.Result is GameObject))
Debug.LogWarning(string.Format("Unable to load character 0.", c.characterName));
yield break;
newChar = op.Result as GameObject;
Helpers.SetRendererLayerRecursive(newChar, k_UILayer);
newChar.transform.SetParent(charPosition, false);
newChar.transform.rotation = k_FlippedYAxisRotation;
if (m_Character != null)
Addressables.ReleaseInstance(m_Character);
m_Character = newChar;
charNameDisplay.text = c.characterName;
m_Character.transform.localPosition = Vector3.right * 1000;
//animator will take a frame to initialize, during which the character will be in a T-pose.
//So we move the character off screen, wait that initialised frame, then move the character back in place.
//That avoid an ugly "T-pose" flash time
yield return new WaitForEndOfFrame();
m_Character.transform.localPosition = Vector3.zero;
SetupAccessory();
else
yield return new WaitForSeconds(1.0f);
m_IsLoadingCharacter = false;
void SetupAccessory()
Character c = m_Character.GetComponent<Character>();
c.SetupAccesory(PlayerData.instance.usedAccessory);
if (PlayerData.instance.usedAccessory == -1)
accesoryNameDisplay.text = "None";
accessoryIconDisplay.enabled = false;
else
accessoryIconDisplay.enabled = true;
accesoryNameDisplay.text = c.accessories[PlayerData.instance.usedAccessory].accessoryName;
accessoryIconDisplay.sprite = c.accessories[PlayerData.instance.usedAccessory].accessoryIcon;
void PopulatePowerup()
powerupIcon.gameObject.SetActive(true);
if (PlayerData.instance.consumables.Count > 0)
Consumable c = ConsumableDatabase.GetConsumbale(m_PowerupToUse);
powerupSelect.gameObject.SetActive(true);
if (c != null)
powerupIcon.sprite = c.icon;
powerupCount.text = PlayerData.instance.consumables[m_PowerupToUse].ToString();
else
powerupIcon.sprite = noItemIcon;
powerupCount.text = "";
else
powerupSelect.gameObject.SetActive(false);
public void ChangeConsumable(int dir)
bool found = false;
do
m_UsedPowerupIndex += dir;
if(m_UsedPowerupIndex >= (int)Consumable.ConsumableType.MAX_COUNT)
m_UsedPowerupIndex = 0;
else if(m_UsedPowerupIndex < 0)
m_UsedPowerupIndex = (int)Consumable.ConsumableType.MAX_COUNT - 1;
int count = 0;
if(PlayerData.instance.consumables.TryGetValue((Consumable.ConsumableType)m_UsedPowerupIndex, out count) && count > 0)
found = true;
while (m_UsedPowerupIndex != 0 && !found);
m_PowerupToUse = (Consumable.ConsumableType)m_UsedPowerupIndex;
PopulatePowerup();
public void UnequipPowerup()
m_PowerupToUse = Consumable.ConsumableType.NONE;
public void SetModifier(Modifier modifier)
m_CurrentModifier = modifier;
public void StartGame()
if (PlayerData.instance.tutorialDone)
if (PlayerData.instance.ftueLevel == 1)
PlayerData.instance.ftueLevel = 2;
PlayerData.instance.Save();
manager.SwitchState("Game");
public void Openleaderboard()
leaderboard.displayPlayer = false;
leaderboard.forcePlayerDisplay = false;
leaderboard.Open();
【问题讨论】:
【参考方案1】:这个问题太模糊了,不过,我想到了一些事情: 1. 您是否使用过时版本的 Android SDK 进行测试,然后在手机上运行更新的 Android 版本?
情况是否相反?
您的设备是否有足够的处理能力和 GPU 能力来运行相关场景?
如果您发布一些日志和/或图片会很有帮助。
【讨论】:
您好,感谢您的帮助,请查看我在上面发布的场景 1 和场景 2 代码的代码。期待。谢谢【参考方案2】:由于缺乏信息,我只能建议您至少创建仅包含第二个场景(您无法加载的场景)的构建并查看结果。
请填写其他信息(场景加载代码、您的第一个场景层次结构作为屏幕截图等),以便其他人可以更好地帮助您。
【讨论】:
您好,感谢您的帮助,请查看我在上面发布的场景 1 和场景 2 代码的代码。期待。谢谢【参考方案3】:同样的问题。
我坚持使用 Endless Runner 代码,它是资产商店中的示例代码。 (https://assetstore.unity.com/packages/essentials/tutorial-projects/endless-runner-sample-game-87901)
我发现 ThemeDatabase.loaded 和 CharacterDatabase.loaded 在 Unity 中都是 true,但在 Android 中是 false。
因此,在 Android 中,interactable 将是错误的。 (bool interactable = ThemeDatabase.loaded && CharacterDatabase.loaded;)
CharacterDatabase.cs 如下。
using UnityEngine;
using UnityEngine.AddressableAssets;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// This allows us to store a database of all characters currently in the bundles, indexed by name.
/// </summary>
public class CharacterDatabase
static protected Dictionary<string, Character> m_CharactersDict;
static public Dictionary<string, Character> dictionary get return m_CharactersDict;
static protected bool m_Loaded = false;
static public bool loaded get return m_Loaded;
static public Character GetCharacter(string type)
Character c;
if (m_CharactersDict == null || !m_CharactersDict.TryGetValue(type, out c))
return null;
return c;
static public IEnumerator LoadDatabase()
if (m_CharactersDict == null)
m_CharactersDict = new Dictionary<string, Character>();
yield return Addressables.LoadAssetsAsync<GameObject>("characters", op =>
Character c = op.GetComponent<Character>();
if (c != null)
m_CharactersDict.Add(c.characterName, c);
);
m_Loaded = true;
【讨论】:
那么,你在那里做了什么,与我的代码没有什么不同?但即使在 Unity 中也没有运行。以上是关于场景在 Unity 中加载但无法加载场景 Android的主要内容,如果未能解决你的问题,请参考以下文章