Skip to content

TeddyEngel/ChocolateECS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ChocolateECS

A simple hybrid Entity Component System for Unity.

License Unity

About

ChocolateECS is a lightweight ECS framework that bridges Unity's traditional MonoBehaviour workflow with Entity Component System patterns. It provides the benefits of ECS architecture—data-driven design, separation of concerns, and efficient component queries—while staying compatible with Unity's editor and existing workflows.

Hybrid approach: Components can be both IComponent and MonoBehaviour, letting you use the Unity Inspector while benefiting from ECS-style systems.

Features

  • Simple API — Just IComponent, ECSSystem, and Bootstrapper
  • Unity lifecycle integration — Systems hook into Awake, Start, Update, LateUpdate, FixedUpdate
  • Component queries — Get all components of a type, or query dual-component pairs
  • Automatic registration — Components auto-register when GameObjects are instantiated
  • Reflection-optimized — Only calls lifecycle methods you actually override
  • Factory patternECSFactory for runtime instantiation with proper ECS tracking
  • Singleton systems — Built-in SingletonSystem base class

Installation

  1. Copy all .cs files to your Unity project's Assets/ folder (or a subfolder)
  2. Create a bootstrapper and attach it to a GameObject in your scene

Quick Start

1. Create a Component

Components hold data. They implement IComponent and optionally inherit from MonoBehaviour for editor visibility:

using ChocolateECS;
using UnityEngine;

public class HealthComponent : MonoBehaviour, IComponent
{
    public int currentHealth = 100;
    public int maxHealth = 100;
}

2. Create a System

Systems contain logic. They extend ECSSystem and override lifecycle methods:

using ChocolateECS;
using System.Collections.Generic;
using UnityEngine;

public class HealthSystem : ECSSystem
{
    public override void OnUpdate(float deltaTime)
    {
        var healthComponents = ComponentManager.GetComponents(typeof(HealthComponent));

        for (int i = 0; i < healthComponents.Count; ++i)
        {
            var health = healthComponents[i] as HealthComponent;
            
            if (health.currentHealth <= 0)
                Debug.Log("Entity died!");
        }
    }
}

3. Create a Bootstrapper

The bootstrapper registers systems and attaches to a GameObject in your scene:

using ChocolateECS;

public class GameBootstrapper : Bootstrapper
{
    public override void Awake()
    {
        // Register your systems here
        RegisterSystem(new HealthSystem());
        
        // Always call base.Awake() LAST
        base.Awake();
    }
}

4. Set Up Your Scene

  1. Create an empty GameObject, name it "Bootstrapper"
  2. Attach your GameBootstrapper script
  3. Add HealthComponent to any GameObjects you want tracked
  4. Press Play

Component Queries

Single Component Query

Get all components of a specific type:

var enemies = ComponentManager.GetComponents(typeof(EnemyComponent));

for (int i = 0; i < enemies.Count; ++i)
{
    var enemy = enemies[i] as EnemyComponent;
    // Process enemy...
}

Dual Component Query

Get components that exist on the same GameObject as another component type. Useful for querying entities that have multiple components:

// Get all HealthComponents that are on GameObjects that also have EnemyComponent
var enemyHealths = ComponentManager.GetDualComponents(
    typeof(EnemyComponent),    // Primary component type
    typeof(HealthComponent)    // Secondary component type to return
);

for (int i = 0; i < enemyHealths.Count; ++i)
{
    var health = enemyHealths[i] as HealthComponent;
    // This health belongs to an enemy...
}

Runtime Instantiation

Use ECSFactory to instantiate GameObjects at runtime so their components are properly tracked:

using ChocolateECS;
using UnityEngine;

public class Spawner : MonoBehaviour
{
    public GameObject enemyPrefab;

    public void SpawnEnemy()
    {
        // Use ECSFactory instead of GameObject.Instantiate
        GameObject enemy = ECSFactory.Instantiate(enemyPrefab);
    }

    public void DestroyEnemy(GameObject enemy)
    {
        // Use ECSFactory instead of GameObject.Destroy
        ECSFactory.DestroyImmediate(enemy);
    }
}

System Lifecycle

Systems can override any of these methods (only overridden methods are called):

Method Unity Equivalent Description
OnAwake(List<ISystem> systems) Awake() Called once when bootstrapper awakens
OnStart() Start() Called once before first Update
OnEnable() OnEnable() Called when bootstrapper is enabled
OnUpdate(float deltaTime) Update() Called every frame
OnLateUpdate(float deltaTime) LateUpdate() Called after all Update calls
OnFixedUpdate() FixedUpdate() Called at fixed time intervals
OnDisable() OnDisable() Called when bootstrapper is disabled
OnDestroy() OnDestroy() Called when bootstrapper is destroyed

API Reference

IComponent

Marker interface for components. Implement on MonoBehaviours or plain classes.

public class MyComponent : MonoBehaviour, IComponent
{
    public float speed;
}

ECSSystem

Base class for systems. Override lifecycle methods as needed.

public class MySystem : ECSSystem
{
    public override void OnUpdate(float deltaTime) { }
}

SingletonSystem

Alternative base class for systems that don't need multiple instances.

public class AudioSystem : SingletonSystem
{
    public override void OnUpdate(float deltaTime) { }
}

ComponentManager

Accessed via ComponentManager property in systems.

Method Description
GetComponents(Type type) Returns all components of the specified type
GetDualComponents(Type main, Type secondary) Returns secondary components on GameObjects that also have main component
CountComponents(Type type) Returns count of components of specified type

ECSFactory

Static factory for runtime GameObject management.

Method Description
Instantiate(GameObject prefab) Instantiate and register components
DestroyImmediate(GameObject obj) Unregister components and destroy

Bootstrapper

Abstract MonoBehaviour that orchestrates the ECS. Extend and override Awake() to register systems.

Method Description
RegisterSystem(ISystem system) Register a system to receive lifecycle calls

Project Structure

ChocolateECS/
├── Bootstrapper.cs       # Scene entry point, system orchestration
├── ComponentManager.cs   # Component registration and queries
├── ECSFactory.cs         # Runtime instantiation with tracking
├── ECSSystem.cs          # Base class for systems
├── SingletonSystem.cs    # Base class for singleton systems
├── IComponent.cs         # Component marker interface
├── ISystem.cs            # System interface
└── Examples/
    ├── Bootstrappers/    # Example bootstrapper
    ├── Components/       # Example components
    └── Systems/          # Example systems

License

MIT License — see LICENSE for details.

About

A simple hybrid Entity Component System for Unity

Topics

Resources

License

MIT, Unknown licenses found

Licenses found

MIT
LICENSE
Unknown
LICENSE.meta

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages