Forum begins after the advertisement:
Big heart in the center scene and save didn’t save the Max hearth
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › Big heart in the center scene and save didn’t save the Max hearth
- This topic has 10 replies, 2 voices, and was last updated 1 month, 1 week ago by pepecry.
-
AuthorPosts
-
November 9, 2024 at 1:11 am #16279::
So i’m making the heart collection function. The fill, the save look good but after i collect 4 heart to increase the max health. It has increase but when I exit the game and replay it, the max health turn back to basic health. Same as saved with the Alter(bench).
Another problem that is the heart showup in the center of the game like the image belowThis heart only disapear after I take the heartshard.Update, I forgot to turn off the Canvas in the HeatShard. Still need your help to figure all why the max health didn’t save. Here is the script of the SaveData, HeartShard and increaseMaxHealth.<code>using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using UnityEngine.SceneManagement; [System.Serializable] public struct SaveData { public static SaveData Instance; public HashSet<string> sceneNames; public string altersceneName; public Vector2 alterPos; public int playerHealth; public int playerHeartShards; public float playerMana; public Vector2 playerPosition; public string lastScene; public bool playerUnlockWallJump; public void Initialize() { if (!File.Exists(Application.persistentDataPath + "/save.alter.data")) { BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.alter.data")); } if (!File.Exists(Application.persistentDataPath + "/save.player.data")) { BinaryWriter writer = new BinaryWriter(File.Create(Application.persistentDataPath + "/save.player.data")); } if (sceneNames == null) { sceneNames = new HashSet<string>(); } } public void saveAlter() { using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.alter.data"))) { writer.Write(altersceneName); writer.Write(alterPos.x); writer.Write(alterPos.y); } } public void loadAlter() { if (File.Exists(Application.persistentDataPath + "/save.alter.data")) { using(BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.alter.data"))) { altersceneName = reader.ReadString(); alterPos.x = reader.ReadSingle(); alterPos.y = reader.ReadSingle(); } } } public void savePlayerData() { using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.player.data"))) { playerHealth = Move.Instance.Health; writer.Write(playerHealth); playerMana = Move.Instance.Mana; writer.Write(playerMana); playerUnlockWallJump = Move.Instance.unlockWalljump; writer.Write(playerUnlockWallJump); playerPosition = Move.Instance.transform.position; writer.Write(playerPosition.x); writer.Write(playerPosition.y); lastScene = SceneManager.GetActiveScene().name; writer.Write(lastScene); playerHeartShards = Move.Instance.heartShards; writer.Write(playerHeartShards); } } public void loadPlayerData() { if(File.Exists(Application.persistentDataPath + "/save.player.data")) { using(BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.player.data"))) { playerHealth = reader.ReadInt32(); playerMana = reader.ReadSingle(); playerUnlockWallJump = reader.ReadBoolean(); playerPosition.x = reader.ReadSingle(); playerPosition.y = reader.ReadSingle(); lastScene = reader.ReadString(); playerHeartShards = reader.ReadInt32(); SceneManager.LoadScene(lastScene); Move.Instance.transform.position = playerPosition; Move.Instance.Health = playerHealth; Move.Instance.Mana = playerMana; Move.Instance.unlockWalljump = playerUnlockWallJump; Move.Instance.heartShards = playerHeartShards; } Debug.Log("load player Data"); } else { Debug.Log("File doesn't exist"); Move.Instance.Health = Move.Instance.MaxHealth; Move.Instance.heartShards = 0; Move.Instance.Mana = 0.5f; Move.Instance.unlockWalljump = false; } } } </code>
<code>using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class HeartShards : MonoBehaviour { public Image fill; public float targetFillAmount; public float lerpDuration= 1.5f; public float initalFillAmount; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } public IEnumerator LerpFill() { float elapseTime = 0f; while(elapseTime < lerpDuration) { elapseTime += Time.deltaTime; float t = Mathf.Clamp01(elapseTime / lerpDuration); float lerpFillAmount = Mathf.Lerp(initalFillAmount, targetFillAmount, t); fill.fillAmount = lerpFillAmount; yield return null; } fill.fillAmount = targetFillAmount; if(fill.fillAmount == 1) { Move.Instance.MaxHealth++; Move.Instance.onHealthChangedCallback(); Move.Instance.heartShards = 0; } } } </code>
<code>using System.Collections; using System.Collections.Generic; using UnityEngine; public class IncreaseMaxHealth : MonoBehaviour { // Start is called before the first frame update [SerializeField] GameObject canvasUI; bool used; [SerializeField] HeartShards heartShards; void Start() { if (Move.Instance.MaxHealth >= Move.Instance.maxTotalHealth) { Destroy(gameObject); } } // Update is called once per frame private void OnTriggerEnter2D(Collider2D collision) { if (collision.CompareTag("Player") && !used) { used = true; StartCoroutine(ShowUI()); } } IEnumerator ShowUI() { yield return new WaitForSeconds(0.5f); canvasUI.SetActive(true); heartShards.initalFillAmount = Move.Instance.heartShards * 0.25f; Move.Instance.heartShards++; heartShards.targetFillAmount = Move.Instance.heartShards * 0.25f; Move.Instance.unlockWalljump = true; StartCoroutine(heartShards.LerpFill()); yield return new WaitForSeconds(2.5f); SaveData.Instance.savePlayerData(); canvasUI.SetActive(false); Destroy(gameObject); } } </code>
And the heartcontainer as well
<code>using System.Collections; using System.Collections.Generic; using UnityEngine.UI; using UnityEngine; public class HeartController : MonoBehaviour { Move Player; private GameObject[] heartContainer; private Image[] heartFill; public Transform heartParent; public GameObject heartContainerPrefab; // Start is called before the first frame update void Start() { Player = Move.Instance; heartContainer = new GameObject[Move.Instance.maxTotalHealth]; heartFill = new Image[Move.Instance.maxTotalHealth]; Move.Instance.onHealthChangedCallback += updateHeartHUD; InstantiateHeartContainer(); updateHeartHUD(); } // Update is called once per frame void Update() { } void SetHeartContainer() { for (int i = 0; i < heartContainer.Length; i++) { if (i < Move.Instance.MaxHealth) { heartContainer[i].SetActive(true); } else { heartContainer[i].SetActive(false); } } } void SetFilledHeart() { for (int i = 0; i < heartFill.Length; i++) { if (i < Move.Instance.Health) { heartFill[i].fillAmount = 1; } else { heartFill[i].fillAmount = 0; } } } void InstantiateHeartContainer() { for(int i = 0; i < Move.Instance.maxTotalHealth; i++) { GameObject temp = Instantiate(heartContainerPrefab); temp.transform.SetParent(heartParent, false); heartContainer[i] = temp; heartFill[i] = temp.transform.Find("heartfill").GetComponent<Image>(); } } void updateHeartHUD() { SetHeartContainer(); SetFilledHeart(); } } </code>
Thank you guys
November 9, 2024 at 4:55 pm #16287November 9, 2024 at 9:05 pm #16288::Yes. I have. As you could see in the record. I have saved my character and the console has log out that max health record
has upvoted this post. November 10, 2024 at 1:35 pm #16290::Put a debug message on your
loadPlayerData
function. Let’s check whether the values are correctly loaded:public void loadPlayerData() { if(File.Exists(Application.persistentDataPath + "/save.player.data")) { using(BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.player.data"))) { playerHealth = reader.ReadInt32(); playerMana = reader.ReadSingle(); playerUnlockWallJump = reader.ReadBoolean(); playerPosition.x = reader.ReadSingle(); playerPosition.y = reader.ReadSingle(); lastScene = reader.ReadString(); playerHeartShards = reader.ReadInt32(); SceneManager.LoadScene(lastScene); Move.Instance.transform.position = playerPosition; Move.Instance.Health = playerHealth; Move.Instance.Mana = playerMana; Move.Instance.unlockWalljump = playerUnlockWallJump; Move.Instance.heartShards = playerHeartShards; print("Loaded position: " + playerPosition); print("Loaded health: " + playerHealth); print("Loaded mana: " + playerMana); print("Loaded unlock wall jump: " + playerUnlockWallJump); print("Loaded heart shards: " + playerHeartShards); } Debug.Log("load player Data"); } else { Debug.Log("File doesn't exist"); Move.Instance.Health = Move.Instance.MaxHealth; Move.Instance.heartShards = 0; Move.Instance.Mana = 0.5f; Move.Instance.unlockWalljump = false; } }
November 10, 2024 at 5:23 pm #16291::So when the game start. the console show up this
After I get 1 heartshard. And save. The game could save the heartShard like in the second pic But then I get all the shard to have 1 additional hearth and then save, the game still load only 4 health just like the first picture. I also try to change the Health to health in savePlayerData and loadPlayerData but not working thoughtplayerHealth = Move.Instance.health;
Move.Instance.health = playerHealth;
I will put the player controller here if you need<code>using System; using System.Collections; using System.Collections.Generic; using Unity.Mathematics; using UnityEditor.Tilemaps; using UnityEngine; using UnityEngine.UI; [RequireComponent(typeof(Rigidbody2D))] public class Move : MonoBehaviour { //animation and physic [Header("physic of player")] public Rigidbody2D rbd2; [SerializeField] public float speed = 2.0f; private float xAxis, yAxis; [SerializeField] private float jumpForce = 10; private int dbJumpCounter; [SerializeField] private int maxdbJump = 1; [Space(5)] [Header("Groundcheck setting")] [SerializeField] private Transform groundcheck; [SerializeField] private float groundchecky = 0.2f; [SerializeField] private float groundcheckx = 0.5f; [SerializeField] private LayerMask isground; Animator animator; [HideInInspector] public PlayerStateList playerStateList; [Space(5)] [Header("Coyotetime setting")] [SerializeField] private float coyoteTime = 0.1f; private float coyoteTimeCounter = 0; [Space(5)] [Header("Attacking setting")] [SerializeField] private float timeBetweenattck; [SerializeField] Transform sideAttackTransform, upAttackTransform, downAttackTransform; [SerializeField] Vector2 sideAttackArea, upAttackArea, downAttackArea; [SerializeField] LayerMask attackableLayer; [SerializeField] float playerDmg; private float timeSinceattk; bool attk = false; [Space(5)] [Header("Health Setting")] [SerializeField] public int health; [SerializeField] public int MaxHealth; [SerializeField] GameObject bloodSpurt; [SerializeField] float hitFlashspeed; public delegate void OnHealthChangedDelegate(); [HideInInspector] public OnHealthChangedDelegate onHealthChangedCallback; [SerializeField] float timetoHeal; float healTimer; public int maxTotalHealth = 10; public int heartShards; [Space(5)] [Header("Dash setting")] [SerializeField] private float dashSpeed; [SerializeField] private float dashTime; [SerializeField] private float dashCD; private bool canDash = true; private bool dashed; [Space(5)] [Header("Recoil")] [SerializeField] int recoilXSteps = 5; [SerializeField] int recoilYSteps = 5; [SerializeField] float recoilXSpeed = 100; [SerializeField] float recoilYSpeed = 100; int stepXrecoiled, stepYrecoiled; [Space(5)] [Header("Mana Setting")] [SerializeField] float mana; [SerializeField] float manaDrain; [SerializeField] float manaGain; [SerializeField] UnityEngine.UI.Image manaStorage; [Space(5)] [Header("Spellcasting")] [SerializeField] float manaSpellcost = 0.3f; [SerializeField] float timeBetweencast = 0.5f; float timeSincecast; float castOrhealTimer; [SerializeField] float spellDmg; //dark rising and skyfall only [SerializeField] float skyfallForce; // force for skyfall [SerializeField] GameObject sideSpellDarkBall; [SerializeField] GameObject upSpellDarkRising; [SerializeField] GameObject downSpellSkyFall; [Space(5)] [Header("Walljump")] [SerializeField] private float wallSlidingSpeed = 2f; [SerializeField] private Transform wallCheck; [SerializeField] private LayerMask wallLayer; [SerializeField] private float wallJumpingDuration; [SerializeField] private Vector2 wallJumpPow; float wallJumpDirection; bool iswallSliding; bool iswallJumping; public bool unlockWalljump = false; [Space(5)] bool restoreTime; float restoreTimeSpeed; private SpriteRenderer spriteRenderer; public static Move Instance; private float gravity; bool openMap; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } DontDestroyOnLoad(gameObject); } // Start is called before the first frame update private void Start() { //player game object playerStateList = GetComponent<PlayerStateList>(); rbd2 = GetComponent<Rigidbody2D>(); animator = GetComponent<Animator>(); spriteRenderer = GetComponent<SpriteRenderer>(); gravity = rbd2.gravityScale; Mana = mana; manaStorage.fillAmount = Mana; Health = MaxHealth; SaveData.Instance.loadPlayerData(); if(Health == 0) { playerStateList.alive = false; GameManager.Instance.respawnPlayer(); } } private void OnDrawGizmos() { Gizmos.color = Color.yellow; Gizmos.DrawWireCube(sideAttackTransform.position, sideAttackArea); Gizmos.DrawWireCube(upAttackTransform.position, upAttackArea); Gizmos.DrawWireCube(downAttackTransform.position, downAttackArea); } // Update is called once per frame private void Update() { if (playerStateList.incutscene) return; if(playerStateList.alive) { getInput(); OpenMap(); } UpdateJump(); RestoreTimeScale(); if (playerStateList.dashing) return; FlashWhenInvi(); if (playerStateList.alive){ if (!iswallJumping) { Moving(); Flip(); Jump(); } }; Heal(); CastSpell(); if (playerStateList.healing) return; if (unlockWalljump) { WallSlide(); WallJump(); } WallSlide(); WallJump(); StartDash(); Attack(); } private void OnTriggerEnter2D(Collider2D _other) { if (_other.GetComponent<Enemy>() != null && playerStateList.castspell) { _other.GetComponent<Enemy>().EnemyHit(spellDmg, (_other.transform.position - _other.transform.position).normalized, -recoilYSpeed); } } private void FixedUpdate() { if (playerStateList.incutscene) return; if (playerStateList.dashing) return; Recoil(); } void getInput() { xAxis = Input.GetAxisRaw("Horizontal"); yAxis = Input.GetAxisRaw("Vertical"); attk = Input.GetButtonDown("Attack"); openMap = Input.GetButton("Map"); if (Input.GetButton("Cast/Heal")) { castOrhealTimer += Time.deltaTime; } else { castOrhealTimer = 0; } } //player Attack void Attack() { timeSinceattk += Time.deltaTime; if (attk && timeSinceattk >= timeBetweenattck) { timeSinceattk = 0; animator.SetTrigger("Attacking"); if (yAxis == 0 || yAxis < 0 && isonGround()) { int _recoilLeftorRight = playerStateList.lookingRight ? 1 : -1; Hit(sideAttackTransform, sideAttackArea, ref playerStateList.recoilingX, recoilXSpeed, Vector2.right * _recoilLeftorRight); } else if (yAxis > 0) { Hit(upAttackTransform, upAttackArea, ref playerStateList.recoilingY, recoilYSpeed, Vector2.up); } else if (yAxis < 0 && !isonGround()) { Hit(downAttackTransform, downAttackArea, ref playerStateList.recoilingY, recoilYSpeed, Vector2.down); } } } //Using for the character recoil void Recoil() { if (playerStateList.recoilingX) { if (playerStateList.lookingRight) { rbd2.velocity = new Vector2(-recoilXSpeed, 0); } else { rbd2.velocity = new Vector2(recoilXSpeed, 0); } } if (playerStateList.recoilingY) { rbd2.gravityScale = 0; if (yAxis < 0) { rbd2.velocity = new Vector2(rbd2.velocity.x, recoilYSpeed); } else { rbd2.velocity = new Vector2(rbd2.velocity.x, -recoilYSpeed); } dbJumpCounter = 0; } else { rbd2.gravityScale = gravity; } //Stop recoil X if (playerStateList.recoilingX && stepXrecoiled < recoilXSteps) { stepXrecoiled++; } else { StopRecoilX(); } //Stop recoil Y if (playerStateList.recoilingY && stepYrecoiled < recoilYSteps) { stepYrecoiled++; } else { StopRecoilY(); } // if hit ground stop recoil Y if (isonGround()) { StopRecoilY(); } } void StopRecoilX() { stepXrecoiled = 0; playerStateList.recoilingX = false; } void StopRecoilY() { stepYrecoiled = 0; playerStateList.recoilingY = false; } //player hit check void Hit(Transform _attackTransform, Vector2 _attackArea, ref bool _recoilBool, float _recoilStrenght, Vector2 _recoilDir) { Collider2D[] objecttoHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer); if (objecttoHit.Length > 0) { _recoilBool = true; } for (int i = 0; i < objecttoHit.Length; i++) { if (objecttoHit[i].GetComponent<Enemy>() != null) { objecttoHit[i].GetComponent<Enemy>().EnemyHit(playerDmg, _recoilDir, _recoilStrenght); if (objecttoHit[i].CompareTag("Enemy")) { Mana += manaGain; } } } } //change dir of the player void Flip() { if (xAxis < 0) { transform.localScale = new Vector2(-1, transform.localScale.y); playerStateList.lookingRight = false; } else if (xAxis > 0) { transform.localScale = new Vector2(1, transform.localScale.y); playerStateList.lookingRight = true; } } // start the dash void StartDash() { if (Input.GetButtonDown("Dash") && canDash && !dashed) { StartCoroutine(Dash()); dashed = true; } if (isonGround()) { dashed = false; } } IEnumerator Dash() { canDash = false; playerStateList.dashing = true; animator.SetTrigger("Dashing"); rbd2.gravityScale = 0; int _dir = playerStateList.lookingRight ? 1 : -1; rbd2.velocity = new Vector2(_dir * dashSpeed, 0); yield return new WaitForSeconds(dashTime); rbd2.gravityScale = gravity; playerStateList.dashing = false; yield return new WaitForSeconds(dashCD); canDash = true; } //moving of player private void Moving() { //if(playerStateList.healing) rbd2.velocity = new Vector2(0,0); rbd2.velocity = new Vector2(speed * xAxis, rbd2.velocity.y); animator.SetBool("Walking", rbd2.velocity.x != 0 && isonGround()); } //check if player is on the ground or not public bool isonGround() { if (Physics2D.Raycast(groundcheck.position, Vector2.down, groundchecky, isground) || Physics2D.Raycast(groundcheck.position + new Vector3(groundcheckx, 0, 0), Vector2.down, groundchecky, isground) || Physics2D.Raycast(groundcheck.position + new Vector3(-groundcheckx, 0, 0), Vector2.down, groundchecky, isground) ) { return true; } else { return false; } } //player jump void Jump() { if (Input.GetButtonDown("Jump") && coyoteTimeCounter > 0) { rbd2.velocity = new Vector3(rbd2.velocity.x, jumpForce); /* playerStateList.Jumping = true;*/ } else if (!isonGround() && dbJumpCounter < maxdbJump && Input.GetButtonDown("Jump")) { dbJumpCounter++; rbd2.velocity = new Vector3(rbd2.velocity.x, jumpForce); } animator.SetBool("Jumping", !isonGround()); } void UpdateJump() { if (isonGround()) { /* playerStateList.Jumping = false;*/ coyoteTimeCounter = coyoteTime; dbJumpCounter = 0; } else { coyoteTimeCounter -= Time.deltaTime; } } //stop taking dmg when player get hit IEnumerator StopTakingDmg() { playerStateList.Invi = true; GameObject _bloodSpurtParticles = Instantiate(bloodSpurt, transform.position, Quaternion.identity); Destroy(_bloodSpurtParticles, 1f); animator.SetTrigger("TakeDmg"); yield return new WaitForSeconds(1f); playerStateList.Invi = false; } //player health calculated public int Health { get { return health; } set { if (health != value) { health = Mathf.Clamp(value, 0, MaxHealth); if (onHealthChangedCallback != null) { onHealthChangedCallback.Invoke(); } } } } public float Mana { get { return mana; } set { if (mana != value) { mana = Mathf.Clamp(value, 0, 1); manaStorage.fillAmount = Mana; } } } //take dmg function public void takeDmg(float _Dmg) { if (playerStateList.alive) { Health -= Mathf.RoundToInt(_Dmg); if(Health <= 0) { Health = 0; StartCoroutine(Death()); } else { StartCoroutine(StopTakingDmg()); } } } //time delay for player when get hit public void HitStopTime(float _newTimeScale, int _restoreSpeed, float _delay) { restoreTimeSpeed = _restoreSpeed; Time.timeScale = _newTimeScale; if (_delay > 0) { StopCoroutine(TimeStartAgain(_delay)); StartCoroutine(TimeStartAgain(_delay)); } else { restoreTime = true; } } void RestoreTimeScale() { if (restoreTime) { if (Time.timeScale < 1) { Time.timeScale += Time.unscaledDeltaTime * restoreTimeSpeed; } else { Time.timeScale = 1; restoreTime = false; } } } IEnumerator TimeStartAgain(float _delay) { yield return new WaitForSecondsRealtime(_delay); restoreTime = true; } void FlashWhenInvi() { spriteRenderer.material.color = playerStateList.Invi ? Color.Lerp(Color.white, Color.black, Mathf.PingPong(Time.time * hitFlashspeed, 0.5f)) : Color.white; } void Heal() { if (Input.GetButton("Cast/Heal") && castOrhealTimer > 0.05f && Health < MaxHealth && Mana > 0 && !playerStateList.jumping && !playerStateList.dashing) { print("Healing: " + playerStateList.healing + ", Timer:" + healTimer + ", Mana:" + Mana); playerStateList.healing = true; animator.SetBool("Healing", true); healTimer += Time.deltaTime; if (healTimer >= timetoHeal) { Health++; healTimer = 0; } //using mana to heal Mana -= Time.deltaTime * manaDrain; } else { playerStateList.healing = false; animator.SetBool("Healing", false); healTimer = 0; } } void CastSpell() { if (Input.GetButtonUp("Cast/Heal") && castOrhealTimer <= 0.05f && timeSincecast >= timeBetweencast && Mana >= manaSpellcost) { playerStateList.castspell = true; timeSincecast = 0; StartCoroutine(CastCoroutine()); } else { timeSincecast += Time.deltaTime; } if (isonGround()) { //cannot using skyfall if on ground downSpellSkyFall.SetActive(false); } //force the player to fall down if cast skyfall if (downSpellSkyFall.activeInHierarchy) { rbd2.velocity += skyfallForce * Vector2.down; } } IEnumerator CastCoroutine() { animator.SetBool("Casting", true); yield return new WaitForSeconds(0.12f); //sidecast/darkball if(yAxis == 0 || (yAxis < 0 && isonGround())) { GameObject _darkball = Instantiate(sideSpellDarkBall, sideAttackTransform.position, Quaternion.identity); //flip skill if (playerStateList.lookingRight) { _darkball.transform.eulerAngles = Vector3.zero; // ban spell nhu bth } else { _darkball.transform.eulerAngles = new Vector2(_darkball.transform.eulerAngles.x, 100); } playerStateList.recoilingX = true; } //upcast/Dark Rising else if(yAxis > 0) { Instantiate(upSpellDarkRising, transform); rbd2.velocity = Vector2.zero; } //downcasr/ Sky Fall else if (yAxis < 0 && !isonGround()) { downSpellSkyFall.SetActive(true); } Mana -= manaSpellcost; yield return new WaitForSeconds(0.35f); animator.SetBool("Casting", false); playerStateList.castspell = false; } public IEnumerator WalktonewScene(Vector2 _exitDir, float _delay) { if(_exitDir.y > 0) { rbd2.velocity = jumpForce * _exitDir; } if (_exitDir.x != 0) { xAxis = _exitDir.x > 0 ? 1 : -1; Moving(); } Flip(); yield return new WaitForSeconds(_delay); playerStateList.incutscene = false; } IEnumerator Death() { playerStateList.alive = false; Time.timeScale = 1f; animator.SetTrigger("Death"); rbd2.constraints = RigidbodyConstraints2D.FreezePosition; GetComponent<BoxCollider2D>().enabled = false; yield return new WaitForSeconds(0.9f); StartCoroutine(UIManager.Instance.ActiveDeathScreen()); } public void Respawn() { if (!playerStateList.alive) { rbd2.constraints = RigidbodyConstraints2D.None; rbd2.constraints = RigidbodyConstraints2D.FreezeRotation; GetComponent<BoxCollider2D>().enabled = true; playerStateList.alive = true; Health = MaxHealth; Mana = 0; animator.Play("PlayerIdle"); } } void OpenMap() { if (openMap) { UIManager.Instance.mapHandler.SetActive(true); } else { UIManager.Instance.mapHandler.SetActive(false); } } private bool Walled() { return Physics2D.OverlapCircle(wallCheck.position, 0.2f, wallLayer); } void WallSlide() { if (Walled() && !isonGround() && xAxis != 0) { iswallSliding = true; rbd2.velocity = new Vector2(rbd2.velocity.x, Mathf.Clamp(rbd2.velocity.y, -wallSlidingSpeed, float.MaxValue)); } else { iswallSliding = false; } } void WallJump() { if (iswallSliding) { iswallJumping = false; wallJumpDirection = !playerStateList.lookingRight ? 1:-1; CancelInvoke(nameof(StopWallJumping)); } if (Input.GetButtonDown("Jump") && iswallSliding) { iswallJumping = true; rbd2.velocity = new Vector2(wallJumpDirection * wallJumpPow.x, wallJumpPow.y); dashed = false; dbJumpCounter = 0; playerStateList.lookingRight = !playerStateList.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); } } </code>
November 11, 2024 at 6:36 pm #16292::Try setting the player’s health to factor in the heart shards:
Move.Instance.Health = playerHealth + Mathf.Floor(0.25f * playerHeartShards);
November 11, 2024 at 8:43 pm #16293::When I put the code into loadPlayerData. It said Cannot implicitly convert type ‘float’ to ‘int’. An explicit conversion exists (are you missing a cast?). Should I change the playerHealth from int to float?
November 11, 2024 at 10:19 pm #16294::I tried to fix by adding variable maxhealth
public int playerMaxHealth;
and in save and load player data, i add this variable to the value of the player max health like this<code> public void savePlayerData() { using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(Application.persistentDataPath + "/save.player.data"))) { playerHealth = Move.Instance.Health; writer.Write(playerHealth); playerMana = Move.Instance.Mana; writer.Write(playerMana); playerUnlockWallJump = Move.Instance.unlockWalljump; writer.Write(playerUnlockWallJump); playerPosition = Move.Instance.transform.position; writer.Write(playerPosition.x); writer.Write(playerPosition.y); lastScene = SceneManager.GetActiveScene().name; writer.Write(lastScene); playerHeartShards = Move.Instance.heartShards; writer.Write(playerHeartShards); playerMaxHealth = Move.Instance.MaxHealth; writer.Write(playerMaxHealth); } }</code>
<code>public void loadPlayerData() { if (File.Exists(Application.persistentDataPath + "/save.player.data")) { using (BinaryReader reader = new BinaryReader(File.OpenRead(Application.persistentDataPath + "/save.player.data"))) { playerHealth = reader.ReadInt32(); playerMana = reader.ReadSingle(); playerUnlockWallJump = reader.ReadBoolean(); playerPosition.x = reader.ReadSingle(); playerPosition.y = reader.ReadSingle(); lastScene = reader.ReadString(); playerHeartShards = reader.ReadInt32(); playerMaxHealth = reader.ReadInt32(); SceneManager.LoadScene(lastScene); Move.Instance.transform.position = playerPosition; Move.Instance.MaxHealth = playerMaxHealth; Move.Instance.Health = playerHealth; Move.Instance.Mana = playerMana; Move.Instance.unlockWalljump = playerUnlockWallJump; Move.Instance.heartShards = playerHeartShards; Debug.Log("Loaded position: " + playerPosition); Debug.Log("Loaded health: " + playerHealth); Debug.Log("Loaded mana: " + playerMana); Debug.Log("Loaded unlock wall jump: " + playerUnlockWallJump); Debug.Log("Loaded heart shards: " + playerHeartShards); Debug.Log("Loaded Health: " + playerHealth); Debug.Log("Loaded Max Health: " + playerMaxHealth); } Debug.Log("Player data loaded successfully"); } else { Debug.Log("File doesn't exist"); Move.Instance.Health = Move.Instance.MaxHealth; Move.Instance.heartShards = 0; Move.Instance.Mana = 0.5f; Move.Instance.unlockWalljump = false; } }</code>
And the game work look fine. Thank you for helping me at all
November 11, 2024 at 11:49 pm #16296::No, we need to do a cast. I forgot to add that in the code above:
Move.Instance.Health = playerHealth + (int)Mathf.Floor(0.25f * playerHeartShards);
November 12, 2024 at 12:21 am #16298::Oh my reply has been flaged as spam (again). In the flag comment. I mada another variable name playermaxhealth and then add it same way as the other variables in the save and load playerdata. Now the game working good. Tks you for helping me all of this time.
has upvoted this post. -
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: