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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.