0
\$\begingroup\$

I'm somewhat new to Unity and am trying to build a battle system. Right now, I have an attack that checks collisions with enemy objects like this:

private void OnTriggerEnter2D(Collider2D other) {
  if (other.gameObject.layer != LayerMask.NameToLayer(_hurtboxLayer))
    return;

  var enemyHealth = other.GetComponent<Health>();
  enemyHealth.TakeDamage(_damagePoints);
}

My game also uses Rigidbody2D objects to let the player and enemies bump into each other. Because I want the "bumping" Collider2D be different from the hitbox Collider2D, I made a child GameObject called Hurtbox for each enemy. The Hurtbox objects have a Health behaviour which handles the HP and death of an enemy:

public class Health : MonoBehaviour {

  [SerializeField] private int _initialHealthPoints;
  private int _healthPoints;

  public void TakeDamage(int damagePoints) {
    _healthPoints -= damagePoints;

    if (_healthPoints <= 0) {
      Die();
    }
  }

  private void Die() {
    Destroy(gameObject);
  }

  private void Start() {
    _healthPoints = _initialHealthPoints;
  }

}

The Die method only destroys the hurtbox object and is not allowed to destroy the enemy object, which is its parent. Is there any way I can put both Collider2Ds and the Health behaviour on the same GameObject and only check a specific Collider in the OnTriggerEnter2D method?

\$\endgroup\$
3
  • 2
    \$\begingroup\$ It sounds like you have a perfectly workable solution with multiple game objects right now. Why do you want to reduce to one game object instead? \$\endgroup\$
    – DMGregory
    Nov 11 '20 at 15:34
  • \$\begingroup\$ @DMGregory When I called the Die method before, I would only destroy the Hurtbox object, not the parent object that holds the Rigidbody, SpriteRenderer, etc. But I just checked now, the code works fine, if I attach the Health behaviour to the Hurtbox object and then call Destroy(transform.parent.gameObject) from Die. \$\endgroup\$
    – G_hi3
    Nov 11 '20 at 16:38
  • 3
    \$\begingroup\$ If you've solved your problem, please post your solution as an Answer below. \$\endgroup\$
    – DMGregory
    Nov 11 '20 at 16:42
0
\$\begingroup\$

As DMGregory pointed out, my solution was on the right track. What I do differently now, is that now the Health behaviour detroys its parent. I had an exception when I tried this the first time, but that might have been because I put the code in the wrong behaviour. Also, I made sure to check the Physics 2D settings to make sure, the Hurtbox objects wouldn't collide with any other objects.

My game objects:

  • Character/Enemy (Rigidbody2D, Box Collider 2D)
    • Hurtbox (Box Collider 2D, Health)
  • Projectile (Box Collider 2D, Projectile behaviour) -> instantiated by character/enemy

Projectile Code

private void OnTriggerEnter2D(Collider2D other) {
  if (other.gameObject.layer != _hurtboxLayerMask)
    return;

  var enemyHealth = other.GetComponent<Health>();
  enemyHealth.TakeDamage(damagePoints);
  Destroy(gameObject);
}

Health behaviour

public class Health : MonoBehaviour {
  [SerializeField] private int initialHealthPoints;
  private int _healthPoints;
  
  public void TakeDamage(int damagePoints) {
    HealthPoints -= damagePoints;
    
    if (HealthPoints <= 0) {
      Die();
    }
  }

  private void Die() {
    Destroy(transform.parent.gameObject);
  }

  private void Start() {
    HealthPoints = TotalHealthPoints = initialHealthPoints;
  }

  public int TotalHealthPoints { get; private set; }
  public int HealthPoints { get; private set; }
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .