- Home /
Very strange bug that appears only in a build. I am desperate
Unity version 5.6.3f1
In my game there is a class named GameManager that initializes the game and creates player and his weapons. But recently a strange bug appeared. When you die and hit Restart(reloads the current scene) the player and his weapons are not spawning, UI not working and enemies are not spawning. This bug only appears in a build, in the editor all works great. I tried to create my own class for logging to a text file in a build (because there is no console in a build)
using System.IO;
namespace Astro
{
public static class FileLogger
{
private const string PATH = log.txt;
private static FileStream fileStream;
static FileLogger()
{
fileStream = File.Create(PATH);
}
public static void Log(object message)
{
using (StreamWriter streamWriter = new StreamWriter(fileStream))
{
streamWriter.WriteLine(message);
}
}
}
}
I added FileLogger.Log() calls to the beginning of some functions. But after I added these lines this bugs started appearing in the beggining of the game (not only after restart), and even in the editor. How is that possible It just writes strings to a file? Anyways, I checked the log file and then reverted adding these log lines. According to the log file, the Awake() method is called, but the Start() is not. I have no idea why.
Upd
I tried to wrap all Unity methods(Start, Update, OnEnable, OnDisable) in GameManager in try catch and log exceptions using file logger. After long hours of logging and building I found that problem was because two GameObject fields (pauseMenu and dieMenu) that were set in inspector somehow were null. I added some code to find these objects and assign to that variables in case they are null. I made a new build, launched it and... I got a NullReferenceException somewhere in Start. I spent so much time trying to fix exception in Awake only to discover an exception in Start. I am afraid that when I will fix it, another problem will appear. I don't understand why game behaves differently in editor and in build. I am desperate. I have no idea how to deal with it. Please help me!
Game manager class
using System;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
using Astro.CamerEffects;
using Astro.InputManager;
using Astro.ModuleObjects;
using Astro.Player;
using Astro.Scriptable;
using Astro.Scriptable.Heroes;
using Astro.Tools;
using Astro.UI;
using Astro.Weapon;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;
namespace Astro.Managers
{
public class GameManager : SingletonOneScene<GameManager>
{
private const float DIALOGUE_LOCK_TIME = 0.25f;
private const int DEMO_MAX_LEVEL = 2;
public const bool IS_DEMO = false;
[Header("Start settings")] [SerializeField] private Vector3 startPosition;
[Header("UI settings")] [SerializeField] private GameObject pauseMenu;
[SerializeField] private GameObject dieMenu;
[SerializeField] private string previousScene;
[Header("Heroes settings")] [SerializeField] private HeroesInfo heroes;
[Header("Levels setting")] [SerializeField] private int[] meatIndex;
public int MeatIndex
{
get { return meatIndex[CurrentLevel]; }
}
[Header("Module objects")] [SerializeField] private GameObject weaponModuleObject;
public GameObject WeaponModuleObject
{
get { return weaponModuleObject; }
}
[SerializeField] private WeaponModule weaponModule;
public WeaponModule WeaponModule
{
get { return weaponModule; }
}
public GameObject HeroInstance { get; private set; }
public PlayerController PlayerControllerInstance { get; private set; }
public bool IsPaused { get; private set; }
public bool IsDie { get; private set; }
public bool IsAblityDialogueLocked
{
get
{
return Time.time - dialogueEndTime <= DIALOGUE_LOCK_TIME;
}
}
public int CurrentLevel { get; private set; }
private bool isBackgroundEnd;
private bool isHardMode = false;
private int previousPauseToggleFrame = -1;
private int frameCount = 0;
private float dialogueEndTime = -1f;
protected override void Awake()
{
try
{
ScoreManager.Instance.CurrentScore = 0;
base.Awake();
}
catch (Exception e)
{
FileLogger.Log("1 " + e);
}
try
{
if (PlayerLevelSaver.Instance.IsSave)
{
CurrentLevel = PlayerLevelSaver.Instance.Level;
PlayerBonus.Instance.Load();
ScoreManager.Instance.CurrentScore = PlayerLevelSaver.Instance.Score;
}
else
{
PlayerBonus.Instance.Clear();
PlayerLevelSaver.Instance.Clear();
}
}
catch (Exception e)
{
FileLogger.Log("2 " + e);
}
try
{
//To fix the bug when these fields are null in a build
if(pauseMenu == null)
pauseMenu = (GameObject)Resources.FindObjectsOfTypeAll(typeof(GameObject)).Single(x => x.name == "PauseMenu");
if (dieMenu == null)
dieMenu = (GameObject)Resources.FindObjectsOfTypeAll(typeof(GameObject)).Single(x => x.name == "DieMenu");
pauseMenu.SetActive(IsPaused = false);
dieMenu.SetActive(IsDie = false);
}
catch (Exception e)
{
FileLogger.Log("3 " + "pause menu == null: " + (pauseMenu == null).ToString() + " dieMenu == null: " + (dieMenu == null).ToString() + " Ecxeption: " + e);
}
}
protected virtual void Start()
{
try
{
DialogManager.Instance.DisableDialog += OnEndDialog;
DialogManager.Instance.EnableDialog += OnStartDialog;
int weapon1, weapon2, hero;
if (PlayerLevelSaver.Instance.IsSave)
{
weapon1 = PlayerLevelSaver.Instance.Weapon1;
weapon2 = PlayerLevelSaver.Instance.Weapon2;
hero = PlayerLevelSaver.Instance.Hero;
PlayerInfo.Instance.HeroId = hero;
}
else
{
weapon1 = PlayerInfo.Instance.FirstWeaponId;
weapon2 = PlayerInfo.Instance.SecondWeaponId;
hero = PlayerInfo.Instance.HeroId;
StartCoroutine(DialogInvoker(2f, 0));
UIGameManager.Instance.Help();
}
HeroInstance = Instantiate(heroes.Heroes[hero].HeroPrefab, startPosition,
Quaternion.identity);
PlayerControllerInstance = HeroInstance.GetComponent<PlayerController>();
PlayerControllerInstance.Weapon1 =
WeaponInstanceManager.AddWeapon((PlayerControllerInstance.Weapon1Id = weapon1), HeroInstance);
if (weapon2 != -1)
{
PlayerControllerInstance.Weapon2 =
WeaponInstanceManager.AddWeapon((PlayerControllerInstance.Weapon2Id = weapon2), HeroInstance);
}
StartLevel();
}
catch (Exception e)
{
FileLogger.Log("Exception in Start: " + e);
}
}
public void OnPause()
{
Debug.Log("OnPauseCalled");
if (TimeManager.Instance.isDialog)
{
return;
}
if (previousPauseToggleFrame == Time.frameCount) return;
previousPauseToggleFrame = Time.frameCount;
IsPaused = true;
pauseMenu.SetActive(true);
pauseMenu.GetComponent<SwitchButtons>().EnableControll();
TimeManager.Instance.SetPause();
if (MobileControlsManager.HasIntance)
{
MobileControlsManager.Instance.SetPauseButtonActive(false);
}
}
public void OnContinue()
{
if (previousPauseToggleFrame == Time.frameCount) return;
previousPauseToggleFrame = Time.frameCount;
EventSystem.current.SetSelectedGameObject(null);
pauseMenu.GetComponent<SwitchButtons>().DisableControll();
IsPaused = false;
pauseMenu.SetActive(false);
TimeManager.Instance.SetUnpause();
if (MobileControlsManager.HasIntance)
{
MobileControlsManager.Instance.SetPauseButtonActive(true);
}
Debug.Log("OnContinue ended " + "IsPaused: " + IsPaused);
}
public void OnDie()
{
MusicManager.Instance.PlaySound("lose");
ScoreManager.MaxScore = ScoreManager.Instance.CurrentScore;
if(isHardMode)
PlayerLevelSaver.Instance.Clear();
if (BossManager.Instance.IsBossFight)
{
Action dialogEndWaiter = null;
dialogEndWaiter = delegate
{
dieMenu.GetComponent<SwitchButtons>().EnableControll();
dieMenu.SetActive(IsDie = true);
Destroy(HeroInstance);
DialogManager.Instance.DisableDialog -= dialogEndWaiter;
};
DialogManager.Instance.DisableDialog += dialogEndWaiter;
DialogManager.Instance.StartDialog(CurrentLevel, 3);
}
else
{
dieMenu.GetComponent<SwitchButtons>().EnableControll();
dieMenu.SetActive(IsDie = true);
Destroy(HeroInstance);
}
if (MobileControlsManager.HasIntance)
{
MobileControlsManager.Instance.SetPauseButtonActive(false);
}
}
public void OnRestart()
{
SceneLoadManager.LoadScene(SceneManager.GetActiveScene().name);
OnContinue();
}
public void OnExit()
{
SceneLoadManager.LoadScene(previousScene);
OnContinue();
}
public void OnNextLevel()
{
if (IsDie)
{
return;
}
StartCoroutine(GoToNewLevel());
}
public void OnBossKill()
{
if (IsDie)
{
return;
}
PlayerControllerInstance.GodMode = true;
PlayerControllerInstance.IsControlingAbility = false;
if (CurrentLevel < 7)
{
PlayerControllerInstance.IsControlingBonus = true;
}
MusicManager.Instance.PlaySound("win");
StartCoroutine(DialogInvoker(0f, 2));
}
public bool IsLoadingLevel { get; set; }
private IEnumerator GoToNewLevel()
{
if (IS_DEMO && CurrentLevel >= DEMO_MAX_LEVEL)
{
PlayerLevelSaver.Instance.SaveDemoLocked(
CurrentLevel + 1,
PlayerInfo.Instance.HeroId,
PlayerControllerInstance.Weapon1Id,
PlayerControllerInstance.Weapon2Id,
PlayerControllerInstance.Hp,
ScoreManager.Instance.CurrentScore);
SceneLoadManager.LoadScene("DemoEnd");
yield break;
}
PlayerLevelSaver.Instance.Save(
CurrentLevel + 1,
PlayerInfo.Instance.HeroId,
PlayerControllerInstance.Weapon1Id,
PlayerControllerInstance.Weapon2Id,
PlayerControllerInstance.Hp,
ScoreManager.Instance.CurrentScore);
IsLoadingLevel = true;
CameraEffect.Instance.EnableBlick = true;
PlayerControllerInstance.NextLevelAnim();
yield return new WaitForSeconds(6f);
if (CurrentLevel >= 7)
{
//Debug.Log("Game is End");
int currentHero = PlayerLevelSaver.Instance.Hero;
if (currentHero < 3)//Если не Вей Линг
{
int lastUnlockedHero = PlayerPrefs.GetInt("last_unlocked_hero", 0);
if (currentHero + 1 > lastUnlockedHero)
PlayerPrefs.SetInt("last_unlocked_hero", currentHero + 1);
}
else//Если Вей линг
{
}
PlayerLevelSaver.Instance.Clear();
OnExit();
//TODO: GAME END
}
++CurrentLevel;
BossManager.Instance.wasBoss = false;
StartLevel();
PlayerControllerInstance.IsControlingAbility = true;
PlayerControllerInstance.GodMode = false;
IsLoadingLevel = false;
}
private void OnClickBack()
{
if (IsDie)
{
if (IsPaused)
{
EventSystem.current.SetSelectedGameObject(null);
pauseMenu.GetComponent<SwitchButtons>().DisableControll();
pauseMenu.SetActive(IsPaused = false);
}
return;
}
if (IsPaused)
{
OnContinue();
}
}
private void OnClickMenu()
{
Debug.Log("OnClickMenu called " + "IsPaused: " + IsPaused);
if (IsPaused)
{
OnContinue();
}
else
{
OnPause();
}
}
public void OnEndBackground()
{
Debug.Log("OnEndBackground");
if (IsDie)
{
return;
}
isBackgroundEnd = true;
EnemySpawner.Instance.StopSpawn();
StartCoroutine(WaitUntilEnemyDies());
}
private IEnumerator WaitUntilEnemyDies()
{
yield return new WaitWhile(() => EnemySpawner.Instance.IsPatternOrControllerWork ||
EnemySpawner.Instance.IsEnemyOnLevel);
if (IsDie)
{
yield break;
}
BossManager.Instance.CreateBoss(CurrentLevel);
}
private void StartLevel()
{
EnemySpawner.Instance.StartSpawn();
BackgroundManager.Instance.SetBackgroundRandom();
CameraEffect.Instance.EnableBlick = false;
}
private IEnumerator DialogInvoker(float time, int id)
{
yield return new WaitForSeconds(time);
/*if (CurrentLevel == 1)
{
DialogManager.Instance.StartDialog(-1, -1);
}
else
{*/
DialogManager.Instance.StartDialog(CurrentLevel, id);
//}
}
private void OnEndDialog()
{
InputController.Instance.UIBack += OnClickBack;
InputController.Instance.Menu += OnClickMenu;
dialogueEndTime = Time.time;
}
private void OnStartDialog()
{
InputController.Instance.UIBack -= OnClickBack;
InputController.Instance.Menu -= OnClickMenu;
}
public void StopPlayerControlling()
{
PlayerControllerInstance.IsControlingByPlayer = false;
}
public void StartPlayerControlling()
{
PlayerControllerInstance.IsControlingByPlayer = true;
}
protected virtual void OnEnable()
{
try
{
MusicManager.Instance.StartPlayBackgroundLevel();
InputController.Instance.UIBack += OnClickBack;
InputController.Instance.Menu += OnClickMenu;
}
catch (Exception e)
{
FileLogger.Log("Exception in OnEnable: " + e);
}
}
protected virtual void OnDisable()
{
try
{
InputController.Instance.UIBack -= OnClickBack;
InputController.Instance.Menu -= OnClickMenu;
if (MusicManager.CheckExist())
{
MusicManager.Instance.StopPlayBackgroundLevel();
MusicManager.Instance.PlayBackgroundMainMenu();
}
EnemySpawner.Instance.StopSpawn();
}
catch (Exception e)
{
FileLogger.Log("Exception in OnDisable: " + e);
}
}
}
}
Your answer
Follow this Question
Related Questions
Cloud Build fails with Analytics.AnalyticsEvent (2019.2.1f) 1 Answer
Unity Hangs when compiling after the 1st run 2 Answers
Distribute terrain in zones 3 Answers
Sphere disappear after build 0 Answers
Build error 2 Answers