Search Unity

My life system isnt working as intended and I dont know how to fix it

Discussion in 'Scripting' started by Felipe_Schluepmann, Jan 16, 2021.

  1. Felipe_Schluepmann

    Felipe_Schluepmann

    Joined:
    Jan 12, 2021
    Posts:
    14
    Hi I'm using a life system that really depends on collisions with the player and the different objects like for example if the player collides with an extra life token he gets one more life and if he gets hit by an enemy or falls down a pit/cliff he loses one life however the system that I have implemented to do so doesn't work that well especially when I want to reduce lives.

    Code (CSharp):
    1. using System.Collections;using System.Collections.Generic;
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4.  
    5. public class Health : MonoBehaviour
    6. {
    7.     [SerializeField] private Transform player;
    8.     [SerializeField] private Transform respawnPoint;
    9.  
    10.     public float health = 5f;
    11.     public float zeroHearts = 0f;
    12.  
    13.     public Text lifeText
    14.  
    15.     private void Update()
    16.     {
    17.  
    18.         lifeText.text = health.ToString();
    19.  
    20.         if (health <= 0)
    21.         {
    22.             health = zeroHearts;
    23.             FindObjectOfType<GameManager>().EndGame();
    24.         }
    25.  
    26.     }
    27.  
    28.     private void OnTriggerEnter(Collider col)
    29.     {
    30.         if (col.transform.tag == "HealthUp")
    31.         {
    32.             HealthUp(1);
    33.         }
    34.         if (col.transform.tag == "Enemies")
    35.         {
    36.             TakeDamage(1);
    37.            
    38.         }
    39.  
    40.         if ((col.transform.tag == "PitDeath"))
    41.         {
    42.             TakeDamage(1);
    43.         }
    44.     }
    45.  
    46.     void TakeDamage(int damage)
    47.     {
    48.         health -= damage;
    49.     }
    50.  
    51.     void HealthUp(int heal)
    52.     {
    53.         health += heal;
    54.     }
    55. }
    56.  
    for some reason when the player collides with an enemy, he ends up losing 2 lives instead of 1, and when he falls down a pit/cliff because I made it be a collision box he looses practically all of his lives just by falling instead of losing just 1 again I tried using


    Code (CSharp):
    1. bool inPIt;
    2.  
    3. if (inPit== false)
    4.         {
    5.             inPit = true;
    6.             TakeDamage(1);
    7.         }
    however, if a player falls into the pit and then falls again he ends up not losing life and just respawns(which is supposed to happen but he is also supposed to lose a life), I've tried to do many things but now I'm just lost at what to do to fix this problem


    ps: just in case you want to see the respawn code just in case this might be the problem here it is:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Respawn : MonoBehaviour
    6. {
    7.     [SerializeField] private Transform player;
    8.     [SerializeField] private Transform respawnPoint;
    9.  
    10.     private void OnTriggerEnter(Collider other)
    11.     {
    12.         if (other.CompareTag("Player"))
    13.         {
    14.             player.transform.position = respawnPoint.transform.position;
    15.             Physics.SyncTransforms();
    16.         }
    17.     }
    18.  
    19. }
    20.  
    21.  
     
  2. mikeohc

    mikeohc

    Joined:
    Jul 1, 2020
    Posts:
    215
    1) Pit fall issue -
    inPit = true;
    is never reset back to false, therefore will not execute again because it's always true.

    2) is the Health script only attached to the player? try putting Debug.log(health); in
    Code (CSharp):
    1. if (col.transform.tag == "Enemies")
    2.         {
    3.             TakeDamage(1);
    4.            Debug.Log(health);
    5.         }
    and see how many times this is being called. Maybe you're triggering this collider twice somewhere.
     
    Lethn likes this.
  3. Felipe_Schluepmann

    Felipe_Schluepmann

    Joined:
    Jan 12, 2021
    Posts:
    14
    I managed to fix the pit problem however using the debug.log function I saw that the enemies are somehow being triggered 3 times and now they are removing all 5 lives for some weird reason and now the health system is also having problems in which when you collect the health objects the Debug.Log says that I've collected them but the number wont change in the health HUD, however, it changes when we take damage.

    Code (CSharp):
    1. using System.Collections;using System.Collections.Generic;
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4.  
    5.  
    6. updated Script:
    7. public class Health : MonoBehaviour
    8. {
    9.     [SerializeField] private Transform player;
    10.     [SerializeField] private Transform respawnPoint;
    11.  
    12.     public float health = 5f;
    13.     public float zeroHearts = 0f;
    14.  
    15.     public Text lifeText;
    16.  
    17.     bool inPIt;
    18.  
    19.     bool isGrounded;
    20.  
    21.     //gravity check
    22.     public Transform groundCheck;
    23.     public float groundDistance = 0.4f;
    24.     public LayerMask groundMask;
    25.  
    26.  
    27.     private void Update()
    28.     {
    29.  
    30.         lifeText.text = health.ToString();
    31.  
    32.         if (health <= 0)
    33.         {
    34.             health = zeroHearts;
    35.             FindObjectOfType<GameManager>().EndGame();
    36.         }
    37.  
    38.         isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
    39.  
    40.         if (isGrounded)
    41.         {
    42.             inPIt = false;
    43.         }
    44.  
    45.     }
    46.  
    47.  
    48.     private void OnTriggerEnter(Collider col)
    49.     {
    50.         if (col.transform.tag == "HealthUp")
    51.         {
    52.             HealthUp(1);
    53.             Debug.Log("Health increase");
    54.         }
    55.         if (col.transform.tag == "Enemies")
    56.         {
    57.             TakeDamage(1);
    58.             Debug.Log("Health Decrease");
    59.         }
    60.  
    61.         if (inPIt == false)
    62.         {
    63.             inPIt = true;
    64.             TakeDamage(1);
    65.         }
    66.  
    67.  
    68.     }
    69.  
    70.         void TakeDamage(int damage)
    71.         {
    72.             health -= damage;
    73.         }
    74.  
    75.         void HealthUp(int heal)
    76.         {
    77.             health += heal;
    78.         }
    79.  
    80.    
    81. }
    82.  
     
  4. mikeohc

    mikeohc

    Joined:
    Jul 1, 2020
    Posts:
    215
    1) for the enemies problem - it's hard to help when you can't locate the source of cause. It could be many reasons that involves more than the script. e.g. Maybe you have multiple colliders? Maybe you attached two of the same script? Or ran the method somewhere else? If they are triggering 3 times but reduces hp by 5, according to the script attached, it doesn't seem to be this script's problem.

    2) As for the healing, add another
     Debug.Log(health); 
    underneath
    Debug.Log("Health increase");
    to see if it's UI not updating or whether the script is actually calling HealthUp();
     
  5. Felipe_Schluepmann

    Felipe_Schluepmann

    Joined:
    Jan 12, 2021
    Posts:
    14
    yeah even with the debug and using a simple cube with one collider nothing shows what could be the problem the healing shows up countless times in the console but it doesn't register in the text for some weird reason and some times one pick up registers and the other one doesn't and the enemies haven't changed I'm going to have to try and focus on other elements of the game and then come back to this thank you for all your help mikeohc I really appreciate it
     
    mikeohc likes this.
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,727
    Each console entry where that debug shows you can study the lower part of the console window and see the call stack of code leading to that output, and perhaps reason about why you are seeing it more times than you expect.

    Here is some timing diagram help:

    https://docs.unity3d.com/Manual/ExecutionOrder.html
     
    mikeohc likes this.
  7. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    691
    This probably won't solve your multiple-hit issue (not sure why it's happening), but there are a number of changes I'd recommend for clarity:

    1) health is used as an int, so declare it as an int, not a float.
    2) zerohearts seems unnecessary: health value is all that matters to determine alive/dead state, UI representation, etc.
    3) The only thing you should do in Update (out of what you have) is your ground check, because that actually does need to be done every frame. Checking the health value and showing it on the screen should be done in your Trigger function, when they actually change, so they're only done then, not every frame (this is wasted processing).
    4) When checking multiple tag names, use an if/else if structure, because only one happens at a time. This also saves processing (if even just a little).
    5) I wouldn't bother with separate health+ and health- functions. Just use one called healthChange and send it 1 or -1. Right after changing it, check for health <= 0. (That said, if you like the clarity of different names of HealthUp and TakeDamage, that's understandable.)

    Also wondering about the if(inPIt == false) line, that doesn't make sense to me...?
     
  8. mikeohc

    mikeohc

    Joined:
    Jul 1, 2020
    Posts:
    215
    In this case, try to comment out different parts of your code and run the game. Narrow down the cause one by one.
    e.g.
    Code (CSharp):
    1. private void OnTriggerEnter(Collider col)
    2.     {
    3.         if (col.transform.tag == "HealthUp")
    4.         {
    5.             HealthUp(1);
    6.             Debug.Log("Health increase");
    7.         }
    8.         //if (col.transform.tag == "Enemies")
    9.         //{
    10.             //TakeDamage(1);
    11.             //Debug.Log("Health Decrease");
    12.         //}
    13.         if (inPIt == false)
    14.         {
    15.             inPIt = true;
    16.             TakeDamage(1);
    17.         }
    18.     }
    You can comment multiple lines with Ctrl + K + C. and to uncomment multiple, Ctrl + K + U
     
  9. Felipe_Schluepmann

    Felipe_Schluepmann

    Joined:
    Jan 12, 2021
    Posts:
    14
    the inPit == false is just to make sure that when you fall off the map that it only registers once and doesn't keep updating so it only removes 1 life instead of many. ill try to implement your suggestions thank you so much for the advice!
     
  10. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    691
    Just a thought, do you happen to have more than one collider on your player and/or anything it could collide with?