icestorm0806
icestorm0806

Reputation: 711

Cause player to take damage in Unity 2D

I made two scripts. One that'll keep track of the player's health, health bar and cause the screen to flash when the player is damaged. The other script is meant to be placed on any object I wish to do damage to the player, on contact. My problem is, Nothing seems to be doing any damage to the player.

PlayerHealth.cs:

using UnityEngine;
using UnityEngine.UI;

public class PlayerHealth : MonoBehaviour
{
    public int currentHealth;
    public float flashSpeed = 5;
    public Slider healthSlider;
    public Color flashColour = new Color(1, 0, 0, 0.1f);
    bool isDead;
    bool damaged;

    private void Awake()
    {
        currentHealth = 100;
    }

    private void Update()
    {
        damaged = false;
    }

    public void TakeDamage(int amount)
    {
        damaged = true;
        currentHealth -= amount;
        healthSlider.value = currentHealth;
    }
}

AttackPlayer.cs:

using UnityEngine;

public class AttackPlayer : MonoBehaviour
{
    public float timeBetweenAttacks = 0.5f;
    public int attackDamage = 10;

    GameObject player;
    PlayerHealth playerHealth;

    float timer;

    private void Awake()
    {
        player = GameObject.FindGameObjectWithTag("Player");
        playerHealth = player.GetComponent<PlayerHealth>();
    }

    private void OnTriggerEnter2D(Collider2D col)
    {
        if (col.gameObject == player)
        {
            Attack();
        }
    }

    private void Update()
    {
        timer += Time.deltaTime;

        if(playerHealth.currentHealth <=0)
        {
            // TODO: add death script here.
        }
    }

    void Attack()
    {
        timer = 0f;
        if(playerHealth.currentHealth > 0)
        {
            playerHealth.TakeDamage(attackDamage);
        }
    }
}

The player has a rigidbody2D. The player and damaging objects have Box Collider 2D's on them.

Upvotes: 0

Views: 8547

Answers (1)

derHugo
derHugo

Reputation: 90813

  1. Make sure that the players Collider has isTrigger enabled.

  2. attackDamage is public -> set in the inspector. Make sure it is not 0.

    You could use

    [Range(1,100)] public int attackDamage = 10;
    

    to automatically clamp the value in the inspector.

  3. A guess but I'ld say your Collider might not be on the GameObject player but probably on one of its children => the condition col.gameObject == player is not true.

    Instead of GameObject references rather compare the PlayerHealth (since there is only one) reference like

    private void OnTriggerEnter2D(Collider2D col)
    {
        // gets PlayerHealth component on this or any parent object
        var health = col.GetComponentInParent<PlayerHealth>();
        if (health  == playerHealth)
        {
            Attack();
        }
    }
    
  4. You have

    private void Update()
    {
        damaged = false;
    }
    
    public void TakeDamage(int amount)
    {
        damaged = true;
        currentHealth -= amount;
        healthSlider.value = currentHealth;
    }
    

    I don't know what else should happen on TakeDamage but the value of damaged is resetted in Update so right after it was set by the Trigger because Physics events like OnTriggerEnter are executed before Update (see execution Order).


Hint: Instead of

player = GameObject.FindGameObjectWithTag("Player");
playerHealth = player.GetComponent<PlayerHealth>();

you could also use

playerHealth = FindObjectOfType<PlayerHealth>();

if that component exists only once in your scene.


Or to be more flexible (having multiple Players) all you have to do is change your OnTriggerEnter2D and Attack method to

private void OnTriggerEnter2D(Collider2D col)
{
    // gets PlayerHealth component on this or any parent object
    var health = col.GetComponentInParent<PlayerHealth>();
    if (health != null)
    {
        Attack(health);
    }
}

void Attack(PlayerHealth health)
{
    timer = 0f;
    if(health.currentHealth > 0)
    {
        health.TakeDamage(attackDamage);
    }
}

So you wouldn't need to get the reference before.

Upvotes: 2

Related Questions