Skip to content

New feature: Map component / tag types to enum ids #123

@friflo

Description

@friflo

ComponentType.AsEnum<>()

It is basically quality of life features that simplifies branching on component / tag types.
It simplifies code and improves performance by replacing multiple branches (required before) by a switch statement.
This enables the compiler to generate a fast jump table for all cases.

Problem

You want to write a switch statement depending on a specific component type.

      foreach (var component in entity.Components)
      {
           // compile error: switch expects an integer. It cannot switch on class types.
          switch (component.Type.Type) {
              case Melee:    ...  break;
              case Ranged:   ...  break;
              case Tank:     ...  break;
              default:       ...  break;
          }
      }

Solution

Introduced a mapping functionality which enables to map component types to enum ids.

Therefore introducing a new method ComponentType.AsEnum<TEnum>().
It is used to return the enum id mapped to a component type.
This enables the use of switch statements on ComponentType's.
E.g. when iterating Entity.Components or Archetype.ComponentTypes.
Or to handle specific ComponentType's in event handlers like ComponentChanged.
It also improves project overview by grouping a domain of component types to an enum.

Example

Precondition: Some example component types.

struct Melee  : IComponent { }
struct Ranged : IComponent { }
struct Tank   : IComponent { }

enum declaration which maps component types to enum ids

public enum CombatType
{
    Undefined = 0, // 0 => unmapped component types switch to default case 
    [MapComponent<Melee>]   Melee,
    [MapComponent<Ranged>]  Ranged,
    [MapComponent<Tank>]    Tank,
}

Use the enum above to get the enum id from a component type: component.Type.AsEnum<CombatType>().

foreach (var component in entity.Components)
{
    // get the enum id mapped to the component type
    var combatId = component.Type.AsEnum<CombatType>();
    switch (combatId) {
        case CombatType.Melee:  var melee = entity.GetComponent<Melee>(); ...  break;
        case CombatType.Ranged: ... break;
        case CombatType.Tank:   ... break;
        default:                ... break;
    }
}

Other advantages

  • ComponentType.AsEnum<>() is blazing fast - a simple array lookup.
  • The compiler can generate fast jump tables in IL / assembly for the switch cases.
  • It enables nice code navigation by finding all usages of a specific enum.
  • Handy in debugger when tracing a switch statement or using breakpoints.

TagType.AsEnum<>()

The API for tags is similar to ComponentType.AsEnum<>().
The attribute used for tag type mapping is different: [MapTag<>]. E.g.

public enum CombatTags
{
    Undefined = 0,
    [MapTag<Melee>]   Melee,
    [MapTag<Ranged>]  Ranged,
    [MapTag<Tank>]    Tank,
}

To get the enum for a tag use:

    tag.AsEnum<CombatTags>();

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions