I’m learning about inheritance and created a parent class called Character. Then there’s a child class called Player. I was trying to assign the rigidbody2D in the parent class through code, but I kept getting a NullReferenceException error saying the instance of rb is not assigned for the Player.
public class Character : MonoBehaviour {
public int maxHealth;
public int currentHealth;
public HealthBar healthBar;
[SerializeField] protected float damageInterval = 2f;
protected float currentDamageInterval;
public Rigidbody2D rb;
void Start() {
rb = GetComponent<Rigidbody2D>();
currentHealth = maxHealth;
healthBar.SetMaxHealth(maxHealth);
}
public 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);
currentDamageInterval = damageInterval;
}
}
public class Player : Character {
[SerializeField] private Transform groundCheck;
[SerializeField] private LayerMask hazardLayer;
private SpriteRenderer sr;
private Color[] colors = { Color.red, Color.white };
private Coroutine damageFlash;
void Start() {
sr = GetComponent<SpriteRenderer>();
maxHealth = 10;
}
public override void Update() {
base.Update();
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);
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) {
sr.color = colors[index % 2];
index++;
yield return wait;
}
damageFlash = null;
}
}
Initially because the Player’s rigidbody2D was not assigned, the overrided portion of the TakeDamage method in the Player class could not run. It’s odd because in the Character’s Start method, I assign rb = GetComponent<Rigidbody2D>()
which I thought would in turn assign the Player’s rigidbody2D to rb. I ended up making the Rigidbody2D rb public at the top in the Character class and then assigned the Player’s rigidbody2D in the inspector. Now everything works.
But I was wondering if there’s a way to assign the Player’s (or any child class’s) rigidbody2D in the Character class by code instead? Or a cleaner way to do this?