#Hybrid ECS System

1 messages · Page 1 of 1 (latest)

meager oak
#

I'm making a BitLife clone. It's nothing too performance-intensive, so I thought I'd give a made-up programming methodology I've never heard of a shot. My idea was to use an ECS system like Bevy to represent all the "in-world" data (people, places, objects, relationships, organizations, problems, etc.), and use Unity's MonoBehaviour stuff for UI. This way, one class has a dictionary storing all the relevant game data and systems operating on that data, and OOP only applies to the player's interactions with the systems.

Has anyone done anything like this before? Does it sound interesting, or am I doomed to fail?

#

Here's the essential code, if anyone's interested:


    public partial class WorldManager : MonoBehaviour
    {
        interface IComponentStorage
        {
            void Add(uint entity);
            void Remove(uint entity);
            bool Contains(uint entity);
        }

        class ComponentStorage<T> : IComponentStorage
            where T : class, IWorldEntityComponent, new()
        {
            public Dictionary<uint, T> Components = new();

            public void Add(uint entity)
            {
                if (Components.ContainsKey(entity))
                {
                    throw new InvalidOperationException($"Attempted to add a component of type {typeof(T)} to an entity that already had that component.");
                }
                Components[entity] = new T();
                Components[entity].Initialize(entity);
            }

            public void Set(uint entity, T component)
            {
                Components[entity] = component;
            }

            public void Remove(uint entity)
            {
                Components.Remove(entity);
            }

            public bool Contains(uint entity)
            {
                return Components.ContainsKey(entity);
            }
        }

        readonly Dictionary<Type, IComponentStorage> storages = new();
. . . 
        public IEnumerable<(uint, T)> Query<T>()
            where T : class, IWorldEntityComponent, new()
        {
            Type type = typeof(T);
            if (!storages.ContainsKey(type))
            {
                RegisterType<T>();
                yield break;
            }
            var dict = ((ComponentStorage<T>)storages[type]).Components;
            uint[] keys = dict.Keys.ToArray();
            foreach (uint key in keys)
            {
                yield return (key, dict[key]);
            }
        }
    }
sullen roost
#

The whole point of ECS is improving performance via cache hits and parallelization. If you're using non blittable types and normal dicts, you're basically losing most of reasons to use ecs. Maybe saving a tiny bit on reducing gameobject overhead.
The price is losing the readability, extendability and debugability of OOP. So you're basically paying the price without getting much out of it atm.

meager oak
# sullen roost The whole point of ECS is improving performance via cache hits and parallelizati...

I thought the point was to decrease the pains of organizing all types into a "hierarchy" by replacing inheritance with a system of data storage that more closely resembled the real world. I think "entities have collections of components" is much more intuitive than "all objects inherit the data and methods of their parents", especially for big simulations.

I've never heard of blittable types or any alternative to normal dicts. How should I be implementing this?

tidal schooner