Is there a way to linking two data values, simpler than Dictionary?

Viewed 92

I'm working on a game with Unity in which the player has some spells. I have an enum that contains all of these and I want to attach them a bool value. I think I can use a System.Collections.Generics.Dictionary with the Spells as Keys and the Boolean as Value, but is there a simpler way to do such a thing?

4 Answers

You can simplify Dictionary<Spell, bool> hasSpell into HashSet<Spell> (you want only Key, not Value from the initial Dictionary):

  public enum Spell { 
    Fireball,
    Levitate,
    Resurrect,   
  };

  ...

  HashSet<Spell> abilities = new HashSet<Spell>() { 
    Spell.Fireball, 
    Fireball.Levitate,
  };

  ...

  // If the hero can resurrect...
  if (abilities.Contains(Spell.Resurrect)) {
    // ...let him raises from the dead
  }

Individually the simplest way of pairing two data values is to use a value tuple. This feature can be used on any Unity version from 2018.3 onwards as that's when it stopped using outdated C# versions.

var spell = ("Fireball", true);

If you'd rather be more explicit about types:

(string, bool) spell = ("Fireball", true);

(This is another approach in making things "easy")

Yes, dictionnary are simple collections but it's not really what I expect. I want something just to say "this value from the enum is true, this one is false"

This sounds you need a nice class that encapsulates the less-simple or more low-level structure (e.g. dictionary or hashset). This will things easy from the outside / API-isde.

For example:

public enum Spell
{
    Firebolt,
    Rage,
    Flash,
};


public class SpellState
{
    private HashSet<Spell> _enabled = new HashSet<Spell>();

    public void EnableSpell(Spell spell)
    {
        _enabled.Add(spell);
    }

    public void DisableSpell(Spell spell)
    {
         _enabled.Remove(spell);
    }

    public bool IsSpellEnabled(Spell spell)
    {
        return _enabled.Contains(spell);
    }
}

Usage

var spellState = new SpellState();

spellState.EnableSpell(Spell.Rage);

// later
if (spellState.IsSpellEnabled(Spell.Flash))
{
    spellState.DisableSpell(Spell.Rage);
    // todo
}

You could use a single bitwise value by defining enum flags, so long as you have a limited number of spells.

[Flags]
public enum Spell : long
{
    Firebolt = (1 << 0),
    Rage = (1 << 1),
    Flash = (1 << 2),
};
Related