0
\$\begingroup\$

I would like some advice on the architecture I am using, and if there's perhaps a better way to go about doing this / if I am over-complicating things.

I have a combo meter go up on the screen based off successive hits. My high level design is like this:

  • DamageCalculator.cs : a static class that is used on every successful hit
  • StatsManager.cs : a singleton that contains a lot of fields relating to stats like comboCount (an int that is the current number of combos)
  • ComboGUI.cs : a component that updates the GUI

The combo counter UI works as follows:

  1. When the player successfully hits an enemy more than once, DamageCalculator.cs triggers an event OnCombo()

  2. StatsManager.cs is subscribed to the OnCombo event, and when this triggers it does comboCount++

  3. ComboGui.cs is also subscribed to the OnCombo event, and when this triggers, it updates the UI to show the value of comboCount

The code:

DamageCalculator.cs

public static Action OnCombo;

// ...

public static void CalculateDamage(...)
{
  // ...
  if ( combo ) 
  {
    // ...
    OnCombo();
  }
  // ...
}

StatsManager.cs

public int comboCount

private void OnEnable()
{
  CalculateDamage.OnCombo += IncrementCombo;
}

private void OnDisable()
{
  CalculateDamage.OnCombo -= IncrementCombo;
}

private void IncrementCombo() 
{
  comboCount++;
}

// ...

ComboGUI.cs


private TextMeshProUGUI tmp;

private void OnEnable()
{
    DamageCalculator.OnCombo += SetCombo;
}

private void OnDisable()
{
    DamageCalculator.OnCombo -= SetCombo;
}

// ...

private void SetCombo()
{
    string comboText = StatsManager.Instance.comboCount + " COMBO";
    tmp.text = comboText;  // tmp is a TextMeshProUGUI
}

What makes me go 🤔🤔🤔 like there is probably a better way for this, is that I have no guarantee which events in StatsManager and ComboGUI will get triggered first when OnCombo fires. So I wonder if there is a pattern or better way of doing this, since it seems to be a pretty "routine" thing in games?

\$\endgroup\$
1
  • \$\begingroup\$ Is it only the player/main character that's able to do combos? If so, why use messages to invoke the StatsManager? I'd call the methods directly from DamageCalculator then post a message for the UI to check the new value and update. Conversely, if multiple entities can do combos, I'd store the state on the entity itself so everyone has their own counter. \$\endgroup\$
    – Basic
    Commented Feb 26, 2022 at 10:50

1 Answer 1

1
\$\begingroup\$

The first thing that hits me is singleton and static classes. You should use them only if it's necessary. Maby it is in your case.

The reason we usually (not always) stay away from statics and singletons is because it easily violates the SRP (single-responsibility principle).

Link to SRP

Composite pattern seems like a promising idea in your case when dealing with combos. It's a step-by-step pattern which gives more control of each step.

Link to Composite pattern

From what I can see in your code you're trying to use loosely coupled classes. That's great. Follow DRY (Don't repeat yourself) principle.

Link to DRY

This is not an exact answer, but I hope it provides an idea of what could lay a solid foundation to your project.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .