Forum begins after the advertisement:


[Part 7] Game Manager disappear after game load

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 7] Game Manager disappear after game load

Viewing 8 posts - 1 through 8 (of 8 total)
  • Author
    Posts
  • #19780
    Tú Hoàng Anh
    Level 2
    Participant
    Helpful?
    Up
    0
    ::

    My Game Manager just disappear from the button after i start the game. When i try to add it back in Play Mode, the death screen UI does not turn off, only the scene faded run

    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class GameManager : MonoBehaviour
    {
        public string Transitionfrom;
    
        public Vector2 PlatformrespawnPoint;
        public Vector2 respawnAfterDeath;
        [SerializeField] LightSpot lightSpot;
    
        public GameObject Shade;
        public static GameManager Instance { get; private set; }
        private void Awake()
        {
            SaveData.saveinstance.Instantiate();
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
            }
            else
            {
                Instance = this;
            }
            if (PlayerController.Instance == null)
            {
                if (PlayerController.Instance.respawnMana)
                {
                    SaveData.saveinstance.LoadShadeData();
                    if (SaveData.saveinstance.scenewithShade == UnityEngine.SceneManagement.SceneManager.GetActiveScene().name || SaveData.saveinstance.scenewithShade == "")
                    {
                        Instantiate(Shade, SaveData.saveinstance.shadePos, SaveData.saveinstance.shadeRotation);
                    }
                }
            }
            SaveScene();
            DontDestroyOnLoad(gameObject);
            lightSpot = FindObjectOfType<LightSpot>();
        }
    
        public void SaveScene()
        {
            string currentSceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
            SaveData.saveinstance.sceneNames.Add(currentSceneName);
        }
    
        public void respawnPlayer()
        {
            SaveData.saveinstance.LoadLightSpot();
            if (SaveData.saveinstance.spotSceneName != null)
            {
                SceneManager.LoadScene(SaveData.saveinstance.spotSceneName);
            }
            if (SaveData.saveinstance.lightPos != null)
            {
                respawnAfterDeath = SaveData.saveinstance.lightPos;
            }
            else
            {
                respawnAfterDeath = PlatformrespawnPoint;
            }
            PlayerController.Instance.transform.position = respawnAfterDeath;
            StartCoroutine(UIManager.Instance.DeactivateDeathScreen());
            PlayerController.Instance.Respawn();
        }
    }

    Here is the Game manager script

    #19781
    Terence
    Level 32
    Keymaster
    Helpful?
    Up
    0
    ::

    I’ll have to look at your project more closely to figure this out, but you have a mistake here:

        if (PlayerController.Instance == null)
        if (PlayerController.Instance != null)
        {
            if (PlayerController.Instance.respawnMana)
            {
                SaveData.saveinstance.LoadShadeData();
                if (SaveData.saveinstance.scenewithShade == UnityEngine.SceneManagement.SceneManager.GetActiveScene().name || SaveData.saveinstance.scenewithShade == "")
                {
                    Instantiate(Shade, SaveData.saveinstance.shadePos, SaveData.saveinstance.shadeRotation);
                }
            }
        }

    Also, at the start of Awake(), add a return to prevent code from running if the GameObject is already destroyed.

    private void Awake()
    {
        SaveData.saveinstance.Instantiate();
    
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return; // stop executing on the object that's about to be destroyed
        }
        ...

    Let me know if this fixes things.

    #19782
    Tú Hoàng Anh
    Level 2
    Participant
    Helpful?
    Up
    0
    ::

    The problem with the Game Manager has been fixed, but when i press respawn button the shade disappear immediately and the player stuck in halfmana mode

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Shade : Enemy
    {
        [SerializeField] private float chaseRange;
        [SerializeField] private float stunDuration;
        float timer;
        public static Shade Instance;
    
        private void Awake()
        {
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
            }
            else
            {
                Instance = this;
            }
            SaveData.saveinstance.SaveShadeData();
        }
        protected override void Start()
        {
            base.Start();
            ChangeState(EnemyStates.Shade_Idle);
        }
        protected override void Update()
        {
            base.Update();
            if (!PlayerController.Instance.pState.alive)
            {
                ChangeState(EnemyStates.Shade_Idle);
            }
        }
    
        protected override void UpdateEnemyStates()
        {
            float _dist = Vector2.Distance(transform.position, PlayerController.Instance.transform.position);
            switch (GetCurrentEnemyStates)
            {
                case EnemyStates.Shade_Idle:
                    rb.velocity = new Vector2(0, 0);
                    if (_dist < chaseRange)
                    {
                        ChangeState(EnemyStates.Shade_Chase);
                    }
                    break;
    
                case EnemyStates.Shade_Chase:
                    rb.MovePosition(Vector2.MoveTowards(transform.position, PlayerController.Instance.transform.position, speed * Time.deltaTime));
                    FlipShade();
                    if (_dist > chaseRange)
                    {
                        ChangeState(EnemyStates.Shade_Idle);
                    }
                    break;
    
                case EnemyStates.Shade_Stun:
                    timer += Time.deltaTime;
                    if (timer > stunDuration)
                    {
                        ChangeState(EnemyStates.Shade_Chase);
                        timer = 0;
                    }
                    break;
    
                case EnemyStates.Shade_Died:
                    Death(Random.Range(5, 10));
                    break;
            }
        }
    
        protected override void Death(float _destroyTime)
        {
            rb.gravityScale = 1;
            base.Death(_destroyTime);
        }
        public override void EnemyHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
        {
            base.EnemyHit(_damageDone, _hitDirection, _hitForce);
            if (health > 0)
            {
                ChangeState(EnemyStates.Shade_Stun);
            }
            else
            {
                ChangeState(EnemyStates.Shade_Died);
            }
        }
    
        protected override void ChangeCurrentAnim()
        {
            if (GetCurrentEnemyStates == EnemyStates.Shade_Idle)
            {
                anim.Play("idle");
            }
            anim.SetBool("Walking", GetCurrentEnemyStates == EnemyStates.Shade_Chase);
            anim.SetBool("takeDamage", GetCurrentEnemyStates == EnemyStates.Shade_Stun);
    
            if (GetCurrentEnemyStates == EnemyStates.Shade_Died)
            {
                anim.SetTrigger("Death");
                SaveData.saveinstance.SavePlayerData();
                Destroy(gameObject, 0.5f);
                PlayerController.Instance.RestoreMana();
            }
        }
        protected override void Attack()
        {
            PlayerController.Instance.TakeDamage(damage);
        }
        void FlipShade()
        {
            sr.flipX = PlayerController.Instance.transform.position.x < transform.position.x;
        }
    }

    Here is the Shade.cs

    #19783
    Sean Ng
    Level 8
    Moderator
    Helpful?
    Up
    0
    ::

    Looking at the shade script alone I don’t see how it would cause a problem, but from what you describe it seems the shade never died but removed from scene which is why the player is stuck in half mana.

    I need more information to know whats happening, when you click respawn did SceneManager.LoadScene() run, if it did it will explain why the shade was removed and I need to look at GameManager.cs and SaveData.cs.

    #19784
    Tú Hoàng Anh
    Level 2
    Participant
    Helpful?
    Up
    0
    ::

    Here is the GameManager.cs

    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class GameManager : MonoBehaviour
    {
        public string Transitionfrom;
    
        public Vector2 PlatformrespawnPoint;
        public Vector2 respawnAfterDeath;
        [SerializeField] LightSpot lightSpot;
    
        public GameObject Shade;
        public static GameManager Instance { get; private set; }
        private void Awake()
        {
            SaveData.saveinstance.Instantiate();
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
                return;
            }
            else
            {
                Instance = this;
            }
            if (PlayerController.Instance != null)
            {
                if (PlayerController.Instance.respawnMana)
                {
                    SaveData.saveinstance.LoadShadeData();
                    if (SaveData.saveinstance.scenewithShade == UnityEngine.SceneManagement.SceneManager.GetActiveScene().name || SaveData.saveinstance.scenewithShade == "")
                    {
                        Instantiate(Shade, SaveData.saveinstance.shadePos, SaveData.saveinstance.shadeRotation);
                    }
                }
            }
            SaveScene();
            DontDestroyOnLoad(gameObject);
            lightSpot = FindObjectOfType<LightSpot>();
        }
    
        public void SaveScene()
        {
            string currentSceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
            SaveData.saveinstance.sceneNames.Add(currentSceneName);
        }
    
        public void respawnPlayer()
        {
            SaveData.saveinstance.LoadLightSpot();
            if (SaveData.saveinstance.spotSceneName != null)
            {
                SceneManager.LoadScene(SaveData.saveinstance.spotSceneName);
            }
            if (SaveData.saveinstance.lightPos != null)
            {
                respawnAfterDeath = SaveData.saveinstance.lightPos;
            }
            else
            {
                respawnAfterDeath = PlatformrespawnPoint;
            }
            PlayerController.Instance.transform.position = respawnAfterDeath;
            StartCoroutine(UIManager.Instance.DeactivateDeathScreen());
            PlayerController.Instance.Respawn();
        }
    }

    And Here is the SaveData.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System.IO;
    using UnityEngine.SceneManagement;
    
    
    [System.Serializable]
    public struct SaveData
    {
        public static SaveData saveinstance;
    
        public HashSet<string> sceneNames;
    
        public string spotSceneName;
        public Vector2 lightPos;
    
        public int playerHealth;
        public float playerMana;
        public bool playerRespawnMana;
        public Vector2 playerPosition;
        public string lastScene;
    
        public Vector2 shadePos;
        public string scenewithShade;
        public Quaternion shadeRotation;
        public void Instantiate()
        {
            if (!File.Exists(Application.persistentDataPath + "/save.light.dat"))
            {
                BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.light.dat"));
            }
            if (!File.Exists(Application.persistentDataPath + "/save.player.dat"))
            {
                BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.player.dat"));
            }
            if (!File.Exists(Application.persistentDataPath + "/save.shade.dat"))
            {
                BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.shade.dat"));
            }
            if (sceneNames == null)
            {
                sceneNames = new HashSet<string>();
            }
        }
    
        public void SavedLightSpot()
        {
            using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.light.dat")))
            {
                writer.Write(spotSceneName);
                writer.Write(lightPos.x);
                writer.Write(lightPos.y);
            }
        }
        public void LoadLightSpot()
        {
            if (File.Exists(Application.persistentDataPath + "/save.light.dat"))
            {
                using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.light.dat")))
                {
                    spotSceneName = reader.ReadString();
                    lightPos.x = reader.ReadSingle();
                    lightPos.y = reader.ReadSingle();
                }
            }
        }
        public void SavePlayerData()
        {
            using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.player.dat")))
            {
                playerHealth = PlayerController.Instance.Health;
                writer.Write(playerHealth);
                playerMana = PlayerController.Instance.Mana;
                writer.Write(playerMana);
                playerRespawnMana = PlayerController.Instance.respawnMana;
                writer.Write(playerRespawnMana);
    
                playerPosition = PlayerController.Instance.transform.position;
                writer.Write(playerPosition.x);
                writer.Write(playerPosition.y);
                lastScene = SceneManager.GetActiveScene().name;
                writer.Write(lastScene);
            }
        }
        public void LoadPlayerData()
        {
            if (File.Exists(Application.persistentDataPath + "/save.player.dat"))
            {
                using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.player.dat")))
                {
                    playerHealth = reader.ReadInt32();
                    playerMana = reader.ReadSingle();
                    playerRespawnMana = reader.ReadBoolean();
                    playerPosition.x = reader.ReadSingle();
                    playerPosition.y = reader.ReadSingle();
                    lastScene = reader.ReadString();
    
                    SceneManager.LoadScene(lastScene);
                    PlayerController.Instance.transform.position = playerPosition;
                    PlayerController.Instance.Health = playerHealth;
                    PlayerController.Instance.Mana = playerMana;
                    PlayerController.Instance.respawnMana = playerRespawnMana;
                }
            }
            else
            {
                Debug.Log("No save file found for player data.");
                PlayerController.Instance.Health = PlayerController.Instance.maxHealth;
                PlayerController.Instance.Mana = 0.5f;
                PlayerController.Instance.respawnMana = false;
            }
        }
        public void SaveShadeData()
        {
            using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.shade.dat")))
            {
                scenewithShade = SceneManager.GetActiveScene().name;
                shadePos = Shade.Instance.transform.position;
                shadeRotation = Shade.Instance.transform.rotation;
    
                writer.Write(scenewithShade);
                writer.Write(shadePos.x);
                writer.Write(shadePos.y);
                writer.Write(shadeRotation.x);
                writer.Write(shadeRotation.y);
                writer.Write(shadeRotation.z);
                writer.Write(shadeRotation.w);
            }
        }
        public void LoadShadeData()
        {
            if (File.Exists(Application.persistentDataPath + "/save.shade.data"))
            {
                using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.shade.dat")))
                {
                    scenewithShade = reader.ReadString();
                    shadePos.x = reader.ReadSingle();
                    shadePos.y = reader.ReadSingle();
                    float shadeRotationx = reader.ReadSingle();
                    float shadeRotationy = reader.ReadSingle();
                    float shadeRotationz = reader.ReadSingle();
                    float shadeRotationw = reader.ReadSingle();
                    shadeRotation = new Quaternion(shadeRotationx, shadeRotationy, shadeRotationz, shadeRotationw);
                }
            }
            else
            {
                Debug.Log("No save file found for shade data.");
            }
        }
    }
    #19785
    Sean Ng
    Level 8
    Moderator
    Helpful?
    Up
    0
    ::

    The problem is found in your GameManager.cs, when you respawn you will load scene even if it is the same it will refresh the scene, this causes your shade to dissapear as it is not part of the original scene, as your GameManager.cs Awake() function is only called once at the start when the game begins the shade data is never loaded.

    To fix this We’ll move it down and create a new function that load shade data everytime the scene change.

    
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class GameManager : MonoBehaviour
    {
        public string Transitionfrom;
    
        public Vector2 PlatformrespawnPoint;
        public Vector2 respawnAfterDeath;
        [SerializeField] LightSpot lightSpot;
    
        public GameObject Shade;
        public static GameManager Instance { get; private set; }
        private void Awake()
        {
            SaveData.saveinstance.Instantiate();
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
                return;
            }
            else
            {
                Instance = this;
            }
            if (PlayerController.Instance != null)
            {
                if (PlayerController.Instance.respawnMana)
                {
                    SaveData.saveinstance.LoadShadeData();
                    if (SaveData.saveinstance.scenewithShade == UnityEngine.SceneManagement.SceneManager.GetActiveScene().name || SaveData.saveinstance.scenewithShade == "")
                    {
                        Instantiate(Shade, SaveData.saveinstance.shadePos, SaveData.saveinstance.shadeRotation);
                    }
                }
            }
            SaveScene();
            DontDestroyOnLoad(gameObject);
            lightSpot = FindObjectOfType<LightSpot>();
        }
    
        public void SaveScene()
        {
            string currentSceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
            SaveData.saveinstance.sceneNames.Add(currentSceneName);
        }
    
        public void respawnPlayer()
        {
            SaveData.saveinstance.LoadLightSpot();
            if (SaveData.saveinstance.spotSceneName != null)
            {
                SceneManager.LoadScene(SaveData.saveinstance.spotSceneName);
            }
            if (SaveData.saveinstance.lightPos != null)
            {
                respawnAfterDeath = SaveData.saveinstance.lightPos;
            }
            else
            {
                respawnAfterDeath = PlatformrespawnPoint;
            }
            PlayerController.Instance.transform.position = respawnAfterDeath;
            StartCoroutine(UIManager.Instance.DeactivateDeathScreen());
            PlayerController.Instance.Respawn();
        }
    
        private void OnEnable()
        {
            SceneManager.sceneLoaded += OnSceneLoaded;
        }
    
        private void OnDisable()
        {
            SceneManager.sceneLoaded -= OnSceneLoaded;
        }
    
        private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
        {
            if (PlayerController.Instance != null)
            {
                if (PlayerController.Instance.respawnMana)
                {
                    SaveData.saveinstance.LoadShadeData();
                    if (SaveData.saveinstance.scenewithShade == UnityEngine.SceneManagement.SceneManager.GetActiveScene().name || SaveData.saveinstance.scenewithShade == "")
                    {
                        Instantiate(Shade, SaveData.saveinstance.shadePos, SaveData.saveinstance.shadeRotation);
                    }
                }
            }
            SaveScene();
            DontDestroyOnLoad(gameObject);
            lightSpot = FindObjectOfType<LightSpot>();
        }
    }
    
    #19786
    Tú Hoàng Anh
    Level 2
    Participant
    Helpful?
    Up
    0
    ::

    The Shade is now display but when i kill it and then restart the game, the player is still at halfmana state but the shade is gone

    #19787
    Sean Ng
    Level 8
    Moderator
    Helpful?
    Up
    1
    ::

    when you kill the shade does your mana restore? If the only problem is when restart the player go back to half mana, to fix it you just need to rearrange the code at your ChangeCurrentAnim() of Shade.cs

    protected override void ChangeCurrentAnim()
        {
            if (GetCurrentEnemyStates == EnemyStates.Shade_Idle)
            {
                anim.Play("idle");
            }
            anim.SetBool("Walking", GetCurrentEnemyStates == EnemyStates.Shade_Chase);
            anim.SetBool("takeDamage", GetCurrentEnemyStates == EnemyStates.Shade_Stun);
    
            if (GetCurrentEnemyStates == EnemyStates.Shade_Died)
            {
                anim.SetTrigger("Death");
                PlayerController.Instance.RestoreMana();
                SaveData.saveinstance.SavePlayerData();
                Destroy(gameObject, 0.5f);
            }
        }

    You want the RestoreMana() to go first before SavePlayerData() otherwise it won’t save the player mana state.

    has upvoted this post.
Viewing 8 posts - 1 through 8 (of 8 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: