Forum begins after the advertisement:


[Part 7] My Maps cannot update when I quit the game

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 7] My Maps cannot update when I quit the game

Viewing 15 posts - 1 through 15 (of 15 total)
  • Author
    Posts
  • #14853
    Elvin Sim
    Participant

    My maps cannot update when I quit the game, but during the game it is ok

    #14854
    #14855
    #14856
    Elvin Sim
    Participant
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System.IO;
    using UnityEngine.SceneManagement;
    
    [System.Serializable]
    public struct SaveData
    {
        public static SaveData Instance;
    
        //map stuff
        public HashSet<string> sceneNames;
    
        //bench stuff
        public string benchSceneName;
        public Vector2 benchPos;
    
        //player stuff
        public int playerHealth;
        public int playerMaxHealth;
        public int playerHeartShards;
        public float playerMana;
        public int playerManaOrbs;
        public int playerOrbShard;
        public float playerOrb0fill, playerOrb1fill, playerOrb2fill;
        public bool playerHalfMana;
        public Vector2 playerPosition;
        public string lastScene;
    
        public bool playerUnlockedWallJump, playerUnlockedDash, playerUnlockedVarJump;
        public bool playerUnlockedSideCast, playerUnlockedUpCast, playerUnlockedDownCast;
       
        //enemies stuff
        //shade
        public Vector2 shadePos;
        public string sceneWithShade;
        public Quaternion shadeRot;
    
        public void Initialize()
        {
            if(!File.Exists(Application.persistentDataPath + "/save.bench.data")) 
            {
                BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.bench.data"));
            }
    
            if (!File.Exists(Application.persistentDataPath + "/save.player.data"))
            {
                BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.player.data"));
            }
    
            if (!File.Exists(Application.persistentDataPath + "/save.shade.data"))
            {
                BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.shade.data"));
            }
    
            if (sceneNames == null)
            {
                sceneNames = new HashSet<string>();
            }
        }
    
        #region Bench Stuff
        public void SaveBench()
        {
            using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.bench.data")))
            {
                writer.Write(benchSceneName);
                writer.Write(benchPos.x);
                writer.Write(benchPos.y);
            }
        }
    
        public void LoadBench()
        {
            string savePath = Application.persistentDataPath + "/save.bench.data";
            if (File.Exists(savePath) && new FileInfo(savePath).Length > 0)
            {
                using(BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.bench.data")))
                {
                    benchSceneName = reader.ReadString();
                    benchPos.x = reader.ReadSingle();
                    benchPos.y = reader.ReadSingle();
                }
            }
            else
            {
                Debug.Log("Bench doesn't exist");
            }
        }
        #endregion
    
        #region Player Stuff
        public void SavePlayerData()
        {
            using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.player.data")))
            {
                playerHealth = PlayerController.Instance.Health;
                writer.Write(playerHealth);
                playerMaxHealth = PlayerController.Instance.maxHealth;
                writer.Write(playerMaxHealth);
                playerHeartShards = PlayerController.Instance.heartShards;
                writer.Write(playerHeartShards);
    
                playerMana = PlayerController.Instance.Mana;
                writer.Write(playerMana);
                playerHalfMana = PlayerController.Instance.halfMana;
                writer.Write(playerHalfMana);
                playerManaOrbs = PlayerController.Instance.manaOrbs;
                writer.Write(playerManaOrbs);
                playerOrbShard = PlayerController.Instance.orbShard;
                writer.Write(playerOrbShard);
                playerOrb0fill = PlayerController.Instance.manaOrbsHandler.orbFills[0].fillAmount;
                writer.Write(playerOrb0fill);
                playerOrb1fill = PlayerController.Instance.manaOrbsHandler.orbFills[1].fillAmount;
                writer.Write(playerOrb1fill);
                playerOrb2fill = PlayerController.Instance.manaOrbsHandler.orbFills[2].fillAmount;
                writer.Write(playerOrb2fill);
    
                playerUnlockedWallJump = PlayerController.Instance.unlockedWallJump;
                writer.Write(playerUnlockedWallJump);
                playerUnlockedDash = PlayerController.Instance.unlockedDash;
                writer.Write(playerUnlockedDash);
                playerUnlockedVarJump = PlayerController.Instance.unlockedVarJump;
                writer.Write(playerUnlockedVarJump);
    
                playerUnlockedSideCast = PlayerController.Instance.unlockedSideCast;
                writer.Write(playerUnlockedSideCast);
                playerUnlockedUpCast = PlayerController.Instance.unlockedUpCast;
                writer.Write(playerUnlockedUpCast);
                playerUnlockedDownCast = PlayerController.Instance.unlockedDownCast;
                writer.Write(playerUnlockedDownCast);
                
    
                playerPosition = PlayerController.Instance.transform.position;
                writer.Write(playerPosition.x);
                writer.Write(playerPosition.y);
    
                lastScene = SceneManager.GetActiveScene().name;
                writer.Write(lastScene);
    
            }
            Debug.Log("saved player data");
        }
    
        public void LoadPlayerData()
        {
            string savePath = Application.persistentDataPath + "/save.player.data";
            if (File.Exists(savePath) && new FileInfo(savePath).Length > 0)
            {
                using(BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.player.data")))
                {
                    playerHealth = reader.ReadInt32();
                    playerMaxHealth = reader.ReadInt32();
                    playerHeartShards = reader.ReadInt32();
                    playerMana = reader.ReadSingle();
                    playerHalfMana = reader.ReadBoolean();
                    playerManaOrbs = reader.ReadInt32();
                    playerOrbShard = reader.ReadInt32();
                    playerOrb0fill = reader.ReadSingle();
                    playerOrb1fill = reader.ReadSingle();
                    playerOrb2fill = reader.ReadSingle();
    
                    playerUnlockedWallJump = reader.ReadBoolean();
                    playerUnlockedDash= reader.ReadBoolean();
                    playerUnlockedVarJump= reader.ReadBoolean();
    
                    playerUnlockedSideCast= reader.ReadBoolean();
                    playerUnlockedUpCast = reader.ReadBoolean();
                    playerUnlockedDownCast = reader.ReadBoolean();
    
                    playerPosition.x = reader.ReadSingle();
                    playerPosition.y = reader.ReadSingle();
    
                    lastScene = reader.ReadString();
    
                    SceneManager.LoadScene(lastScene);
                    PlayerController.Instance.transform.position = playerPosition;
                    PlayerController.Instance.halfMana = playerHalfMana;
                    PlayerController.Instance.Health = playerHealth;
                    PlayerController.Instance.maxHealth = playerMaxHealth;
                    PlayerController.Instance.heartShards = playerHeartShards;
                    PlayerController.Instance.Mana = playerMana;
                    PlayerController.Instance.manaOrbs = playerManaOrbs;
                    PlayerController.Instance.orbShard = playerOrbShard;
                    PlayerController.Instance.manaOrbsHandler.orbFills[0].fillAmount = playerOrb0fill;
                    PlayerController.Instance.manaOrbsHandler.orbFills[1].fillAmount = playerOrb1fill;
                    PlayerController.Instance.manaOrbsHandler.orbFills[2].fillAmount = playerOrb2fill;
    
                    PlayerController.Instance.unlockedWallJump = playerUnlockedWallJump;
                    PlayerController.Instance.unlockedDash = playerUnlockedDash;
                    PlayerController.Instance.unlockedVarJump = playerUnlockedVarJump;
    
                    PlayerController.Instance.unlockedSideCast = playerUnlockedSideCast;
                    PlayerController.Instance.unlockedUpCast = playerUnlockedUpCast;
                    PlayerController.Instance.unlockedDownCast = playerUnlockedDownCast;
    
                }
                Debug.Log("load player data");
                Debug.Log(playerHalfMana);
            }
            else
            {
                Debug.Log("File doesn't exist");
                PlayerController.Instance.halfMana = false;
                PlayerController.Instance.Health = PlayerController.Instance.maxHealth;
                PlayerController.Instance.Mana = 0.5f;
                PlayerController.Instance.heartShards = 0;
    
                PlayerController.Instance.unlockedWallJump = false;
                PlayerController.Instance.unlockedDash = false;
                PlayerController.Instance.unlockedVarJump = false;
    
                PlayerController.Instance.unlockedSideCast = false;
                PlayerController.Instance.unlockedUpCast = false;
                PlayerController.Instance.unlockedDownCast = false;
    
            }
        }
        #endregion
    
        #region Shade Stuff
        public void SaveShadeData()
        {
            using(BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.shade.data")))
            {
                sceneWithShade = SceneManager.GetActiveScene().name;
                shadePos = Shade.Instance.transform.position;
                shadeRot = Shade.Instance.transform.rotation;
    
                writer.Write(sceneWithShade);
    
                writer.Write(shadePos.x);
                writer.Write(shadePos.y);
    
                writer.Write(shadeRot.x);
                writer.Write(shadeRot.y);
                writer.Write(shadeRot.z);
                writer.Write(shadeRot.w);
            }
        }
    
        public void LoadShadeData()
        {
            string savePath = Application.persistentDataPath + "/save.shade.data";
            if (File.Exists(savePath) && new FileInfo(savePath).Length > 0)
            {
                using(BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.shade.data")))
                {
                    sceneWithShade = reader.ReadString();
                    shadePos.x = reader.ReadSingle();
                    shadePos.y = reader.ReadSingle();
    
                    float rotationX = reader.ReadSingle();
                    float rotationY = reader.ReadSingle();
                    float rotationZ = reader.ReadSingle();
                    float rotationW = reader.ReadSingle();
                    shadeRot = new Quaternion(rotationX, rotationY, rotationZ, rotationW);
                }
                Debug.Log("Load shade data");
            }
            else
            {
                Debug.Log("Shade doesn't exist");
            }
        }
        #endregion
    }
    #14857
    Elvin Sim
    Participant
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class MapManager : MonoBehaviour
    {
        [SerializeField] GameObject[] maps;
    
        Bench bench;
    
        private void OnEnable()
        {
            bench = FindObjectOfType<Bench>();
            if ( bench != null )
            {
                if(bench.interacted )
                {
                    UpdateMap();
                }
            }
        }
    
        void UpdateMap()
        {
            var savedScenes = SaveData.Instance.sceneNames;
    
            for(int i = 0; i < maps.Length; i++)
            {
                if(savedScenes.Contains("The Forest of Beginnings_" + (i + 1)))
                {
                    maps[i].SetActive(true);
                }
                else if (savedScenes.Contains("The Ruins of Unity_" + (i + 1)))
                {
                    maps[i].SetActive(true);
                }
                else if (savedScenes.Contains("The Bastion of Strife_" + (i + 1)))
                {
                    maps[i].SetActive(true);
                }
                else if (savedScenes.Contains("The Abyssal Depths_" + (i + 1)))
                {
                    maps[i].SetActive(true);
                }
                else
                {
                    maps[i].SetActive(false);
                }
            }
        }
    }
    #14858
    Elvin Sim
    Participant
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class Bench : MonoBehaviour
    {
        bool inRange = false;
        public bool interacted;
        
        // Update is called once per frame
        void Update()
        {
            if (Input.GetButtonDown("Interact") && inRange)
            {
                interacted = true;
    
                SaveData.Instance.benchSceneName = SceneManager.GetActiveScene().name;
                SaveData.Instance.benchPos = new Vector2(gameObject.transform.position.x, gameObject.transform.position.y);
                SaveData.Instance.SaveBench();
                SaveData.Instance.SavePlayerData();
    
                Debug.Log("benched");
            }
        }
    
        private void OnTriggerEnter2D(Collider2D _collision)
        {
            if(_collision.CompareTag("Player")) inRange = true;
        }
    
        private void OnTriggerExit2D(Collider2D _collision)
        {
            if (_collision.CompareTag("Player"))
            {
                interacted = false;
                inRange = false;
            }
        }
    }
    #14859
    Elvin Sim
    Participant
    using Microsoft.Unity.VisualStudio.Editor;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UIElements;
    using UnityEngine.UI;
    using Cinemachine;
    using Unity.VisualScripting;
    
    public class PlayerController : MonoBehaviour
    {
        [Header("Horizontal Movement Settings:")]
        [SerializeField] private float walkSpeed = 1;
        [Space(5)]
    
        [Header("Vertical Movement Settings:")]
        [SerializeField] private float jumpForce = 45f;
    
        private int jumpBufferCounter = 0;
        [SerializeField] private int jumpBufferFrames;
    
        private float coyoteTimeCounter = 0;
        [SerializeField] private float coyoteTime;
    
        private int airJumpCounter = 0;
        [SerializeField] private int maxAirJumps;
    
        private float gravity;
        [Space(5)]
    
        [Header("Wall Jump Settings")]
        [SerializeField] private float wallSlidingSpeed = 2f;
        [SerializeField] private Transform wallCheck;
        [SerializeField] private LayerMask wallLayer;
        [SerializeField] private float wallJumpingDuration;
        [SerializeField] private Vector2 wallJumpingPower;
        float wallJumpingDirection;
        bool isWallSliding;
        bool isWallJumping;
    
        [Space(5)]
    
        [Header("Ground Check Settings:")]
        [SerializeField] private Transform groundCheckPoint; //point at which ground check happens
        [SerializeField] private float groundCheckY = 0.2f; //how far down from ground check point is Grounded() checked
        [SerializeField] private float groundCheckX = 0.5f; //how far horizontally from ground check point to the edge of the player is
        [SerializeField] private LayerMask whatIsGround; //sets the ground layer
        [Space(5)]
    
        [Header("Dash Settings:")]
        [SerializeField] private float dashSpeed;
        [SerializeField] private float dashTime;
        [SerializeField] private float dashCooldown;
        [SerializeField] GameObject dashEffect;
        private bool canDash = true;
        private bool dashed;
        [Space(5)]
    
        [Header("Attack Settings:")]
        [SerializeField] private Transform SideAttackTransform; //the middle of the side attack area
        [SerializeField] private Vector2 SideAttackArea; //how large the area of side attack is
    
        [SerializeField] private Transform UpAttackTransform; //the middle of the up attack area
        [SerializeField] private Vector2 UpAttackArea; //how large the area of up attack is
    
        [SerializeField] private Transform DownAttackTransform; //the middle of the down attack area
        [SerializeField] private Vector2 DownAttackArea; //how large the area of down attack is
    
        [SerializeField] private LayerMask attackableLayer;
    
        private float timeBetweenAttack, timeSinceAttack;
    
        [SerializeField] private float damage;
    
        [SerializeField] private GameObject slashEffect;
    
        bool restoreTime;
        float restoreTimeSpeed;
        [Space(5)]
    
        [Header("Recoil Settings:")]
        [SerializeField] private int recoilXSteps = 5;
        [SerializeField] private int recoilYSteps = 5;
    
        [SerializeField] private float recoilXSpeed = 100;
        [SerializeField] private float recoilYSpeed = 100;
    
        private int stepsXRecoiled, stepsYRecoiled;
        [Space(5)]
    
        [Header("Health Settings:")]
        public int health;
        public int maxHealth;
        public int maxTotalHealth = 10;
        public int heartShards;
        [SerializeField] GameObject bloodSpurt;
        [SerializeField] float hitFlashSpeed;
        public delegate void OnHealthChangedDelegate();
        [HideInInspector] public OnHealthChangedDelegate onHealthChangedCallback;
    
        float healTimer;
        [SerializeField] float timeToHeal;
        [Space(5)]
    
        [Header("Mana Settings:")]
        [SerializeField] UnityEngine.UI.Image manaStorage;
        [SerializeField] float mana;
        [SerializeField] float manaDrainSpeed;
        [SerializeField] float manaGain;
        public bool halfMana;
    
        public ManaOrbsHandler manaOrbsHandler;
        public int orbShard;
        public int manaOrbs;
        [Space(5)]
    
        [Header("Spell Settings:")]
        [SerializeField] float manaSpellCost = 0.3f;
        [SerializeField] float timeBetweenCast = 0.5f;
        [SerializeField] float spellDamage; //upspellexplosion and downspellfireball
        [SerializeField] float downSpellForce; //desolate dive only
        //spell cast objects
        [SerializeField] GameObject sideSpellFireball;
        [SerializeField] GameObject upSpellExplosion;
        [SerializeField] GameObject downSpellFireball;
        float timeSinceCast;
        float castOrHealtimer;
        [Space(5)]
    
        [Header("Camera Stuff")]
        [SerializeField] private float playerFallSpeedThreshold = -5;
        [Space(5)]
    
        [Header("Audio")]
        [SerializeField] AudioClip landingSound;
        [SerializeField] AudioClip jumpSound;
        [SerializeField] AudioClip dashAndAttackSound;
        [SerializeField] AudioClip spellCastSound;
        [SerializeField] AudioClip hurtSound;
    
        [HideInInspector] public PlayerStateList pState;
        [HideInInspector] public Rigidbody2D rb;
        private Animator anim;
        private SpriteRenderer sr;
        private AudioSource audioSource;
    
        //Input Variables
        private float xAxis, yAxis;
        private bool attack = false;
        bool openMap;
        bool openInventory;
    
        private bool canFlash = true;
    
        private bool landingSoundPlayed;
    
        public static PlayerController Instance;
    
        //unlocking
        public bool unlockedWallJump;
        public bool unlockedDash;
        public bool unlockedVarJump;
    
        public bool unlockedSideCast;
        public bool unlockedUpCast;
        public bool unlockedDownCast;
    
        private void Awake()
        {
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
            }
            else
            {
                Instance = this;
            }
            DontDestroyOnLoad(gameObject);
    
        }
    
        // Start is called before the first frame update
        void Start()
        {
            pState = GetComponent<PlayerStateList>();
    
            rb = GetComponent<Rigidbody2D>();
            sr = GetComponent<SpriteRenderer>();
            audioSource = GetComponent<AudioSource>();
    
            anim = GetComponent<Animator>();
            manaOrbsHandler = FindObjectOfType<ManaOrbsHandler>();
    
            SaveData.Instance.LoadPlayerData();
    
            FindObjectOfType<MapManager>().UpdateMap();
    
            if (halfMana)
            {
                UIManager.Instance.SwitchMana(UIManager.ManaState.HalfMana);
            }
    
            gravity = rb.gravityScale;
    
            Mana = mana;
            manaStorage.fillAmount = Mana;
    
            Health = maxHealth;
            Debug.Log(transform.position);
    
            
        }
    
        private void OnDrawGizmos()
        {
            Gizmos.color = Color.red;
            Gizmos.DrawWireCube(SideAttackTransform.position, SideAttackArea);
            Gizmos.DrawWireCube(UpAttackTransform.position, UpAttackArea);
            Gizmos.DrawWireCube(DownAttackTransform.position, DownAttackArea);
        }
    
        // Update is called once per frame
        void Update()
        {
            if (GameManager.Instance.gameIsPaused) return;
    
            if (pState.cutscene) return;
            if (pState.alive)
            {
                GetInputs();
                ToggleMap();
                ToggleInventory();
            }
           
            UpdateJumpVariables();
            UpdateCameraYDampForPlayerFall();
            RestoreTimeScale();
    
            if (pState.alive)
            {
                Heal();
            }
    
            if (pState.dashing || pState.healing) return;
    
            if (pState.alive)
            {
                if (!isWallJumping)
                {
                    Flip();
                    Move();
                    Jump();
                }
    
                if (unlockedWallJump)
                {
                    WallSlide();
                    WallJump();
                }
    
                if (unlockedDash)
                {
                    StartDash();
                }
    
                
                Attack();
                CastSpell();
            }
            FlashWhileInvincible();
        }
    
        private void OnTriggerEnter2D(Collider2D _other) //for up and down spell cast
        {
            if(_other.GetComponent<Enemy>() != null && pState.casting)
            {
                _other.GetComponent<Enemy>().EnemyGetsHit(spellDamage, (_other.transform.position - transform.position).normalized, -recoilYSpeed);
            }
        }
    
        private void FixedUpdate()
        {
            if (pState.cutscene) return;
    
            if (pState.dashing || pState.healing) return;
            Recoil();
        }
    
        void GetInputs()
        {
            xAxis = Input.GetAxisRaw("Horizontal");
            yAxis = Input.GetAxisRaw("Vertical");
            attack = Input.GetButtonDown("Attack");
            openMap = Input.GetButton("Map");
            openInventory = Input.GetButton("Inventory");
    
            if (Input.GetButton("Cast/Heal"))
            {
                castOrHealtimer += Time.deltaTime;
            }
           
        }
    
        void ToggleMap()
        {
            if(openMap)
            {
                UIManager.Instance.mapHandler.SetActive(true);
            }
            else
            {
                UIManager.Instance.mapHandler.SetActive(false);
            }
        }
    
        void ToggleInventory()
        {
            if (openInventory)
            {
                UIManager.Instance.inventory.SetActive(true);
            }
            else
            {
                UIManager.Instance.inventory.SetActive(false);
            }
        }
    
        void Flip()
        {
            if (xAxis < 0)
            {
                transform.localScale = new Vector2(-1, transform.localScale.y);
                pState.lookingRight = false;
            }
            else if (xAxis > 0)
            {
                transform.localScale = new Vector2(1, transform.localScale.y);
                pState.lookingRight = true;
            }
        }
    
        private void Move()
        {
            rb.velocity = new Vector2(walkSpeed * xAxis, rb.velocity.y);
            anim.SetBool("Walking", rb.velocity.x != 0 && Grounded());
        }
    
        void UpdateCameraYDampForPlayerFall()
        {
            //if falling past a certain speed threshold
            if(rb.velocity.y < playerFallSpeedThreshold && !CameraManager.Instance.isLerpingYDamping && !CameraManager.Instance.hasLerpedYDamping)
            {
                StartCoroutine(CameraManager.Instance.LerpYDamping(true));
            }
            //if standing still or moving up
            if(rb.velocity.y >= 0 && !CameraManager.Instance.isLerpingYDamping && CameraManager.Instance.hasLerpedYDamping)
            {
                //reset camera function
                CameraManager.Instance.hasLerpedYDamping = false;
                StartCoroutine(CameraManager.Instance.LerpYDamping(false));
            }
        }
    
        void StartDash()
        {
            if (Input.GetButtonDown("Dash") && canDash && !dashed)
            {
                StartCoroutine(Dash());
                dashed = true;
            }
    
            if (Grounded())
            {
                dashed = false;
            }
        }
    
        IEnumerator Dash()
        {
            canDash = false;
            pState.dashing = true;
            anim.SetTrigger("Dashing");
            audioSource.PlayOneShot(dashAndAttackSound);
            rb.gravityScale = 0;
            int _dir = pState.lookingRight ? 1 : -1;
            rb.velocity = new Vector2(_dir * dashSpeed, 0);
            if (Grounded()) Instantiate(dashEffect, transform);
            yield return new WaitForSeconds(dashTime);
            rb.gravityScale = gravity;
            pState.dashing = false;
            yield return new WaitForSeconds(dashCooldown);
            canDash = true;
        }
    
        public IEnumerator WalkIntoNewScene(Vector2 _exitDir, float _delay)
        {
            //If exit direction is upwards
            if(_exitDir.y != 0)
            {
                rb.velocity = jumpForce * _exitDir;
            }
    
            //If exit direction requires horizontal movement
            if(_exitDir.x != 0)
            {
                xAxis = _exitDir.x > 0 ? 1 : -1;
    
                Move();
            }
    
            Flip();
            yield return new WaitForSeconds(_delay);
            pState.cutscene = false;
        }
    
        void Attack()
        {
            timeSinceAttack += Time.deltaTime;
            if(attack && timeSinceAttack >= timeBetweenAttack)
            {
                timeSinceAttack = 0;
                anim.SetTrigger("Attacking");
                audioSource.PlayOneShot(dashAndAttackSound);
    
                if(yAxis == 0 || yAxis < 0 && Grounded())
                {
                    int _recoilLeftOrRight = pState.lookingRight ? 1 : -1;
    
                    Hit(SideAttackTransform, SideAttackArea, ref pState.recoilingX, Vector2.right * _recoilLeftOrRight, recoilXSpeed);
                    Instantiate(slashEffect, SideAttackTransform);
                }
                else if(yAxis > 0)
                {
                    Hit(UpAttackTransform, UpAttackArea, ref pState.recoilingY, Vector2.up, recoilYSpeed);
                    SlashEffectAtAngle(slashEffect, 80, UpAttackTransform);
                }
                else if (yAxis < 0 && !Grounded())
                {
                    Hit(DownAttackTransform, DownAttackArea, ref pState.recoilingY, Vector2.down, recoilYSpeed);
                    SlashEffectAtAngle(slashEffect, -90, DownAttackTransform);
                }
            }
        }
    
        void Hit(Transform _attackTransform, Vector2 _attackArea, ref bool _recoilBool, Vector2 _recoilDir, float _recoilStrength)
        {
            Collider2D[] objectsToHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer);
    
            if(objectsToHit.Length > 0)
            {
                _recoilBool = true;
            }
            for(int i = 0; i < objectsToHit.Length; i++)
            {
                if (objectsToHit[i].GetComponent<Enemy>() != null)
                {
                    objectsToHit[i].GetComponent<Enemy>().EnemyGetsHit(damage, _recoilDir, _recoilStrength);
    
                    if (objectsToHit[i].CompareTag("Enemy"))
                    {
                        if(Mana < 1)
                        {
                            Mana += manaGain;
                        }
                        else
                        {
                            manaOrbsHandler.UpdateMana(manaGain * 3);
                        }
                    }
                }
            }
        } 
    
        void SlashEffectAtAngle(GameObject _slashEffect, int _effectAngle, Transform _attackTransform)
        {
            _slashEffect = Instantiate(_slashEffect, _attackTransform);
            _slashEffect.transform.eulerAngles = new Vector3(0, 0, _effectAngle);
            _slashEffect.transform.localScale = new Vector2(transform.localScale.x, transform.localScale.y);
        }
    
        void Recoil()
        {
            if(pState.recoilingX)
            {
                if(pState.lookingRight)
                {
                    rb.velocity = new Vector2(-recoilXSpeed, 0); 
                }
                else
                {
                    rb.velocity = new Vector2(recoilXSpeed, 0);
                }
            }
    
            if (pState.recoilingY)
            {
                rb.gravityScale = 0;
                if (yAxis < 0)
                {
                    rb.velocity = new Vector2(rb.velocity.x, recoilYSpeed);
                }
                else
                {
                    rb.velocity = new Vector2(rb.velocity.x, -recoilYSpeed);
                }
                airJumpCounter = 0;
            }
            else
            {
                rb.gravityScale = gravity;
            }
    
            //stop recoil
            if(pState.recoilingX && stepsXRecoiled < recoilXSteps)
            {
                stepsXRecoiled++;
            }
            else
            {
                StopRecoilX();
            }
            if (pState.recoilingY && stepsYRecoiled < recoilYSteps)
            {
                stepsYRecoiled++;
            }
            else
            {
                StopRecoilY();
            }
    
            if (Grounded())
            {
                StopRecoilY();
            }
        }
    
        void StopRecoilX()
        {
            stepsXRecoiled = 0;
            pState.recoilingX = false;
        }
    
        void StopRecoilY()
        {
            stepsYRecoiled = 0;
            pState.recoilingY = false;
        }
    
        public void TakeDamage(float _damage)
        {
            if (pState.alive)
            {
                audioSource.PlayOneShot(hurtSound);
    
                Health -= Mathf.RoundToInt(_damage);
                if(Health <= 0)
                {
                    Health = 0;
                    StartCoroutine(Death());
                }
                else
                {
                    StartCoroutine(StopTakingDamage());
                }
         
            }
            
        }
    
        IEnumerator StopTakingDamage()
        {
            pState.invincible = true;
            GameObject _bloodSpurtParticles = Instantiate(bloodSpurt, transform.position, Quaternion.identity);
            Destroy(_bloodSpurtParticles, 1.5f);
            anim.SetTrigger("TakeDamage");
            yield return new WaitForSeconds(1f);
            pState.invincible = false;
        }
    
        IEnumerator Flash()
        {
            sr.enabled = !sr.enabled;
            canFlash = false;
            yield return new WaitForSeconds(0.2f);
            canFlash = true;
        }
    
        void FlashWhileInvincible()
        {
            if(pState.invincible)
            {
                if(Time.timeScale > 0.2 && canFlash)
                {
                    StartCoroutine(Flash());
                }
            }
            else
            {
                sr.enabled = true;
            }
        }
    
        void RestoreTimeScale()
        {
            if (restoreTime)
            {
                if(Time.timeScale < 1)
                {
                    Time.timeScale += Time.deltaTime * restoreTimeSpeed;
                }
                else
                {
                    Time.timeScale = 1;
                    restoreTime = false;
                }
            }
        }
    
        public void HitStopTime(float _newTimeScale, int _restoreSpeed, float _delay)
        {
            restoreTimeSpeed = _restoreSpeed;
            Time.timeScale = _newTimeScale;
    
            if(_delay > 0)
            {
                StopCoroutine(StartTimeAgain(_delay));
                StartCoroutine(StartTimeAgain(_delay));
            }
            else
            {
                restoreTime = true;
            }
        }
    
        IEnumerator StartTimeAgain(float _delay)
        {
            restoreTime = true;
            yield return new WaitForSeconds(_delay);
        }
    
        IEnumerator Death()
        {
            pState.alive = false;
            Time.timeScale = 1f;
            GameObject _bloodSpurtParticles = Instantiate(bloodSpurt, transform.position, Quaternion.identity);
            Destroy(_bloodSpurtParticles, 1.5f);
            anim.SetTrigger("Death");
    
            yield return new WaitForSeconds(0.9f);
            StartCoroutine(UIManager.Instance.ActivateDeathScreen());
    
            yield return new WaitForSeconds(0.9f);
            Instantiate(GameManager.Instance.shade, transform.position, Quaternion.identity);
        }
    
        public void Respawned()
        {
            if(!pState.alive)
            {
                pState.alive = true;
                halfMana = true;
                UIManager.Instance.SwitchMana(UIManager.ManaState.HalfMana);
                Mana = 0;
                Health = maxHealth;
                anim.Play("player_idle");
            }
        }
    
        public void RestoreMana()
        {
            halfMana = false;
            UIManager.Instance.SwitchMana(UIManager.ManaState.FullMana);
        }
    
        public int Health
        {
            get { return health; }
            set
            {
                if (health != value)
                {
                    health = Mathf.Clamp(value, 0, maxHealth);
    
                    if(onHealthChangedCallback != null)
                    {
                        onHealthChangedCallback.Invoke();
                    }
                }
            }
        }
    
        void Heal()
        {
            if(Input.GetButton("Cast/Heal") && castOrHealtimer > 0.05f && Health < maxHealth && Mana > 0 && Grounded() && !pState.dashing)
            {
                pState.healing = true;
                anim.SetBool("Healing", true);
    
                //healing
                healTimer += Time.deltaTime;
                if(healTimer >= timeToHeal)
                {
                    Health++;
                    healTimer = 0;
                }
    
                //drain mana
                manaOrbsHandler.usedMana = true;
                manaOrbsHandler.countDown = 3f;
                Mana -= Time.deltaTime * manaDrainSpeed;
            }
            else
            {
                pState.healing = false;
                anim.SetBool("Healing", false);
                healTimer = 0;
            }
        }
    
        public float Mana
        {
            get { return mana; }
            set
            {
                //if mana stats change
                if(mana != value)
                {
                    if (!halfMana)
                    {
                        mana = Mathf.Clamp(value, 0, 1);
                    }
                    else
                    {
                        mana = Mathf.Clamp(value, 0, 0.5f);
                    }
                    
                    manaStorage.fillAmount = Mana;
                }
            }
        }
        
        void CastSpell()
        {
            if(Input.GetButtonUp("Cast/Heal") && castOrHealtimer <= 0.1f && timeSinceCast >= timeBetweenCast && Mana >= manaSpellCost)
            {
                pState.casting = true;
                timeSinceCast = 0;
                StartCoroutine(CastCoroutine());
            }
            else
            {
                timeSinceCast += Time.deltaTime;
            }
    
            if (!Input.GetButton("Cast/Heal"))
            {
                castOrHealtimer = 0;
            }
    
            if (Grounded())
            {
                //disable downspell if on the ground
                downSpellFireball.SetActive(false);
            }
            //if down spell is active, force player down until grounded
            if(downSpellFireball.activeInHierarchy)
            {
                rb.velocity += downSpellForce * Vector2.down;
            }
        }
    
        IEnumerator CastCoroutine()
        {
            //side cast
            if((yAxis == 0 || (yAxis < 0 && Grounded())) && unlockedSideCast)
            {
                audioSource.PlayOneShot(spellCastSound);
                anim.SetBool("Casting", true);
                yield return new WaitForSeconds(0.15f);
                GameObject _fireBall = Instantiate(sideSpellFireball, SideAttackTransform.position, Quaternion.identity);
    
                //flip fireball
                if (pState.lookingRight)
                {
                    _fireBall.transform.eulerAngles = Vector3.zero; //if facing right, fireball continues as per normal
                }
                else
                {
                    _fireBall.transform.eulerAngles = new Vector2(_fireBall.transform.eulerAngles.x, 180);
                    //if not facing right, rotate the fireball 180 deg
                }
                pState.recoilingX = true;
    
                Mana -= manaSpellCost;
                manaOrbsHandler.usedMana = true;
                manaOrbsHandler.countDown = 3f;
                yield return new WaitForSeconds(0.35f);
            }
    
            //up cast
            else if(yAxis > 0 && unlockedUpCast)
            {
                audioSource.PlayOneShot(spellCastSound);
                anim.SetBool("Casting", true);
                yield return new WaitForSeconds(0.15f);
    
                Instantiate(upSpellExplosion, transform);
                rb.velocity = Vector2.zero;
    
                Mana -= manaSpellCost;
                manaOrbsHandler.usedMana = true;
                manaOrbsHandler.countDown = 3f;
                yield return new WaitForSeconds(0.35f);
            }
    
            //down cast
            else if((yAxis < 0 && !Grounded()) && unlockedDownCast)
            {
                audioSource.PlayOneShot(spellCastSound);
                anim.SetBool("Casting", true);
                yield return new WaitForSeconds(0.15f);
    
                downSpellFireball.SetActive(true);
    
                Mana -= manaSpellCost;
                manaOrbsHandler.usedMana = true;
                manaOrbsHandler.countDown = 3f;
                yield return new WaitForSeconds(0.35f);
            }
    
            anim.SetBool("Casting", false);
            pState.casting = false;
        }
    
        public bool Grounded()
        {
            if (Physics2D.Raycast(groundCheckPoint.position, Vector2.down, groundCheckY, whatIsGround) 
                || Physics2D.Raycast(groundCheckPoint.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround) 
                || Physics2D.Raycast(groundCheckPoint.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    
        void Jump()
        {
            if (jumpBufferCounter > 0 && coyoteTimeCounter > 0 && !pState.jumping) 
            {
                audioSource.PlayOneShot(jumpSound);
    
                rb.velocity = new Vector3(rb.velocity.x, jumpForce);
    
                pState.jumping = true;
            }
    
            if (!Grounded() && airJumpCounter < maxAirJumps && Input.GetButtonDown("Jump") && unlockedVarJump)
            {
                audioSource.PlayOneShot(jumpSound);
    
                pState.jumping = true;
    
                airJumpCounter++;
    
                rb.velocity = new Vector3(rb.velocity.x, jumpForce);
            }
    
            if (Input.GetButtonUp("Jump") && rb.velocity.y > 3)
            {
                rb.velocity = new Vector2(rb.velocity.x, 0);
    
                pState.jumping = false;
            }
    
            anim.SetBool("Jumping", !Grounded());
        }
    
        void UpdateJumpVariables()
        {
            if (Grounded())
            {
                if (!landingSoundPlayed)
                {
                    audioSource.PlayOneShot(landingSound);
                    landingSoundPlayed = true;
                }
                pState.jumping = false;
                coyoteTimeCounter = coyoteTime;
                airJumpCounter = 0;
            }
            else
            {
                coyoteTimeCounter -= Time.deltaTime;
                landingSoundPlayed = false;
            }
    
            if (Input.GetButtonDown("Jump"))
            {
                jumpBufferCounter = jumpBufferFrames;
            }
            else
            {
                jumpBufferCounter--;
            }
        }
    
        private bool Walled()
        {
            return Physics2D.OverlapCircle(wallCheck.position, 0.2f, wallLayer);
        }
    
        void WallSlide()
        {
            if(Walled() && !Grounded() && xAxis != 0)
            {
                isWallSliding = true;
                rb.velocity = new Vector2(rb.velocity.x, Mathf.Clamp(rb.velocity.y, -wallSlidingSpeed, float.MaxValue));
            }
            else
            {
                isWallSliding = false;
            }
        }
    
        void WallJump()
        {
            if(isWallSliding)
            {
                isWallJumping = false;
                wallJumpingDirection = !pState.lookingRight ? 1 : -1;
    
                CancelInvoke(nameof(StopWallJumping));
            }
    
            if(Input.GetButtonDown("Jump") && isWallSliding)
            {
                isWallJumping = true;
                rb.velocity = new Vector2(wallJumpingDirection * wallJumpingPower.x, wallJumpingPower.y);
    
                dashed = false;
                airJumpCounter = 0;
                pState.lookingRight = !pState.lookingRight;
                transform.eulerAngles = new Vector2(transform.eulerAngles.x, 180);
                
    
                Invoke(nameof(StopWallJumping), wallJumpingDuration);
            }
        }
    
        void StopWallJumping()
        {
            isWallJumping = false;
            transform.eulerAngles = new Vector2(transform.eulerAngles.x, 0);
        }
    }
    #14867
    Joseph Tang
    Moderator

    This is because the scene names aren’t being saved in a permanent method. Like how player data is saved, you can save the scene names in a file and extract the scenenames from that file if you want the data to be carried over playthroughs.

    SaveData.cs

        public void Initialize()
        {
            if (!File.Exists(Application.persistentDataPath + "/save.scenes.data")) // If file doesn't exist, create it
            {
                using (BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.scenes.data")))
                {
                    writer.Write(0); // Write an empty scene data structure
                }
            }
    
            if (sceneNames == null)
            {
                sceneNames = new HashSet();
            }
    
            // Load existing data
            LoadSceneData();
        }
    
        public void SaveSceneData()
        {
            using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.scenes.data")))
            {
                writer.Write(sceneNames.Count);
                foreach (string sceneName in sceneNames)
                {
                    writer.Write(sceneName);
                }
            }
        }
    
        public void LoadSceneData()
        {
            if (File.Exists(Application.persistentDataPath + "/save.scenes.data"))
            {
                using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.scenes.data")))
                {
                    int sceneCount = reader.ReadInt32();
                    sceneNames = new HashSet();
                    for (int i = 0; i < sceneCount; i++)
                    {
                        string sceneName = reader.ReadString();
                        sceneNames.Add(sceneName);
                    }
                }
            }
            else
            {
                sceneNames = new HashSet();
            }
        }

    GameManager.cs

        public void SaveScene()
        {
            string currentSceneName = SceneManager.GetActiveScene().name;
            SaveData.Instance.sceneNames.Add(currentSceneName);
            SaveData.Instance.SaveSceneData(); // Save scene names whenever a new scene is added
        }

    Like this, your saved scenes should be able to be found in a file and accessed.

    There’s only 2 issues. MapManager.cs calls updatemap only when the bench is interacted with, making it a small window to update the map since the player has to use the map while still standing in the bench’s collider for it to still be counted as interacted.

    And the second issue is that the player calls updatemap on awake, meaning that just by exiting and reenterring the game, the player will update the map all on their own without having to sit on a bench.

    #14868
    Elvin Sim
    Participant

    And I would also like to ask that if I want to disable the scene that I just saved, how do to?

    #14869
    #14870
    Joseph Tang
    Moderator

    Sorry, I need context, what do you want to do?

    Do you want to remove saved scenes to start a new save file or?

    #14871
    Elvin Sim
    Participant

    yes

    #14872
    Elvin Sim
    Participant

    just like you said

    #14873
    Joseph Tang
    Moderator

    In that case, to delete your save files, you can refer to this kind of code that i provided in this post:

    [Part 7] Save Data problems


        public void DeletePlayerData()
        {
            string path = Application.persistentDataPath + "/save.player.data";
            if (File.Exists(path))
            {
                File.Delete(path);
                Debug.Log("Player save data deleted.");
            }
        }
    
        public void DeleteShadeData()
        {
            string path = Application.persistentDataPath + "/save.shade.data";
            if (File.Exists(path))
            {
                File.Delete(path);
                Debug.Log("Shade save data deleted.");
            }
        }
    
        public void DeleteAllSaveData()
        {
            DeleteFlagData();
            DeletePlayerData();
            DeleteShadeData();
        }

    GameManager.cs
    Call this in a function that you want. Maybe a getInput

        {
            SaveData.Instance.DeleteAllSaveData()
        }

    Simply change out the code for the maps or whatever function you want to remove.

    #14874
    Elvin Sim
    Participant

    Ok thank you very much, it works now

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

Go to Login Page →


Advertisement below: