Skip to content
forked from chromealex/ecs

ECS for Unity with full game state automatic rollbacks

License

Notifications You must be signed in to change notification settings

cleancoindev/ecs

 
 

Repository files navigation

ME.ECS

ME.ECS - it's ECS implementation for Unity Engine with full state automatic rollbacks. In general ME.ECS should be used for multiplayer real-time strategy games games because of Network support out of the box with automatic rollbacks. You can set up tick time for your game and system should store your state and automatically sync game instances using minimum traffic (just user RPC calls, no full game sync required).

Demo

(Click image to play)

Tutorial 01: Initialization

(Click image to play)

Default Modules

States History Module

Submodules: IEventRunner

Store states checkpoints and all added events sorting by custom order. Can simulate world tick by tick to restore state with deterministic logic.

Network Module

Submodules: ITransport, ISerializer
Dependencies: StatesHistoryModule

Send RPCs through any network transport implemented from the interface, serialize and deserialize data. By default is the EventRunner for StatesHistoryModule, just send all incoming events to the network and receive events from transport and send them into StatesHistoryModule.

Views Module

Submodules: IViewsProvider (Implemented: GameObjectProvider, ParticlesProvider, DrawMeshProvider)

Synchronizing current world state to views. Automatically destroy and create views (with pools), sync with current entities state and process all ticks correctly to restore visual state even objects already destroyed for a long time ago.

FPS Module

Module just show FPS/FPSMax/FPSMin in world viewer.

How It Works

World (IWorld<TState>)

The container for all components like modules, systems, etc. You can store multiple worlds with different states, entities, components, modules and systems.

State (IState<TState>)

User-side data storage. Just need to implement a couple of methods:

int GetHash() // If possible returns the most unique hash
void Initialize(IWorld<State> world, bool freeze, bool restore) // Register all filter and component storages in the world
void CopyFrom(State other) // copies other state into current
void OnRecycle() // return all used resources into pools

Modules (IModule<TState>)

Modules do visual update on the beginning of the frame and on the beginning of every tick.

Systems (ISystem<TState>)

Systems do visual update at the end of the frame and on the ending of every tick.

Entities (IEntity)

Entities are storing base data of your objects like position, rotation, user data, etc.

Components (IComponent<TEntity>)

Components are working with a certain Entity type and implements AdvanceTick (in which you can add logic of your tick) and CopyFrom. Or you can use components like a markers. Btw, you can use IComponentOnce interface to be sure all components removed at the end of current tick. Also you can add IComponentShared and IComponentSharedOnce to store any shared data.

Markers (IMarker)

Markers needed to implement UI events or something that doesn't exist in game state.

Update

Example

1. World Initialization

// Initialize new world with custom tick time and custom world id
// If customWorldId ignored - it will setup automatically
WorldUtilities.CreateWorld(ref this.world, 0.133f, [customWorldId]);
this.world.AddModule<StatesHistoryModule>(); // Add custom states history module
this.world.AddModule<NetworkModule>();       // Add custom network module

2. State Initialization

// Create new state and set it by default
this.world.SetState(WorldUtilities.CreateState<State>());

3. Register Prefabs

// Register point source prefab with custom views provider
// GameObject (Will call Instantiate/Destroy)
this.pointViewSourceId = this.world.RegisterViewSource<Point, UnityGameObjectProvider>(this.pointSource);
// Register unit source prefab with custom views provider
// Particles (Will draw particles instead of regular GameObjects)
this.unitViewSourceId = this.world.RegisterViewSource<Unit, UnityParticlesProvider>(this.unitSource);
// Register unit source prefab with auto views provider
// Here provider should be choosen by unitSource2 type
this.unitViewSourceId2 = this.world.RegisterViewSource<Unit>(this.unitSource2);
...

4. Create Default Entities with Data

// Create default data for all players at this level
var p1 = this.world.AddEntity(new Point() {
  position = new Vector3(0f, 0f, 3f),
  unitsCount = 99f,
  increaseRate = 1f
});
var p2 = this.world.AddEntity(new Point() {
  position = new Vector3(0f, 0f, -3f),
  unitsCount = 1f,
  increaseRate = 1f
});
...

5. Instantiate Views (Don't worry, you can call Instantiate on any thread)

// Attach views onto entities
// You can attach any count of views on each entity
// But here are some limitations: for now you couldn't attach one source twice, only different sources for one entity allowed.
this.world.InstantiateView<Point>(this.pointViewSourceId, p1);  // Add view with id pointViewSourceId onto p1 Entity
this.world.InstantiateView<Point>(this.pointViewSourceId, p2);  // Add view with id pointViewSourceId onto p2 Entity
...

6. Add Systems

// Add custom systems
this.world.AddSystem<InputSystem>();
this.world.AddSystem<PointsSystem>();
this.world.AddSystem<UnitsSystem>();
...

7. Save Reset State

// Save current world state as a Reset State.
// It's very important to do after the scene loaded and all default entities were set.
// Sure after that you could run any of API methods, but be sure you call them through RPC calls.
this.world.SaveResetState();

Upcoming plans

  • Implement automatic states history with rollback system (100% done)
  • Decrease initialization time and memory allocs (90% done)
  • Random support to generate random numbers, store RandomState in game state (100% done)
  • Add full game example (80% done)
  • Add auto sync on packets drop (TCP) (100% done)
  • Add auto sync on packets drop (UDP) (20% done)
  • Views module (100% done)
  • Implement UnityGameObjectProvider (100% done)
  • Implement UnityParticlesProvider (95% done) - MeshFilter/MeshRenderer support, inner ParticleSystem effects support, but rewind is not fully implemented.
  • Implement UnityDrawMeshProvider (90% done) - only MeshFilter/MeshRenderer support added
  • Add particle system simulation support on state change (100% done)
  • Add shared components support (100% done)
  • Add multithreading support (15% done)
  • Preformance refactoring (70% done)

About

ECS for Unity with full game state automatic rollbacks

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C# 92.4%
  • ShaderLab 6.7%
  • HLSL 0.9%