Forum begins after the advertisement:
[part 8] heart shards dont update
Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [part 8] heart shards dont update
- This topic has 9 replies, 3 voices, and was last updated 9 months, 2 weeks ago by Allan Valin.
-
AuthorPosts
-
December 20, 2023 at 6:49 am #12711::
So unlockable items work fine and the heart shards are picked up and dissapear but…. they dont increase my health when 4 are picked up and the canvas that appears doesnt show the heart filling up animation – it defaults to whatever i already have the heart fill set to in the prefab. When picking up a heart shard – the heart shard counter will increase so ik its working somehow
the video doesnt go over all values you are meant to add to the insepctor – maybe its that issue player: health – 0(sets to 5 when played) maxhealth – 5 totalMaxHealth – 10
increase max Health canvas: fill – fill image under the canvas – ive set its fill amount to 1(ive tried other values but nothing changes) target fill amount – 0.25 lerp duration – 1.5 initial fill amount – 0
ive changed these values tons and nothing seems to change it so i thinks its a script error but i cant seem to pinpoint it
for my heart shards script – all debug logs play except for “fill amoont” and “maxHealthIncrease”
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 initialFillAmount; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } public IEnumerator LerpFill() { float elapsedTime = 0f; while (elapsedTime < LerpDuration) { Debug.Log("filled?"); elapsedTime += Time.deltaTime; float t = Mathf.Clamp01(elapsedTime / LerpDuration); Debug.Log("filled1"); float lerpedFillAmount = Mathf.Lerp(initialFillAmount, targetFillAmount, t); Fill.fillAmount = lerpedFillAmount; Debug.Log("filled2"); yield return null; } Fill.fillAmount = targetFillAmount; Debug.Log("fillamoont?"); Fill.fillAmount = targetFillAmount; Debug.Log("fillamoont?"); if (Fill.fillAmount == 1) { PlayerController.Instance.maxHealth++; Debug.Log("max health increase"); PlayerController.Instance.onHealthChangedCallBack(); PlayerController.Instance.heartShards = 0; } } }
all debugs logs play in my increase MaxHealth script
using System.Collections; using System.Collections.Generic; using UnityEngine; public class IncreaseMaxHealth : MonoBehaviour { [SerializeField] GameObject particles; [SerializeField] GameObject canvasUI; [SerializeField] HeartShards heartShards; bool used; // Start is called before the first frame update void Start() { if (PlayerController.Instance.maxHealth >= PlayerController.Instance.maxTotalHealth) { Destroy(gameObject); } } private void OnTriggerEnter2D(Collider2D _collision) { if (_collision.CompareTag("Player") && !used) { used = true; StartCoroutine(ShowUI()); } } IEnumerator ShowUI() { GameObject _particles = Instantiate(particles, transform.position, Quaternion.identity); Destroy(_particles, 0.5f); yield return new WaitForSeconds(0.5f); canvasUI.SetActive(true); heartShards.initialFillAmount = PlayerController.Instance.heartShards * 0.25f; PlayerController.Instance.heartShards++; heartShards.targetFillAmount = PlayerController.Instance.heartShards * 0.25f; Debug.Log("heartshards"); yield return new WaitForSeconds(2.5f); StartCoroutine(heartShards.LerpFill()); Debug.Log("lerpy fill"); SaveData.Instance.SavePlayerData(); canvasUI.SetActive(false); Destroy(gameObject); } }
using UnityEngine; using UnityEngine.UI; public class HeartController : MonoBehaviour { private GameObject[] heartContainers; private Image[] heartFills; public Transform heartsParent; public GameObject heartContainerPrefab; // Start is called before the first frame update void Start() { heartContainers = new GameObject[PlayerController.Instance.maxTotalHealth]; heartFills = new Image[PlayerController.Instance.maxTotalHealth]; PlayerController.Instance.onHealthChangedCallBack += UpdateHeartsHUD; InstantiateHeartContainers(); UpdateHeartsHUD(); } // Update is called once per frame void Update() { } void SetHeartContainers() { for (int i = 0; i < heartContainers.Length; i++) { if (i < PlayerController.Instance.maxHealth) { heartContainers[i].SetActive(true); } else { heartContainers[i].SetActive(false); } } } void SetFilledHearts() { for (int i = 0; i < heartFills.Length; i++) { if (i < PlayerController.Instance.health) { heartFills[i].fillAmount = 1; } else { heartFills[i].fillAmount = 0; } } } void InstantiateHeartContainers() { for (int i = 0; i < PlayerController.Instance.maxTotalHealth; i++) { GameObject temp = Instantiate(heartContainerPrefab); temp.transform.SetParent(heartsParent, false); heartContainers[i] = temp; heartFills[i] = temp.transform.Find("HeartFill").GetComponent<Image>(); } } void UpdateHeartsHUD() { SetHeartContainers(); SetFilledHearts(); } }
December 20, 2023 at 10:01 pm #12712::Can’t help you much here. Check your Inspector to see if everything is referenced, or if there are duplicate / misreferenced GameObjects.
December 20, 2023 at 10:36 pm #12714::The video didn’t properly mention all values that are to be assigned in the inspector – these are the ones ive changed – are there any more things i need to change?
View post on imgur.com
December 20, 2023 at 10:43 pm #12715::i think it might be a code error as my max health won’t increase when collecting 4 heart shards? ive checked the vied a few times and cant find a difference?
December 21, 2023 at 1:07 am #12717::now my hearts increase – seems like an eror in the video – however the canvas animation doesnt show the heart filling up
my changes to the IEnumeraaotr LerpFill()
public IEnumerator LerpFill() { float elapsedTime = 0f; while (elapsedTime < LerpDuration) { Debug.Log("filled?"); elapsedTime += Time.deltaTime; float t = Mathf.Clamp01(elapsedTime / LerpDuration); Debug.Log("filled1"); float lerpedFillAmount = Mathf.Lerp(initialFillAmount, targetFillAmount, t); fill.fillAmount = lerpedFillAmount; Debug.Log("filled2"); fill.fillAmount = targetFillAmount; Debug.Log("fillamoont?"); if (fill.fillAmount == 1) { PlayerController.Instance.maxHealth++; Debug.Log("max health increase"); PlayerController.Instance.onHealthChangedCallBack(); PlayerController.Instance.heartShards = 0; } yield return null; Debug.Log("returned null"); } }
December 21, 2023 at 3:17 am #12718::im having the same issue with the mana orbs – they dont appear on the canvas – there was a moment when it was working but then it stopped when i restarted to test it out
also the new mini mana containers wont appear when i get 3 mana orbs – i tried the same fix as last time but doesnt seem to do the trick
December 21, 2023 at 3:22 am #12719::highly convinced this is a code problem but im unaware of any errors???
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class OrbShard : MonoBehaviour { public Image fill; public float targetFillAmount; public float LerpDuration = 1.5f; public float initialFillAmount; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } public IEnumerator LerpFill() { float elapsedTime = 0f; while (elapsedTime < LerpDuration) { Debug.Log("filled?"); elapsedTime += Time.deltaTime; float t = Mathf.Clamp01(elapsedTime / LerpDuration); Debug.Log("filled1"); float lerpedFillAmount = Mathf.Lerp(initialFillAmount, targetFillAmount, t); fill.fillAmount = lerpedFillAmount; Debug.Log("filled2"); yield return null; fill.fillAmount = targetFillAmount; Debug.Log("fillamoont?"); if (fill.fillAmount == 1) { PlayerController.Instance.manaOrbs++; PlayerController.Instance.orbShards = 0; } } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class AddManaOrb : MonoBehaviour { [SerializeField] GameObject particles; [SerializeField] GameObject canvasUI; [SerializeField] OrbShard orbShards; bool used; // Start is called before the first frame update void Start() { if (PlayerController.Instance.manaOrbs >= 3) { Destroy(gameObject); } } private void OnTriggerEnter2D(Collider2D _collision) { if (_collision.CompareTag("Player") && !used) { used = true; StartCoroutine(ShowUI()); } } IEnumerator ShowUI() { GameObject _particles = Instantiate(particles, transform.position, Quaternion.identity); Destroy(_particles, 0.5f); yield return new WaitForSeconds(0.5f); canvasUI.SetActive(true); orbShards.initialFillAmount = PlayerController.Instance.orbShards * 0.34f; PlayerController.Instance.orbShards++; orbShards.targetFillAmount = PlayerController.Instance.orbShards * 0.34f; Debug.Log("orbshards"); yield return new WaitForSeconds(2.5f); StartCoroutine(orbShards.LerpFill()); Debug.Log("lerpy fill"); canvasUI.SetActive(false); SaveData.Instance.SavePlayerData(); Destroy(gameObject); } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class ManaOrbsHandler : MonoBehaviour { public bool usedMana; public List<GameObject> manaOrbs; public List<Image> orbFills; public float countDown = 3f; float totalManaPool; // Start is called before the first frame update void Start() { for(int i = 0; i < PlayerController.Instance.manaOrbs; i++) { manaOrbs[i].SetActive(true); } } // Update is called once per frame void Update() { for (int i = 0; i < PlayerController.Instance.manaOrbs; i++) { manaOrbs[i].SetActive(true); } CashInMana(); } public void UpdateMana(float _manaGainFrom) { for(int i = 0; i < manaOrbs.Count; i++) { if (manaOrbs[i].activeInHierarchy && orbFills[i].fillAmount < 1) { orbFills[i].fillAmount += _manaGainFrom; break; } } } void CashInMana() { if(usedMana && PlayerController.Instance.Mana <= 1) { countDown -= Time.deltaTime; } if(countDown <= 0) { usedMana = false; countDown = 3; totalManaPool = (orbFills[0].fillAmount += orbFills[1].fillAmount += orbFills[2].fillAmount) * 0.33f; float manaNeeded = 1 - PlayerController.Instance.Mana; if (manaNeeded > 0) { if(totalManaPool >= manaNeeded) { PlayerController.Instance.Mana += manaNeeded; for (int i = 0; i < orbFills.Count; i++) { orbFills[i].fillAmount = 0; } float addBackTotal = (totalManaPool - manaNeeded) / 0.33f; while(addBackTotal > 0) { UpdateMana(addBackTotal); addBackTotal -= 1; } } else { PlayerController.Instance.Mana += totalManaPool; for (int i = 0; i < orbFills.Count; i++) { orbFills[i].fillAmount = 0; } } } } } }
December 21, 2023 at 8:51 am #12720::the mana orbs work as my mana will increase but it will not create a new mini mana container on the side despite me setting it in the inspector – also the animation of the mana orb filling in the canvas doesnt play – it was working but then stopped when i clicked play again?
View post on imgur.com
December 21, 2023 at 5:20 pm #12722::Hi Niyam, you will have to figure this out on your end. Don’t check against the video to see if your code is the same, check to see which parts of the code are not running. E.g. if the mana orb is not increasing, check if
ShowUI()
inAddManaOrbs
is firing using a Debug.Log().If it is not, then you have to find the function(s) responsible for calling
ShowUI()
, and check if it is running. If it is not, head one level up and find the script that calls it, etc…Eventually, you will find a script with an if conditional that is not set up properly, or a coroutine that is not called / running when it is supposed to be.
March 4, 2024 at 4:35 am #13456::I had the same problem and I can say that it is a simple matter of going to the Increase Maxhealth Prefab and adding values to the HeartShards script (attached to the canvas). However I have no clue about what these values should be since it isn’t mentioned in the video. I tried with Target Fill Amount 0.25, Lerp Duration 1.5, Initial Fill Amount 0. Adding the heart image to the Fill field makes so that the heart increases always from 0 to 0.25 because every heart shard counts as one entire piece for some reason.
In order to solve the problem I just started cutting what I didn’t deem necessary (I don’t use HeartShard.cs anymore because I’d always get an error on line 35
fill.fillAmount = lerpedFillAmount;
even when I assigned a value to it) and ended up with the code below. Now the gathering four pieces gives only one heart instead of four total, and since there’s no UI animation, there’s no wrong animation lol(I changed from heartShards to heartPieces because it sounds better to me, there’s that Papa Roach song, Last Resort, that goes “cut my heart into pieces, this is my last resort (…)”) IncreaseMaxHealth.cs
<code>using System.Collections; using System.Collections.Generic; using UnityEngine; public class IncreaseMaxHealth : MonoBehaviour { [SerializeField] GameObject particles; [SerializeField] GameObject canvasUI; [SerializeField] HeartPieces heartPieces; bool used; // Start is called before the first frame update void Start() { if (PlayerController.Instance.maxHealth >= PlayerController.Instance.maxTotalHealth) { Destroy(gameObject); } } private void OnTriggerEnter2D(Collider2D collision) { if (collision.CompareTag("Player") && !used) { used = true; StartCoroutine(ShowUI()); } } IEnumerator ShowUI() { GameObject _particles = Instantiate(particles, transform.position, Quaternion.identity); Destroy(_particles, 0.5f); yield return new WaitForSecondsRealtime(0.5f); //canvasUI.SetActive(true); //heartPieces.initialFillAmount = PlayerController.Instance.heartPieces * 0.25f; PlayerController.Instance.heartPieces++; //heartPieces.targetFillAmount = PlayerController.Instance.heartPieces * 0.25f; //StartCoroutine(heartPieces.LerpFill()); if(PlayerController.Instance.heartPieces == 4) { PlayerController.Instance.maxHealth++; PlayerController.Instance.onHealthChangedCallback(); PlayerController.Instance.heartPieces = 0; } yield return new WaitForSecondsRealtime(2f); SaveData.Instance.SavePlayerData(); //canvasUI.SetActive(false); Destroy(gameObject); } } </code>
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: