Currently, when the player jumps on top of an enemy, the player and the enemy take damage.
I'm trying to figure out a way that only the enemy gets damaged when the player jumps on top of the enemy and so the player does not get damaged. I have two colliders on the enemy (image below). One collider under the Enemy gameObject (wider, bottom collider) and then there's a child gameObject under Enemy called Receive Damage Check that has a collider (top, smaller collider player jumps on). There is a hazard Layer that the enemy gameObject is on. The child gameObject, Receive Damage Check, underneath the enemy is not on the hazard Layer.
The goal is to have the Receive Damage Check collider register the player collided with it and only damage the Enemy.
Base class:
public class Character : MonoBehaviour {
public int maxHealth;
public int currentHealth;
public HealthBar healthBar;
[SerializeField] protected float damageInterval = 2f; //in seconds
protected float currentDamageInterval;
protected SpriteRenderer sr;
private Rigidbody2D rb;
protected virtual void Start() {
sr = GetComponent<SpriteRenderer>();
rb = GetComponent<Rigidbody2D>();
currentHealth = maxHealth;
healthBar.SetMaxHealth(maxHealth);
}
protected virtual void Update() {
//subtract 1 real life second
if (currentDamageInterval >= 0)
currentDamageInterval -= Time.deltaTime;
}
public bool CanTakeDamage() {
return (currentDamageInterval < 0);
}
public virtual void TakeDamage(int damage) {
currentHealth -= damage;
healthBar.SetHealth(currentHealth);
int yDamageVelocity = 15;
rb.velocity = new Vector2(rb.velocity.x, yDamageVelocity);
//set currentDamageInterval to start a new cooldown/delay period (2 seconds)
currentDamageInterval = damageInterval;
}
}
Children classes:
public class Player : Character {
[SerializeField] private Transform groundCheck;
[SerializeField] private LayerMask hazardLayer;
private Color[] colors = { Color.red, Color.white };
private Coroutine damageFlash;
protected override void Start() {
base.Start();
maxHealth = 10;
}
protected override void Update() {
base.Update();
//if the current number in the currentDamageInterval is <= 0 or in other words if
//2 seconds of delay has passed, take damage
if (CanTakeDamage())
if (Physics2D.OverlapCircle(groundCheck.position, 0.5f, hazardLayer)) {
TakeDamage(1);
}
//for testing purposes
if (Input.GetKeyDown(KeyCode.H))
TakeDamage(1);
}
public override void TakeDamage(int damage) {
base.TakeDamage(damage);
//guarantee at most, one coroutine runs at a time
if (damageFlash != null)
StopCoroutine(damageFlash);
damageFlash = StartCoroutine(DamageFlashing(1f, .1f));
}
IEnumerator DamageFlashing(float duration, float interval) {
int index = 0;
//var is a replacement for WaitForSeconds bc it would be redundant
var wait = new WaitForSeconds(interval);
for (float elapsedTime = 0; elapsedTime < duration; elapsedTime += interval) {
//divides the index by 2 and returns the remainder
sr.color = colors[index % 2];
index++;
//waits the interval time and then continues the next color in the flashing duration
yield return wait;
}
damageFlash = null;
}
}
public class Enemy : Character {
protected override void Start() {
maxHealth = 3;
base.Start();
}
private void OnCollisionEnter2D(Collision2D collision) {
if (collision.gameObject == GameObject.FindWithTag("Player"))
if (CanTakeDamage())
TakeDamage(1);
}
}
Player
class that would specifically cause it to take damage when colliding with an enemy. Is the enemy on the hazard layer? \$\endgroup\$OnCollisionEnter2D
in Enemy that causes player to take damage \$\endgroup\$