Forum begins after the advertisement:
[Part 7] Save Data problems
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [Part 7] Save Data problems
- This topic has 8 replies, 2 voices, and was last updated 3 months, 1 week ago by
Mr Thinker.
-
AuthorPosts
-
May 29, 2024 at 11:39 pm #14804
Mr Thinker
Participant::Save system not working, gets stuck loading the scene after closing the game and reopening it or just forcing the LoadPlayerData function.
Please help kinda need to get it done ASAP.
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 related public HashSet<string> sceneName; //flag stuff public string flagSceneName; public Vector2 flagPos; //player stuff public int playerHealth; public float playerEnergy; public bool playerHalfEnergy; public Vector2 playerPosition; public string lastScene; //enemy stuff //shade public Vector2 shadePos; public string sceneWithShade; public Quaternion shadeRot; public void Initialize() { if (!File.Exists(Application.persistentDataPath + "/save.flag.data")) { BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "save.flag.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 (sceneName == null) { sceneName = new HashSet<string>(); } } public void SaveFlag() { using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "save.flag.data"))) { writer.Write(flagSceneName); writer.Write(flagPos.x); writer.Write(flagPos.y); } } public void LoadBench() { string savePath = Application.persistentDataPath + "/save.flag.data"; if (File.Exists(savePath) && new FileInfo(savePath).Length > 0) { using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.flag.data"))) { flagSceneName= reader.ReadString(); flagPos.x= reader.ReadSingle(); flagPos.y= reader.ReadSingle(); } } } public void SavePlayerData() { using(BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.player.data"))) { playerHealth= PlayerController.Instance.Health; writer.Write(playerHealth); playerEnergy= PlayerController.Instance.Energy; writer.Write(playerEnergy); playerHalfEnergy = PlayerController.Instance.halfEnergy; writer.Write(playerHalfEnergy); playerPosition= PlayerController.Instance.transform.position; writer.Write(playerPosition.x); writer.Write(playerPosition.y); lastScene=SceneManager.GetActiveScene().name; writer.Write(lastScene); } } 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(); playerEnergy=reader.ReadSingle(); playerHalfEnergy=reader.ReadBoolean(); playerPosition.x=reader.ReadSingle(); playerPosition.y=reader.ReadSingle(); lastScene=reader.ReadString(); SceneManager.LoadScene(lastScene); PlayerController.Instance.transform.position=playerPosition; PlayerController.Instance.halfEnergy=playerHalfEnergy; PlayerController.Instance.Health=playerHealth; PlayerController.Instance.Energy=playerEnergy; } } else { Debug.Log("File does not exist"); PlayerController.Instance.halfEnergy=false; PlayerController.Instance.health=PlayerController.Instance.maxHealth; PlayerController.Instance.Energy = 0.5f; } } 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 rotatioX=reader.ReadSingle(); float rotatioY = reader.ReadSingle(); float rotatioZ = reader.ReadSingle(); float rotatioW = reader.ReadSingle(); shadeRot= new Quaternion(rotatioX,rotatioY,rotatioZ,rotatioW); } } else { Debug.Log("Shade does not exist"); } } }
using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; using UnityEngine.SceneManagement; public class GestorPrograma : MonoBehaviour { public static GestorPrograma Instancia { get; private set; } public GameObject audiosorce; public string transitionedFromScene; public Vector2 platformingRespawnPoint; public Vector2 respawnPoint; [SerializeField] Flag flag; public GameObject shade; public bool inicialized=false; private string utilizador; public string Utilizador { get { return utilizador; } set { utilizador = value; } } private int pontuacao; public int Pontuacao { get { return pontuacao; } set { pontuacao = value; } } private int id; public int ID { get { return id; } set { id = value; } } public float volume; public float Volume { get { return volume; } set { volume = value; } } //Verificar se sessão do utilizador já está iniciada public bool SessaoIniciada() { if(utilizador != null){ return true; } else { return false; } } //Fazer reset ao utilizador public void LoggOut() { utilizador = null; } private void Awake() { if (inicialized == false) { SaveData.Instance.Initialize(); inicialized = true; } StartCoroutine(StartingSound()); if (Instancia != null && Instancia!=this) { Destroy(gameObject); } else { Instancia = this; } if (PlayerController.Instance != null) { if (PlayerController.Instance.halfEnergy) { SaveData.Instance.LoadShadeData(); if(SaveData.Instance.sceneWithShade==SceneManager.GetActiveScene().name || SaveData.Instance.sceneWithShade == "") { Instantiate(shade, SaveData.Instance.shadePos, SaveData.Instance.shadeRot); } } } //Método que informa a aplicação para não destruir o objeto marcado quando é carregada uma cena. DontDestroyOnLoad(gameObject); flag=FindObjectOfType<Flag>(); SaveScene(); } private IEnumerator StartingSound() { AudioSource startingsound= audiosorce.GetComponent<AudioSource>(); float waitValue = (startingsound.clip.length); startingsound.Play(); yield return new WaitForSeconds(waitValue); Destroy(audiosorce); } public void RespawnPlayer() { SaveData.Instance.LoadBench(); if (SaveData.Instance.flagSceneName != null) { SceneManager.LoadScene(SaveData.Instance.flagSceneName); } if (SaveData.Instance.flagPos !=null) { respawnPoint = SaveData.Instance.flagPos; } else { respawnPoint = platformingRespawnPoint; } PlayerController.Instance.transform.position=respawnPoint; StartCoroutine(UI_Manager.Instance.DeactivateDeathScreen()); PlayerController.Instance.Respawned(); } public void SaveScene() { string currentSceneName = SceneManager.GetActiveScene().name; SaveData.Instance.sceneName.Add(currentSceneName); } }
May 30, 2024 at 12:51 am #14807Joseph Tang
Moderator::This should be because your
Initialize()
andSaveFlag()
is not saving your file paths correctly. Some of your/save._.data
is missing the/
, this difference in naming your files is causing your load save data methods to fail and go to the else statement.public void Initialize() { if (!File.Exists(Application.persistentDataPath + "/save.flag.data")) { BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.flag.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 (sceneName == null) { sceneName = new HashSet
(); } } public void SaveFlag() { using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.flag.data"))) { writer.Write(flagSceneName); writer.Write(flagPos.x); writer.Write(flagPos.y); } } May 30, 2024 at 4:22 pm #14826Mr Thinker
Participant::It still gets stuck loading after trying to load the data from the player in the file.
May 30, 2024 at 6:54 pm #14843Joseph Tang
Moderator::Do you still get the
Debug.Log("File does not exist");
command prompt when testing it out?If yes, can you send your SaveData.cs again.
If no, can you send another video with the SaveData.cs?
May 30, 2024 at 7:09 pm #14845Mr Thinker
Participant::No i dont get the error
File does not exist
He just really gets stuck in there and i suspect it has to do with something on the player script. I cannot send a video because when he tris to load the scene and gets stuck, so does the whole computer it takes a while for it to get back and stop the test. I’ll send the scriptsusing 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 related public HashSet<string> sceneName; //flag stuff public string flagSceneName; public Vector2 flagPos; //player stuff public int playerHealth; public float playerEnergy; public bool playerHalfEnergy; public Vector2 playerPosition; public string lastScene; //enemy stuff //shade public Vector2 shadePos; public string sceneWithShade; public Quaternion shadeRot; public void Initialize() { if (!File.Exists(Application.persistentDataPath + "/save.flag.data")) { BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.flag.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 (sceneName == null) { sceneName = new HashSet<string>(); } } public void SaveFlag() { using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.flag.data"))) { writer.Write(flagSceneName); writer.Write(flagPos.x); writer.Write(flagPos.y); } } public void LoadBench() { string savePath = Application.persistentDataPath + "/save.flag.data"; if (File.Exists(savePath) && new FileInfo(savePath).Length > 0) { using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.flag.data"))) { flagSceneName= reader.ReadString(); flagPos.x= reader.ReadSingle(); flagPos.y= reader.ReadSingle(); } } } public void SavePlayerData() { using(BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.player.data"))) { playerHealth= PlayerController.Instance.Health; writer.Write(playerHealth); playerEnergy= PlayerController.Instance.Energy; writer.Write(playerEnergy); playerHalfEnergy = PlayerController.Instance.halfEnergy; writer.Write(playerHalfEnergy); playerPosition= PlayerController.Instance.transform.position; writer.Write(playerPosition.x); writer.Write(playerPosition.y); lastScene=SceneManager.GetActiveScene().name; writer.Write(lastScene); } } 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(); playerEnergy=reader.ReadSingle(); playerHalfEnergy=reader.ReadBoolean(); playerPosition.x=reader.ReadSingle(); playerPosition.y=reader.ReadSingle(); lastScene=reader.ReadString(); SceneManager.LoadScene(lastScene); PlayerController.Instance.transform.position=playerPosition; PlayerController.Instance.halfEnergy=playerHalfEnergy; PlayerController.Instance.Health=playerHealth; PlayerController.Instance.Energy=playerEnergy; } } else { Debug.Log("File does not exist"); PlayerController.Instance.halfEnergy=false; PlayerController.Instance.health=PlayerController.Instance.maxHealth; PlayerController.Instance.Energy = 0.5f; } } 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 rotatioX=reader.ReadSingle(); float rotatioY = reader.ReadSingle(); float rotatioZ = reader.ReadSingle(); float rotatioW = reader.ReadSingle(); shadeRot= new Quaternion(rotatioX,rotatioY,rotatioZ,rotatioW); } } else { Debug.Log("Shade does not exist"); } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerStateList : MonoBehaviour { public bool jumping = false; public bool dashing = false; public bool recoilingX, recoilingY; public bool lookingRight; public bool invincible; public bool healing; public bool spitting; public bool exploding; public bool smashing; public bool cutscene=false; public bool alive=true; void Awake() { } }
using System; using System.Collections; using System.Diagnostics; using System.Runtime.InteropServices.WindowsRuntime; using Unity.Mathematics; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class PlayerController : MonoBehaviour { public Rigidbody2D rb; private BoxCollider2D coll; private Animator anim; public SpriteRenderer sprite; private TrailRenderer _trailRenderer; private SpriteRenderer sr; [SerializeField] private LayerMask jumpableGround; private float gravity; public float dirX=0f; bool openMap; [Header("Player Movement")] [SerializeField]private float movespeed = 3f; [SerializeField]private float jumpForce = 6.5f; private enum MovementState { idle, running, jumping, falling } [Header("Sound Effect")] [SerializeField] private AudioSource jumpSoundEffect; [SerializeField] private AudioSource walkingSoundEffect; [Header("Dashing")] [SerializeField] private float _dashingVelocity = 10f; [SerializeField] private float _dashingTime = 0.2f; private Vector2 _dashingDir; private bool _isDashing; private bool _canDash= true; [SerializeField] private AudioSource dashsoundeffect; [Header("Wall Sliding")] [SerializeField] private Transform wallCheckright; [SerializeField] private float wallSlidingSpeed; private bool isWallTouch; private bool isSliding; [Header("Wall Jumping")] private float wallJumpDirection; [SerializeField] private Vector2 wallJumpingPower= new Vector2(8f,16f); bool wallJumping; [SerializeField] private float wallJumpingTime = 0.2f; private float wallJumpingCounter; [SerializeField] private float wallJumpingDuration = 0.4f; [SerializeField] private float wallJumpWaitingTime; private bool canWallJump=true; public PlayerStateList pState; [Space(5)] [Header("Recoil")] [SerializeField] int recoilXSteps=5; [SerializeField] int recoilYSteps=5; [SerializeField] public float recoilXSpeed = 100; [SerializeField] public float recoilYSpeed = 100; private int stepsXRecoiled, stepsYRecoiled; public static PlayerController Instance; bool restoreTime; float restoreTimeSpeed; [Header("Health Settings")] public int health; [SerializeField] public int maxHealth; [SerializeField] GameObject garlicspurt; [SerializeField] float hitFlashSpeed; public delegate void OnHealthChangedDelegate(); [HideInInspector] public OnHealthChangedDelegate onHealthChangedCallback; float healTimer; [SerializeField] float timeToHeal; [Header("Energy")] [SerializeField] public float energy; [SerializeField] float energyDrainSpeed; [SerializeField] public float energyGain; [SerializeField] UnityEngine.UI.Image energyStorageFull; [SerializeField] UnityEngine.UI.Image energyStorageHalf; public bool halfEnergy; [Header("Abilities")] [Header("Spitting")] [SerializeField] float energySpittingCost = 0.3f; [SerializeField] float timeBetweenSpitt = 0.5f; float timeSinceSpit; [SerializeField] GameObject Spit; [SerializeField] float spitdamage; [Header("Self Detonation")] [SerializeField] float energyDetonationCost = 0.5f; [SerializeField] float timeBetweenExplosions = 1f; float timeSinceExplosion; [SerializeField] GameObject selfdetonation; [SerializeField] float explosiondamage; [Header("Ground Smash")] [SerializeField] float energySmashCost = 0.5f; [SerializeField] float timeBetweenSmashs = 1f; float timeSinceSmash; [SerializeField] GameObject groundsmash; [SerializeField] float smashdamage; [SerializeField] float smashforce; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } Health = maxHealth; } void Start() { rb= GetComponent<Rigidbody2D>(); coll = GetComponent<BoxCollider2D>(); anim= GetComponent<Animator>(); sprite= GetComponent<SpriteRenderer>(); _trailRenderer = GetComponent<TrailRenderer>(); pState = GetComponent<PlayerStateList>(); SaveData.Instance.LoadPlayerData(); gravity = rb.gravityScale; sr = GetComponent<SpriteRenderer>(); Energy = energy; energyStorageFull.fillAmount = energy; energyStorageHalf.fillAmount = energy; } // Update is called once per frame void Update() { if (Input.GetKeyDown(KeyCode.P)) { UnityEngine.Debug.Log("gravou"); SaveData.Instance.LoadPlayerData(); } //if (pState.cutscene) return; if (pState.alive) { var dashInput = Input.GetButtonDown("Dash"); dirX = Input.GetAxisRaw("Horizontal"); rb.velocity = new Vector2(dirX * movespeed, rb.velocity.y); if (Input.GetButtonDown("Jump") && IsGrounded()) { jumpSoundEffect.Play(); rb.velocity = new Vector2(rb.velocity.x, jumpForce); pState.jumping = true; } if (IsGrounded() && pState.jumping == true) { pState.jumping = false; } if (Input.GetKeyDown(KeyCode.M)) { ToggleMap(); } UpdateAnimationState(); WallJump(); WallSliding(); Heal(); AbiliteUsage(); } RestoreTimeScale(); FlashWhileInvincible(); } private void FixedUpdate() { if (pState.cutscene) return; if(pState.alive) { //openMap = Input.GetButtonDown("Map"); var dashInput = Input.GetButtonDown("Dash"); Dash(dashInput); Recoil(); } } private void UpdateAnimationState() { MovementState state; if (dirX > 0f) { if (!walkingSoundEffect.isPlaying && IsGrounded()) { walkingSoundEffect.Play(); } state = MovementState.running; transform.localScale = new Vector2(1, transform.localScale.y); pState.lookingRight = true; } else if (dirX < 0f) { if (!walkingSoundEffect.isPlaying && IsGrounded()) { walkingSoundEffect.Play(); } state = MovementState.running; transform.localScale = new Vector2(-1, transform.localScale.y); pState.lookingRight = false; } else { walkingSoundEffect.Stop(); state = MovementState.idle; } if(rb.velocity.y > .1f) { walkingSoundEffect.Stop(); state = MovementState.jumping; } else if(rb.velocity.y < -.1f) { walkingSoundEffect.Stop(); state = MovementState.falling; } anim.SetInteger("state", (int)state); } public bool IsGrounded() { return Physics2D.BoxCast(coll.bounds.center, coll.bounds.size, 0f, Vector2.down, .1f, jumpableGround); } private void Dash(bool dashInput) { if (dashInput && _canDash && rb.bodyType != RigidbodyType2D.Static) { _isDashing = true; pState.dashing = true; dashsoundeffect.Play(); _canDash = false; _trailRenderer.emitting = true; _dashingDir = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")); if (_dashingDir == Vector2.zero) { if (sprite.flipX == true) { _dashingDir = new Vector2(-transform.localScale.x, 0); } else { _dashingDir = new Vector2(transform.localScale.x, 0); } } StartCoroutine(StopDashing()); } anim.SetBool("IsDashing", _isDashing); if (_isDashing) { rb.velocity = _dashingDir.normalized * _dashingVelocity; } if (IsGrounded()) { _canDash = true; } } private IEnumerator StopDashing() { yield return new WaitForSeconds(_dashingTime); _trailRenderer.emitting = false; _isDashing = false; pState.dashing = false; } private void WallJump() { if(isSliding) { wallJumping = false; wallJumpDirection = -dirX; wallJumpingCounter = wallJumpingTime; CancelInvoke(nameof(StopWallJumping)); } else { wallJumpingCounter-=Time.deltaTime; } if(Input.GetButtonDown("Jump") && wallJumpingCounter > 0f&&canWallJump) { anim.SetBool("IsSliding", false); anim.Play("Player_Jumping"); jumpSoundEffect.Play(); wallJumping = true; canWallJump = false; rb.velocity = new Vector2(wallJumpDirection * wallJumpingPower.x, wallJumpingPower.y); wallJumpingCounter = 0f; Invoke(nameof(StopWallJumping), wallJumpingDuration); StartCoroutine(WaitToWallJump()); } } private IEnumerator WaitToWallJump() { yield return new WaitForSeconds(wallJumpWaitingTime); canWallJump = true; } private void WallSliding() { if (dirX > 0) { isWallTouch = Physics2D.OverlapBox(wallCheckright.position, new Vector2(0.09198731f, 0.7120864f), 0, jumpableGround); } else if (dirX < 0) { isWallTouch = Physics2D.OverlapBox(wallCheckright.position, new Vector2(0.09198731f, 0.7120864f), 0, jumpableGround); } if (isWallTouch && !IsGrounded() && dirX != 0) { isSliding = true; } else { isSliding = false; } anim.SetBool("IsSliding", isSliding); if (isSliding) { rb.velocity = new Vector2(rb.velocity.x, Mathf.Clamp(rb.velocity.y, -wallSlidingSpeed, float.MaxValue)); } } private void StopWallJumping() { wallJumping=false; } 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 (GetComponent<PlayerAttack>().dirY< 0) { rb.velocity = new Vector2(rb.velocity.x, recoilYSpeed); } else { rb.velocity = new Vector2(rb.velocity.x, -recoilYSpeed); } } else { rb.gravityScale=gravity; } if (pState.recoilingX && stepsXRecoiled < recoilXSteps) { stepsXRecoiled++; } else { StopRecoilX(); } if (pState.recoilingY && stepsYRecoiled < recoilYSteps) { stepsYRecoiled++; } else { StopRecoilY(); } if (IsGrounded()) { StopRecoilY(); } } void StopRecoilX() { stepsXRecoiled = 0; pState.recoilingX = false; } void StopRecoilY() { stepsYRecoiled = 0; pState.recoilingY = false; } 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); } public int Health { get { return health; } set { if (health != value) { health=math.clamp(value, 0, maxHealth); if(onHealthChangedCallback != null) { onHealthChangedCallback.Invoke(); } } } } void Heal() { if (Input.GetButton("Healing") && Energy>0 &&Health<maxHealth&&!pState.jumping&&!pState.dashing&&dirX==0) { pState.healing=true; anim.SetBool("isHealing", true); healTimer += Time.deltaTime; if(healTimer>=timeToHeal) { Health++; healTimer = 0; } Energy-=Time.deltaTime*energyDrainSpeed; } else { pState.healing=false; anim.SetBool("isHealing", false); healTimer = 0; } } public void TakeDamage(float _damage) { if (pState.alive) { Health -= Mathf.RoundToInt(_damage); if (Health <= 0) { Health = 0; StartCoroutine(Death()); } else { StartCoroutine(StopTakingDamage()); } } } IEnumerator StopTakingDamage() { pState.invincible = true; Vector3 pos = new Vector3(transform.position.x, transform.position.y, -1); GameObject _garlicspurt= Instantiate(garlicspurt, pos, quaternion.identity); Destroy(_garlicspurt, 1.5f); anim.SetTrigger("takeDamage"); yield return new WaitForSeconds(1f); pState.invincible = false; } void FlashWhileInvincible() { sr.material.color = pState.invincible ? Color.Lerp(Color.white, Color.black, Mathf.PingPong(Time.time * hitFlashSpeed, 1.0f)) : Color.white; } public float Energy { get { return energy; } set { if (energy != value) { if (!halfEnergy) { energy = Math.Clamp(value, 0, 1); } else { energy = Math.Clamp(value, 0, 0.5f); } energyStorageFull.fillAmount = energy; energyStorageHalf.fillAmount=energy; } } } void AbiliteUsage() { //Spitting Abilitie if(Input.GetButtonDown("Spitting") && timeSinceSpit>=timeBetweenSpitt&& energy >= energySpittingCost) { pState.spitting = true; timeSinceSpit = 0; StartCoroutine(AbilitieUsage()); } else { timeSinceSpit += Time.deltaTime; } //Ground Smash Abilitie if (Input.GetButtonDown("Ground Smash") && timeSinceSmash >= timeBetweenSmashs && energy >= energySmashCost) { pState.smashing = true; timeSinceSmash = 0; StartCoroutine(AbilitieUsage()); } else { timeSinceSmash += Time.deltaTime; } //Self Detonation Abilitie if (Input.GetButtonDown("Self Detonation") && timeSinceExplosion >= timeBetweenExplosions && energy >= energyDetonationCost) { pState.exploding = true; timeSinceExplosion = 0; StartCoroutine(AbilitieUsage()); } else { timeSinceExplosion += Time.deltaTime; } if (IsGrounded()) { groundsmash.SetActive(false); } if (groundsmash.activeInHierarchy) { rb.velocity += smashforce * Vector2.down; } } IEnumerator AbilitieUsage() { if(pState.spitting) { anim.SetBool("Spitting", true); if(GetComponent<PlayerAttack>().dirY==0 || (GetComponent<PlayerAttack>().dirY<0&& IsGrounded())) { GameObject _spit = Instantiate(Spit, GetComponent<PlayerAttack>().SideAttackTransformRight.position , Quaternion.identity); if (pState.lookingRight) { _spit.transform.eulerAngles=Vector3.zero; } else { _spit.transform.eulerAngles = new Vector3(_spit.transform.eulerAngles.x, 180); } pState.recoilingX = true; Energy -= energySpittingCost; } yield return new WaitForSeconds(0.5f); anim.SetBool("Spitting", false); pState.spitting = false; } else if(pState.exploding) { anim.SetBool("isExploding", true); Instantiate(selfdetonation, transform); rb.velocity=Vector2.zero; Energy -= energyDetonationCost; yield return new WaitForSeconds(0.40f); anim.SetBool("isExploding", false); pState.exploding = false; } else if(pState.smashing) { if(GetComponent<PlayerAttack>().dirY < 0 && !IsGrounded()) { groundsmash.SetActive(true); Energy -= energySmashCost; } pState.smashing = false; } } private void OnTriggerEnter2D(Collider2D _other) { if (_other.GetComponent<Enemy>() != null) { if (pState.spitting) { _other.GetComponent<Enemy>().EnemyHit(spitdamage, (_other.transform.position - transform.position).normalized, -recoilYSpeed); } if (pState.exploding) { _other.GetComponent<Enemy>().EnemyHit(explosiondamage, (_other.transform.position - transform.position).normalized, -recoilYSpeed); } if (pState.smashing) { _other.GetComponent<Enemy>().EnemyHit(smashdamage, (_other.transform.position - transform.position).normalized, -recoilYSpeed); } } } public IEnumerator WalkIntoNewScene(Vector2 _exitDir, float _delay) { //IF exit direction is upwards if (_exitDir.y > 0) { rb.velocity = jumpForce * _exitDir; } if (_exitDir.x != 0) { dirX=_exitDir.x >0 ? 1 : -1; } UpdateAnimationState(); yield return new WaitForSeconds(_delay); pState.cutscene = false; } IEnumerator Death() { pState.alive = false; Time.timeScale = 1f; GameObject _garlicspurt = Instantiate(garlicspurt, transform.position, Quaternion.identity); Destroy(_garlicspurt, 1.5f); anim.SetTrigger("death"); yield return new WaitForSeconds(0.9f); StartCoroutine(UI_Manager.Instance.ActivateDeathScreen()); yield return new WaitForSeconds(0.9f); Instantiate(GestorPrograma.Instancia.shade, transform.position, Quaternion.identity); } public void Respawned() { if (!pState.alive) { pState.alive=true; halfEnergy=true; UI_Manager.Instance.SwitchEnergy(UI_Manager.EnergyState.HalfEnergy); Energy = 0; energyStorageFull.fillAmount = Energy; energyStorageHalf.fillAmount = Energy; Health = maxHealth; anim.Play("Player_Idle"); } } public void RestoreEnergy() { halfEnergy=false; UI_Manager.Instance.SwitchEnergy(UI_Manager.EnergyState.FullEnergy); } void ToggleMap() { openMap = !openMap; UI_Manager.Instance.mapHandler.SetActive(openMap); } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UIElements; public class PlayerAttack : MonoBehaviour { private Animator anim; public float dirY = 0f; [SerializeField] float timeBetweenAttack, timeSinceAttack; bool attack = false; [SerializeField] public Transform SideAttackTransformRight, UpAttackTransform, DownAttackTransform; [SerializeField] Vector2 SideAttackAreaRight, UpAttackArea, DownAttackArea; [SerializeField] LayerMask attackabelMask; [SerializeField] float damage; [SerializeField] GameObject slashEffect; void Start() { anim = GetComponent<Animator>(); } void Update() { dirY = Input.GetAxisRaw("Vertical"); attack = Input.GetButtonDown("Attack"); if (GameObject.Find("Player").GetComponent<PlayerController>().pState.alive) { Attack(); } } void Attack() { timeSinceAttack += Time.deltaTime; if(attack&& timeSinceAttack >= timeBetweenAttack) { timeSinceAttack = 0; anim.SetTrigger("Attacking"); if (dirY==0|| dirY<0&& GameObject.Find("Player").GetComponent<PlayerController>().IsGrounded()&& GameObject.Find("Player").GetComponent<PlayerController>().pState.lookingRight) { int _recoilLeftOrRight = GetComponent<PlayerController>().pState.lookingRight ? 1 : -1; Hit(SideAttackTransformRight, SideAttackAreaRight, ref GetComponent<PlayerController>().pState.recoilingX,Vector2.right*_recoilLeftOrRight,GetComponent<PlayerController>().recoilXSpeed); Instantiate(slashEffect, SideAttackTransformRight); } else if (dirY > 0) { Hit(UpAttackTransform, UpAttackArea, ref GetComponent<PlayerController>().pState.recoilingY, Vector2.up, GetComponent<PlayerController>().recoilYSpeed); SlashEffectAtAngle(slashEffect, 90, UpAttackTransform); } else if (dirY < 0 && !GameObject.Find("Player").GetComponent<PlayerController>().IsGrounded()) { Hit(DownAttackTransform, DownAttackArea, ref GetComponent<PlayerController>().pState.recoilingY,Vector2.down, GetComponent<PlayerController>().recoilYSpeed); SlashEffectAtAngle(slashEffect, -90, DownAttackTransform); } } } private void OnDrawGizmos() { Gizmos.color = Color.red; Gizmos.DrawWireCube(SideAttackTransformRight.position, SideAttackAreaRight); Gizmos.DrawWireCube(UpAttackTransform.position, UpAttackArea); Gizmos.DrawWireCube(DownAttackTransform.position, DownAttackArea); } private void Hit(Transform _AttackTransform, Vector2 _AttackArea,ref bool _recoilBool, Vector2 _recoilDir, float _recoilStrenght) { Collider2D[] objectsToHit = Physics2D.OverlapBoxAll(_AttackTransform.position, _AttackArea, 0, attackabelMask); if (objectsToHit.Length > 0) { _recoilBool = true; } for (int i = 0; i < objectsToHit.Length; i++) { if (objectsToHit[i].GetComponent<Enemy>() != null) { objectsToHit[i].GetComponent<Enemy>().EnemyHit(damage, _recoilDir,_recoilStrenght); if (objectsToHit[i].CompareTag("Enemy")) { PlayerController.Instance.Energy += PlayerController.Instance.energyGain; } } } } 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); } }
using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; using UnityEngine.SceneManagement; public class GestorPrograma : MonoBehaviour { public static GestorPrograma Instancia { get; private set; } public GameObject audiosorce; public string transitionedFromScene; public Vector2 platformingRespawnPoint; public Vector2 respawnPoint; [SerializeField] Flag flag; public GameObject shade; public bool inicialized=false; private string utilizador; public string Utilizador { get { return utilizador; } set { utilizador = value; } } private int pontuacao; public int Pontuacao { get { return pontuacao; } set { pontuacao = value; } } private int id; public int ID { get { return id; } set { id = value; } } public float volume; public float Volume { get { return volume; } set { volume = value; } } //Verificar se sessão do utilizador já está iniciada public bool SessaoIniciada() { if(utilizador != null){ return true; } else { return false; } } //Fazer reset ao utilizador public void LoggOut() { utilizador = null; } private void Awake() { if (inicialized == false) { SaveData.Instance.Initialize(); inicialized = true; } StartCoroutine(StartingSound()); if (Instancia != null && Instancia!=this) { Destroy(gameObject); } else { Instancia = this; } if (PlayerController.Instance != null) { if (PlayerController.Instance.halfEnergy) { SaveData.Instance.LoadShadeData(); if(SaveData.Instance.sceneWithShade==SceneManager.GetActiveScene().name || SaveData.Instance.sceneWithShade == "") { Instantiate(shade, SaveData.Instance.shadePos, SaveData.Instance.shadeRot); } } } //Método que informa a aplicação para não destruir o objeto marcado quando é carregada uma cena. DontDestroyOnLoad(gameObject); flag=FindObjectOfType<Flag>(); SaveScene(); } private IEnumerator StartingSound() { AudioSource startingsound= audiosorce.GetComponent<AudioSource>(); float waitValue = (startingsound.clip.length); startingsound.Play(); yield return new WaitForSeconds(waitValue); Destroy(audiosorce); } public void RespawnPlayer() { SaveData.Instance.LoadBench(); if (SaveData.Instance.flagSceneName != null) { SceneManager.LoadScene(SaveData.Instance.flagSceneName); } if (SaveData.Instance.flagPos !=null) { respawnPoint = SaveData.Instance.flagPos; } else { respawnPoint = platformingRespawnPoint; } PlayerController.Instance.transform.position=respawnPoint; StartCoroutine(UI_Manager.Instance.DeactivateDeathScreen()); PlayerController.Instance.Respawned(); } public void SaveScene() { string currentSceneName = SceneManager.GetActiveScene().name; SaveData.Instance.sceneName.Add(currentSceneName); } }
May 30, 2024 at 11:32 pm #14847Joseph Tang
Moderator::Try commenting out these 2:
GestorPrograma.cs
private void Awake() { if (inicialized == false) { //SaveData.Instance.Initialize(); inicialized = true; } StartCoroutine(StartingSound()); ... if (PlayerController.Instance != null) { if (PlayerController.Instance.halfEnergy) { //SaveData.Instance.LoadShadeData(); /*if(SaveData.Instance.sceneWithShade==SceneManager.GetActiveScene().name || SaveData.Instance.sceneWithShade == "") { Instantiate(shade, SaveData.Instance.shadePos, SaveData.Instance.shadeRot); }*/ } } ... flag=FindObjectOfType
(); //SaveScene(); } PlayerController.cs
void Start() { rb= GetComponent
(); coll = GetComponent (); anim= GetComponent (); sprite= GetComponent (); _trailRenderer = GetComponent (); pState = GetComponent (); //SaveData.Instance.LoadPlayerData(); gravity = rb.gravityScale; sr = GetComponent (); Energy = energy; energyStorageFull.fillAmount = energy; energyStorageHalf.fillAmount = energy; }
Then try playing.
If you can play the game, then add this into your SaveData.cs and GestorPrograma.cs:SaveData.cs
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(); }
GestorPrograma.cs
private void Awake() { ... SaveData.Instance.DeleteAllSaveData() }
After you try playing the game with that new code, it should delete your save files. Once deleted and everything is fine, remove all the comments in the first part.
Once you remove the comments, go to your PlayerController.cs and move your
LoadPlayerData()
to the bottom ofStart()
.
This should make sure that even if your player does not load any correct values, as your save files are empty, the player should start the game with the rest of the code inStart()
functional.PlayerController.cs
void Start() { ... pState = GetComponent
(); SaveData.Instance.LoadPlayerData();gravity = rb.gravityScale; ... SaveData.Instance.LoadPlayerData(); }May 30, 2024 at 11:42 pm #14848Mr Thinker
Participant::It worked thank you. But i am experiencing problems with the Respawn button, it wourl not let me click it, i’ve alreday tries to solve the problem with other posts but it seems to not let me use it, could you help me with this?
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class UI_Manager : MonoBehaviour { public static UI_Manager Instance; public SceneFader sceneFader; [SerializeField] GameObject deathScreen; public GameObject mapHandler; [SerializeField] GameObject halfEnergy, fullEnergy; [SerializeField] public Image halfEnergyImage, fullEnergyImage; public enum EnergyState { FullEnergy, HalfEnergy } public EnergyState energyState; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } DontDestroyOnLoad(gameObject); } private void Start() { sceneFader = GetComponentInChildren<SceneFader>(); } public IEnumerator ActivateDeathScreen() { yield return new WaitForSeconds(0.8f); StartCoroutine(sceneFader.Fade(SceneFader.FadeDirection.In)); yield return new WaitForSeconds(0.8f); deathScreen.SetActive(true); } public IEnumerator DeactivateDeathScreen() { yield return new WaitForSeconds(0.5f); deathScreen.SetActive(false); StartCoroutine(sceneFader.Fade(SceneFader.FadeDirection.Out)); } public void SwitchEnergy(EnergyState _energyState) { switch (_energyState) { case EnergyState.FullEnergy: halfEnergy.SetActive(false); fullEnergy.SetActive(true); break; case EnergyState.HalfEnergy: halfEnergy.SetActive(true); fullEnergy.SetActive(false); break; } energyState = _energyState; } }
using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; using UnityEngine.SceneManagement; public class GestorPrograma : MonoBehaviour { public static GestorPrograma Instancia { get; private set; } public GameObject audiosorce; public string transitionedFromScene; public Vector2 platformingRespawnPoint; public Vector2 respawnPoint; [SerializeField] Flag flag; public GameObject shade; public bool inicialized=false; private string utilizador; public string Utilizador { get { return utilizador; } set { utilizador = value; } } private int pontuacao; public int Pontuacao { get { return pontuacao; } set { pontuacao = value; } } private int id; public int ID { get { return id; } set { id = value; } } public float volume; public float Volume { get { return volume; } set { volume = value; } } //Verificar se sessão do utilizador já está iniciada public bool SessaoIniciada() { if(utilizador != null){ return true; } else { return false; } } //Fazer reset ao utilizador public void LoggOut() { utilizador = null; } private void Awake() { if (inicialized == false) { SaveData.Instance.Initialize(); inicialized = true; } StartCoroutine(StartingSound()); if (Instancia != null && Instancia!=this) { Destroy(gameObject); } else { Instancia = this; } if (PlayerController.Instance != null) { if (PlayerController.Instance.halfEnergy) { SaveData.Instance.LoadShadeData(); if(SaveData.Instance.sceneWithShade==SceneManager.GetActiveScene().name || SaveData.Instance.sceneWithShade == "") { Instantiate(shade, SaveData.Instance.shadePos, SaveData.Instance.shadeRot); } } } //Método que informa a aplicação para não destruir o objeto marcado quando é carregada uma cena. DontDestroyOnLoad(gameObject); flag=FindObjectOfType<Flag>(); SaveScene(); } private IEnumerator StartingSound() { AudioSource startingsound= audiosorce.GetComponent<AudioSource>(); float waitValue = (startingsound.clip.length); startingsound.Play(); yield return new WaitForSeconds(waitValue); Destroy(audiosorce); } public void RespawnPlayer() { SaveData.Instance.LoadBench(); if (SaveData.Instance.flagSceneName != null) { SceneManager.LoadScene(SaveData.Instance.flagSceneName); } if (SaveData.Instance.flagPos !=null) { respawnPoint = SaveData.Instance.flagPos; } else { respawnPoint = platformingRespawnPoint; } PlayerController.Instance.transform.position=respawnPoint; StartCoroutine(UI_Manager.Instance.DeactivateDeathScreen()); PlayerController.Instance.Respawned(); } public void SaveScene() { string currentSceneName = SceneManager.GetActiveScene().name; SaveData.Instance.sceneName.Add(currentSceneName); } }
May 31, 2024 at 1:15 am #14851Joseph Tang
Moderator::How is your button not working?
As in, can you click your button and it doesn’t function?
Or is any and all interaction with the button, like hovering and getting a change in colour, not working?In any case, Check if your scene has an
EventSystem
:
If this does not solve the issue, it may be that it has something to do with the second warning prompt you get in the command box. Something about your Animation Event not being received, which should mean you’re missing some form of MonoBehaviour script on the player.
If possible, could you send a video instead of a screenshot for testing out the button?
May 31, 2024 at 10:26 pm #14882Mr Thinker
Participant::I forgot to add the EventSystem, thank you so much for your help, this series is a life saver and you guys are to.
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: