Forum begins after the advertisement:


[part 4] heart and mana UI problems

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [part 4] heart and mana UI problems

Viewing 8 posts - 1 through 8 (of 8 total)
  • Author
    Posts
  • #13844
    Anuk Thotawatta
    Participant

    When i die and respawn my heartfills are invisible but they appear once the player is hit once. like in the video below.

    View post on imgur.com

    also after i die and respawn my mana container gets cut in half but once i restart the game it appears full(but still has half the mana)

    View post on imgur.com

    #13846
    Joseph Tang
    Moderator

    Looking at it,

    1) Heartfill is invisible

    Can you take a video or screenshot of your PlayerController.cs Respawned().
    Check if you have a code Health = maxHealth; in the Respawn() method.

    My theory is that your health is not being updated or called to update when respawning.

    2) Mana is not halved on reenter

    Currently this is intentional as there is no code for the UI Manager to remember that your Player still has half mana. [You should be able to see on the Canvas Gameobject that it’s state is still FullMana on starting the game, regardless of your Player’s halfmana bool.]
    To add this feature, I suggest to put a code under PlayerController.cs Start().

    void Start()
        {
            pState = GetComponent();
            rb = GetComponent();
            sr = GetComponent();
            anim = GetComponent();
    
            manaOrbsHandler = FindObjectOfType();
    
            audioSource = GetComponent();
    
            SaveData.Instance.LoadPlayerData();
            gravity = rb.gravityScale;
            if (halfMana == true)
            {
                UIManager.Instance.SwitchMana(UIManager.ManaState.HalfMana);
            }
            else
            {
                UIManager.Instance.SwitchMana(UIManager.ManaState.FullMana);
            }
            //Mana = mana;
            //manaStorage.fillAmount = Mana;
    
            //Health = maxHealth;
        }

    #13847
    Anuk Thotawatta
    Participant

    you were right. the problem was in the respawn function. I have accidently written health = maxHealth; instead of Health = maxHealth;.

    And the new mana container code works perfectly too. Thanks alot

    #13851
    Anuk Thotawatta
    Participant

    how do i make heart shards disappear after unlocking them?

    View post on imgur.com

    #13855
    Joseph Tang
    Moderator

    If you want them to be removed, you will have to create some new code for SaveData.cs as this is an intentionally caused issue by not creating the function.

    A simple way to do this is by creating a bunch if bools for specific heart unlocks and copying the structure for Unlocking abilities.

    For example,
    1) In SaveData.cs, create public bool haveCcollectedHeartShard1, haveCcollectedHeartShard2, haveCollectedHeartShard3;
    2) Create a seperate void in SaveData.cs for the Heart Shards. and follow the same format as the previous save and load data.
    3) Similarly, In IncreaseMaxHealth.cs, add public bool collectedHeartShard1, collectedHeartShard2, collectedHeartShard3
    4) In IncreaseMaxHealth.cs, create a way to identify which shard it is, like public int HeartShardNumber.
    5) In IncreaseMaxHealth.cs Start(), create seperate if else statements to check for your HeartShardNumber & the bool of SaveData.cs of the corresponding number. Then create a code to load the SaveData. For instance:

    void Start()
        {
            ;SaveData.Instance.LoadHeartShardData();
            if (PlayerController.Instance.maxHealth >= PlayerController.Instance.maxTotalHealth)
            {
                Destroy(gameObject);
            }
            if (HeartShardNumber == 1)
            {
                if (collectedHeartShard1)
                {
                    Destroy(gameObject);
                }
            }
            else if (HeartShardNumber == 1)
            {
                if (collectedHeartShard1)
                {
                    Destroy(gameObject);
                }
            }
            else
            .
            .
            .
            else if (HeartShardNumber == 10)
            {
                if (collectedHeartShard10)
                {
                    Destroy(gameObject);
                }
            }
        }

    6) Finally, set a way to save the data by adding in a code like in step 5 for ShowUI(). Use the same code but change Destroy() for collectedHeartShard1 = true. AFter all the if statements, put a SaveData.Instance.SaveHeartShardData();.

    This will be a bit of tedious work but this is only one way to save what you collected and what hasn’t for the same type of object. This will not be sustainable for things like Chests where there can be hundreds, but this will suffice for things with little copies such as the shards.

    #13896
    Aria
    Bronze Supporter (Patron)

    How would you go about doing this on a large scale like imagine you had hundreds of chests

    #13923
    Joseph Tang
    Moderator

    This will require some testing, but we’ll get back to you on this when we find an efficient way to make this mechanic.

    #13933
    Terence
    Keymaster

    How would you go about doing this on a large scale like imagine you had hundreds of chests

    Just to add on to Joseph’s comment, usually, for a large number of booleans, we will use bitmasks if we want to make it scalable. Bitmasks are basically integers used as booleans.

    Computers store numbers in binary, not in decimal, which means 0, 1, 2, 3, 4, 5 etc… become 0, 1, 10, 11, 100, 101, 110, etc.

    Integers are 32-bit numbers, which means they are stored as a series of 32 1s or 0s, like so:

    00000000 00000000 00000000 00000000

    Using it as a bitmask means treating the integer as a set of 32 booleans instead of a whole integer. For example, if I wanted to flip chest number 2 and 5, I would change the integer to this:

    00000000 00000000 00000000 00010010

    We can save a bitmask for treasure chests in each scene in SaveData.cs, in a dictionary, like so:

    Dictionary<string, int> pickedItemsRecord = new Dictionary<string, int>();

    Where the key to the dictionary is a string, and the int is the bitmask. You will also need to give an ID property to every treasure chest that ranges between 0 to 32. Then, whenever a Scene is loaded, the treasure chest will check the bitmask for that particular scene to see if the chest has already been picked up, and make the chest hide itself if so.

    The limitation to this system is that you can only have up to 32 items in a Scene, but you can change the int to a long (64-bit integer) so that you can hold 64 items instead.

    It’s a bit hard to implement, because you’ll need to learn about bitwise operations and dictionaries to be able to do this, but I hope this helps!

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

Go to Login Page →


Advertisement below: