Table of Contents

First Module

Create your first module using the 4-struct pattern. For full pattern documentation, see Module Pattern.


Quick Start

  1. Right-click in the Project window
  2. Create > C# Module (or use Pixel Engine / Generate Module)
  3. Name it HealthSystem
  4. Unity generates the full Module Pattern boilerplate

Don't see the Create menu item? Run Pixel Engine / Install Script Templates and restart Unity. See Project Setup.


Example: HealthSystem

using PixelEngine.Architecture;
using System;

public class HealthSystem : IDisposable
{
    [Serializable]
    public readonly struct Configuration : IConfiguration
    {
        public readonly int maxHealth;
        public readonly float regenRate;

        public static readonly Configuration Default = new Configuration(
            maxHealth: 100,
            regenRate: 0f
        );

        public Configuration(int maxHealth, float regenRate)
        {
            this.maxHealth = maxHealth;
            this.regenRate = regenRate;
        }
    }

    [Serializable]
    public readonly struct Reference : IReference
    {
        public static readonly Reference Default = new Reference();
    }

    public struct State : IState
    {
        public int currentHealth;
        public bool isDead;
    }

    public class Components : IComponents { }

    private Configuration _configuration;
    private Reference _reference;
    private State _state;

    public Configuration configuration => _configuration;
    public Reference reference => _reference;
    public State state => _state;
    public Components components { get; private set; }

    // Events — event-driven, no polling
    public event Action<int> HealthChanged;
    public event Action Died;

    public HealthSystem()
        : this(Configuration.Default, Reference.Default) { }

    public HealthSystem(in Configuration configuration)
        : this(in configuration, Reference.Default) { }

    public HealthSystem(in Configuration configuration, in Reference reference)
    {
        _configuration = configuration;
        _reference = reference;
        _state = new State();
        this.components = new Components();

        Init();
    }

    public void SetConfiguration(in Configuration configuration)
    {
        _configuration = configuration;
    }

    public void Init()
    {
        _state.currentHealth = configuration.maxHealth;
        _state.isDead = false;
    }

    public void TakeDamage(int amount)
    {
        if (_state.isDead) return;

        _state.currentHealth = Math.Max(0, _state.currentHealth - amount);
        HealthChanged?.Invoke(_state.currentHealth);

        if (_state.currentHealth <= 0)
        {
            _state.isDead = true;
            Died?.Invoke();
        }
    }

    public void Dispose()
    {
        // cleanup in LIFO order
    }
}

Key Takeaways

Pattern Element Applied Here
readonly struct Configuration Immutable settings with constructor init
in keyword SetConfiguration(in Configuration) -- zero-copy
struct State with public fields External reads via property, internal mutation via _state field
event Action<T> HealthChanged and Died -- no polling
No Update() Fully event-driven
IDisposable Explicit cleanup

Next Steps