I’m trying something a little different with this project with the way classes are structured.
Take this example and so far the only use case I’ve found for it. A character with many working components. Usually, I would have the character class hold the components and take and send information from one to another.
The problem with this is that when something is removed, alot of work needs to be done since alot of logic relies on that class. Testing and structuring it is quite a hassle since things are constantly being changed.
This time I decided to structure it in a way where the main class simply holds the data where everything is public and have dependant classes just get whatever they need from there and perform the logic.
The problem with this is everything is public and exposed, it’s easy to setup and debug and change things but it can run into the same issue as before where removing something can affect many classes.
So now I ended up with something like this, I’m not sure where this is going but my goal is to have everything work independently where theres very little reliance on custom classes and only unity classes.
public class EnemyCharacter : MonoBehaviour, ITakeDamage, IHaveCharacterStats, IHaveLives
{
public System.Action OnDisable;
public System.Action OnEnable;
public System.Action<int> OnTakeDamage { get; set; }
public System.Action OnReachedNoHealth { get; set; }
public System.Action OnDie { get; set; }
public System.Action OnSpawn { get; set; }
public System.Action OnStatChange { get; set; }
}
public class CharacterLivesHandler : MonoBehaviour
{
IHaveLives iHaveLivesBase;
private void Awake()
{
iHaveLivesBase = GetComponent<IHaveLives>();
GetComponent<IHaveCharacterStats>().OnReachedNoHealth += Die;
}
private void Die()
{
iHaveLivesBase.OnDie?.Invoke();
gameObject.SetActive(false);
}
public void Spawn()
{
iHaveLivesBase?.OnSpawn?.Invoke();
}
}
public class CharacterStats : MonoBehaviour
{
public IHaveCharacterStats Base;
public int HealthCurrent
{
get => _healthCurrent;
set
{
_healthCurrent = Mathf.Clamp(value, 0, _healthMax);
if (_healthCurrent <= 0)
{
Base?.OnReachedNoHealth?.Invoke();
}
}
}
[SerializeField] private int _healthCurrent;
[SerializeField] private int _healthMax;
public int HealthMax
{
get => _healthMax;
set
{
_healthMax = value;
_healthCurrent = Mathf.Max(_healthCurrent, _healthMax);
}
}
[SerializeField] private int _power;
public int Power
{
get => _power;
set
{
_power = value;
Base.OnStatChange?.Invoke();
}
}
private void Awake()
{
Base = GetComponent<IHaveCharacterStats>();
GetComponent<ITakeDamage>().OnTakeDamage += (int damage) =>
{
// Debug.Log(damage);
HealthCurrent -= damage;
};
GetComponent<IHaveLives>().OnSpawn += () => HealthCurrent = HealthMax;
}
}
The main problem again is everything is exposed and second heavy reliance on events.
The problems I always run into isnt creating the characters but to integrate an actual game into them.
Everything’s fine on testing because it’s all done on awake and the enemies do their things right away but where I get stuck is integrating the actual game where they shift their behaviors on the state of the game.
An example would be during testing, when enemies spawn in they immediately start attacking the player. Now during the game, the enemies will die if a condition like boss death occurs or if the timer runs out they’ll stop attacking.
Maybe I should make a manager class that handles what I just mentioned by having a state that’s for the game and one for testing? That’s just creating another dependency to the project right?