- Home /
Add Health on Pickup to Decaying Health,Make a collision with an object add health
Hey, so in my game the player is a car running out of fuel (losing health basically) and along the way you need to collect fuel to add to the health bar.
Is there a simple way I can add a collision to my script? I'm having difficulty finding anything useful that wasn't written <5 years ago :|I tried doing stuff like OnCollisionEnter and then doing the 'AddHealth(10)' line but then it just wrecked the whole code up so I have no idea what I'm doing or what I can do.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HealthBar3D : MonoBehaviour {
public float initialHealth;
public Renderer myRenderer;
public Color healthyColor, sickColor;
[Tooltip ("This is the rate the health goes down")]
public float healthDecay;
private float currentHealth;
void Update ()
{
if (Input.GetKeyDown (KeyCode.Space))
AddHealth (10);
}
// Use this for initialization
void Start () {
currentHealth = initialHealth;
UpdateHealthBar ();
StartCoroutine (LoseHealth ());
}
public void AddHealth (float amount) {
currentHealth += amount;
if (currentHealth >= initialHealth)
currentHealth = initialHealth;
UpdateHealthBar ();
}
IEnumerator LoseHealth ()
{
yield return new WaitForSeconds (1);
currentHealth -= healthDecay;
UpdateHealthBar ();
if (currentHealth <= 0) {
currentHealth = 0;
Die ();
}
StartCoroutine (LoseHealth ());
}
void Die () {
Destroy (transform.parent.gameObject);
}
void UpdateHealthBar ()
{
// draw the new scale
float newScale = currentHealth / initialHealth;
transform.localScale = new Vector3 (newScale, transform.localScale.y, transform.localScale.z);
// also change the color
myRenderer.material.color = Color.Lerp(sickColor, healthyColor, newScale);
}
}
I tried doing stuff like OnCollisionEnter and then doing the 'AddHealth(10)' line but then it just wrecked the whole code up
How?
The rest of the code became invalidated and had errors, I'm not sure why.
You probably added comment lines or missed braces or parenthesis.
What are the errors, also there isn't any OnCollisionEnter in the script you posted above.
Answer by Harinezumi · May 11, 2018 at 12:20 PM
As a response to your comment, this is what I meant when I suggested to separate the display related logic from the collision and health logic. From a logic point of view there are various elements here, all of which could be separated into a separate component. In general, it is a good idea to separate logic into independent parts, with as little communication as possible (and only in one direction if possible).
So what I would do in your case is to separate my scripts into (at least) 2 parts: the HealthBar3D
, the Player
, and possible a PlayerCollider
(but this could be in Player
). Most of what is in HealthBar3D
would go into Player
, while PlayerCollider
would only handling collision. BTW, I think you want your collectables to be triggers, so that you can pass through them, not collide with them and be stopped in place...
public class Player : MonoBehaviour {
[SerializeField] private float initialHealth;
[Tooltip("This is the rate the health goes down")]
[SerializeField]
private float healthDecay;
[SerializeField] HealthBar3D healthBar = null;
private float currentHealth;
private void Start () {
AddHealth(initialHealth); // clever way of setting inital health (it also updates health bar)
StartCoroutine(LoseHealth());
}
private void Update () {
if (Input.GetKeyDown(KeyCode.Space)) {
AddHealth(10);
}
}
private IEnumerator LoseHealth () {
// you can just run this forever instead of starting a new coroutine every time
while (true) {
yield return new WaitForSeconds(1);
AddHealth(-healthDecay); // clever way of applying health decay
}
}
// everything handled in the same function: checking max health, dying, and updating health bar
public void AddHealth (float amount) {
currentHealth += amount;
// limit health min and max in one function call
currentHealth = Mathf.Clamp(currentHealth, 0, initialHealth);
if (currentHealth <= 0) { Die(); }
healthBar.UpdateHealth(currentHealth / initialHealth);
}
private void Die () {
Destroy(gameObject);
}
}
public class HealthBar3D : MonoBehaviour {
[SerializeField] private Renderer myRenderer;
[SerializeField] private Color healthyColor, sickColor;
public void UpdateHealth (float healthRatio) {
// draw the new scale
transform.localScale = new Vector3(healthRatio, transform.localScale.y, transform.localScale.z);
// also change the color
myRenderer.material.color = Color.Lerp(sickColor, healthyColor, healthRatio);
}
}
public class PlayerCollider : MonoBehaviour {
// make sure you assign the player to this variable
[SerializeField] Player player = null;
// use this if you can collide with your collectables (they stop movement)
private void OnCollisionEnter (Collision collision) {
if (collision.gameObject.tag == "Cylinder") {
print("hihi");
player.AddHealth(10);
Destroy(collision.gameObject);
}
}
// use this if you can pass through your collectables
private void OnTriggerEnter (Collider collider) {
if (collider.tag == "Cylinder") {
print("hihi");
player.AddHealth(10);
Destroy(collider.gameObject);
}
}
}
Put these 3 script in source files with their respective names, add Player
and PlayerCollider
to your car object, and the HealthBar3D
onto your health bar object (child of the car, if I'm not wrong). Then you fill in and link up the fields exposed to the Editor (marked with [SerializeField]
): initialhealth
, healthDecay
, and healthBar
in Player
, myRenderer
and the colors in HealthBar3D
, and player
for PlayerCollider
. Then it should work! Good luck!
Thank you, my god. Thank you SO $$anonymous$$UCH for the help :) everything's working!!! Yay!
Answer by Yuvii · May 11, 2018 at 08:35 AM
hey, I think the OnCollisionEnter event is fine, and should work. Try a basic code like that :
void OnCollisionEnter(Collider col)
{
if(col.gameObject.layer == *theLayer*)
{
AddHealth(10);
Destroy(col.gameObject);
}
}
Dont forget to set a box collider on your assets then, and the code is different if you set the colliders as trigger or not, so be careful.
EDIT: this code is meant to be in your class of your original post, sorry i should have tell you that.
@kmkittyhawk try this, it should work. Good suggestions as well. Just make sure that the script is on something that should collide (I imagine your 3D health bar is not the thing collecting the health. I would move the health display related logic to a different script).
Btw, the reason answers about collisions are > 5 years old is that collisions have been working well and the same way for a while now, so those answers should still be good.
Ah I guess that would make sense, thanks for the tip.
Hey there,
I've put the script in a separate script but it gives some errors. Firstly, ins$$anonymous$$d of doing 'layer' like you did I just chose to do tags ins$$anonymous$$d (not sure if its any better or worse but I don't know about implementing the layer thing)
Second, the 'AddHealth' line is throwing up errors saying that it doesn't exist in the context?
Lastly, the 'Destroy(col.GameObject); line is also giving an error saying: "it doesn't contain a definition for 'GameObject' and there's no extension method accepting a first argument of a type 'Collider'." It's asking if I'm missing a 'using directive' or an assembly reference. Thanks for the help!
Indeed tags are easier to use (and I would not use layers for this - they are for more complex things). But when you check the tag make sure to use CompareTag()
(it's safer and more efficient).
The second problem comes from putting it in a separate script: the separate script doesn't "see" the function AddHealth()
from tje class HealthBar3D
(this is expressed as "does not exist in the context"). $$anonymous$$ove this code into your HealthBar3D
class.
For the final problem, you wrote GameObject
with a capital "G", but that is the class name, not the variable, which is gameObject
with a lower case "g". The capitalisation of names is very important in program$$anonymous$$g, they are completely different things for the compiler.
Oh thanks xD I'm new to the GameObject thing so I didn't realise those were two different things! I'm not getting anymore errors but for some reason it doesn't seem like the collision is even working!?
Here is a different script, ins$$anonymous$$d of putting it in the same script I made a new one but copied over the CurrentHealth variables and such so that it knows what they are, the reason I did this is because I want when the player collides with an object to receive 10 extra health, BUT the 'HealthBar3D' script is currently on a 'pivot' empty gameobject that affects the health bar above a player.
But despite having no issues with the code anymore, collision still isn't working? thank you so much for the help and explaining things.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AddingHealth : $$anonymous$$onoBehaviour {
private float currentHealth;
public float initialHealth;
public Renderer myRenderer;
public Color healthyColor, sickColor;
// Use this for initialization
void Start () {
currentHealth = initialHealth;
UpdateHealthBar();
}
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "Cylinder")
{
print("hihi");
AddHealth(10);
Destroy(collision.gameObject);
}
}
public void AddHealth(float amount)
{
currentHealth += amount;
if (currentHealth >= initialHealth)
currentHealth = initialHealth;
UpdateHealthBar();
}
void UpdateHealthBar()
{
// draw the new scale
float newScale = currentHealth / initialHealth;
transform.localScale = new Vector3(newScale, transform.localScale.y, transform.localScale.z);
// also change the color
myRenderer.material.color = Color.Lerp(sickColor, healthyColor, newScale);
}
// Update is called once per frame
void Update () {
}
}
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
OnMouseDown with colliders behind the object being clicked 3 Answers
Problem with acing problems with : OnTriggerEnter 0 Answers
On collision nearby objects ui view (scroll view) 0 Answers
My player HP are get decreased from several GameObjects that has is Trigger on 0 Answers