- Home /
How to Use Components and Interfaces together?
I have just transitioned the way I build my player to components and I am wondering if I am using components and interfaces in the correct way. The way I decide if it should be a component or an interface is - if it will have a common implementation it's a component, if it will have a varying implementation, it's an interface. I.e. Health, health will behave the same no matter what it is attached to. However, OnDeath will be different for each thing it is attached to, so instead of having a Killable component, I have a IKillable interface that the object that is killable implements.
I have 4 main components which are held in the Entity Interface:
Health
IInput
EntityAnimator
Movement
My player implements the interface Entity, as all entities will have these elements (at least NPC and player entities)
Health can be buffed, and also damaged so I had it implement the IBuff and IDamageable interfaces.
An Entity can be killed, so I implement the IKillable interface.
My Observation
As I was writing this I came up with a different question/observation. I think I am on the kind of right approach in that if components will be different, and make them interfaces, but instead of having say IEntity implement IKillable, have a component - PlayerKillable and have THAT implement IKillable, and then have IEntity contain an IKillable component. Would that be the right way to handle components and interfaces? If so, the implementation I have below doesn't change much besides the fact that my current components will now implement a base component, correct?
Original Question
My question is - Should I be having these be interfaces? IKillable, IBuff, IDamageable, etc. Or should they be components themselves? The reason I have them as interfaces is because their implementation will change based on the entity. I think I may have answered my question there, but I also want to verify that I am going down the correct path before I get too far.
A followup question would be, I know entites will have Movement, Input, and Animations - however these will be different depending on if it's an NPC or player, so does it make sense to make all of them interfaces like I did for IInput and have the IEntity contain them? Or is there another way I should do it?
Another would be, using Health as an example, how do I differentiate between what should be an interface that the component implements, or a component that the component contains? What I mean by this is the example of IDamageable. Health will not be the only thing I have that is Damageable, an example would be Mana, mana is also Damageable, but in a different way than health would be (potentially), which is why I have it as an interface. What instances would I rather have a component instead of an interface using the example of IDamageable? How do I know when to use one or the other?
Code
Here is the related code -I left out the EntityAnimator and IInput, because I need to make it an IAnimator as players will be animated differently from enemies and because IInput is empty currently:
IDamageable
public interface IDamageable {
void OnHeal(int amount);
void OnDamage(int amount);
}
IKillable
public interface IKillable {
void OnDeath();
}
IBuff
public interface IBuff {
void OnBuff(int amount);
void OnDebuff(int amount);
}
Health
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Health : MonoBehaviour, IBuff, IDamageable {
public int MaxHitPoints = 10;
public int EffectiveHitPoints;
void Awake()
{
EffectiveHitPoints = MaxHitPoints;
HitPoints = EffectiveHitPoints;
}
public int HitPoints
{
get
{
return hitPoints;
}
set
{
hitPoints = Mathf.Clamp(value, 0, EffectiveHitPoints);
if(hitPoints == 0)
{
gameObject.SendMessage("OnDeath");
}
}
}
private int hitPoints;
// Event Listeners
public void OnDamage(int amount)
{
//Debug.Log("Health.OnDamage: " + amount);
HitPoints -= amount;
}
public void OnHeal(int amount)
{
//Debug.Log("Health.OnHeal: " + amount);
HitPoints += amount;
}
public void OnBuff(int amount)
{
//Debug.Log("Health.OnBuff: " + amount);
EffectiveHitPoints += amount;
}
public void OnDebuff(int amount)
{
//Debug.Log("Health.OnDebuff: " + amount);
EffectiveHitPoints -= amount;
}
}
Movement
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour {
Rigidbody2D rigidBody;
void Awake()
{
rigidBody = gameObject.GetComponent<Rigidbody2D>();
}
void OnMove(Vector2 movementVector)
{
//Debug.Log("Movement: " + movementVector);
rigidBody.MovePosition(rigidBody.position + movementVector * Time.deltaTime);
}
void OnTeleport(Vector2 teleportLocation)
{
rigidBody.MovePosition(teleportLocation);
}
}
IEntity
public interface IEntity : IKillable
{
Health Health
{
get;
set;
}
Movement Movement
{
get;
set;
}
IInput EntityInput
{
get;
set;
}
EntityAnimator EntityAnimator
{
get;
set;
}
}
Player
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour, IEntity
{
private Health health;
public Health Health { get; set; }
private Movement movement;
public Movement Movement { get; set; }
private IInput entityInput;
public IInput EntityInput { get; set; }
private EntityAnimator entityAnimator;
public EntityAnimator EntityAnimator { get; set; }
void Awake()
{
Health = gameObject.GetComponent<Health>();
Movement = gameObject.GetComponent<Movement>();
EntityInput = gameObject.GetComponent<UserInput>();
EntityAnimator = gameObject.GetComponent<EntityAnimator>();
}
public void OnDeath()
{
Debug.Log("I died");
}
}
Your answer
Follow this Question
Related Questions
Is it possible to mark MonoBehaviour as EditorOnly 2 Answers
When do components of loaded prefabs get initialized? 1 Answer
Disabling GameObject doesn't disable components 0 Answers
Enabling multiple Monobehaviour Components in a game object 1 Answer
Any recommended books/resources on component-based design? 0 Answers