56
Entity sys tem architecture with Unity

Entitas System Architecture with Unity - Maxim Zaks and Simon Schmid

  • Upload
    wooga

  • View
    2.086

  • Download
    1

Embed Size (px)

Citation preview

Entity system architecturewith Unity

Maxim Zaks | @icex33 | github.com/mzaksSimon Schmid | @s_schmid | github.com/sschmid

Wooga

Unity pain points4 Testability

4 Code sharing

4 Co-dependent logic

4 Querying

4 Deleting code

Testability

Code sharing

Co-dependent logic

Co-dependent logic

Co-dependent logic

Querying

Deleting code

EntitasMatch One Demo

Components are just data

4 no Methods, no Start(), no Update()

4 no inheritance

+-----------+ | Component | |-----------| | Data | +-----------+

PositionComponent

using Entitas;

public class PositionComponent : IComponent{ public int x; public int y;}

GameBoardElementComponent

using Entitas;

public class GameBoardElementComponent : IComponent{

}

Entity is a container for components

+-----------+ | Entity | |-----------| | Component | | | | Component | | | | Component | +-----------+

Entity4 Add Components

4 Replace Components

4 Remove Components

Create Blocker Entity

public static Entity CreateBlocker(this Pool pool, int x, int y){ return pool.CreateEntity() .IsGameBoardElement(true) .AddPosition(x, y) .AddResource(Res.Blocker);}

Pool contains all entities

+------------------+ | Pool | |------------------| | e e | | e e | | e e | | e e e | | e e | | e e | | e e e | | e e e | +------------------+

Pool4 Create Entity

4 Destroy Entity

4 Get all Entities

4 Get Group

Groups are subsets of entities

4 Performance optimization for querying

4 Matcher is a filter description +-------------+ Groups: | e | Subsets of entities in the pool | e e | for blazing fast querying | +------------+ | e | | | | e | e | e | +--------|----+ e | | e | | e e | +------------+

Get Group from pool

_pool.GetGroup( Matcher.AllOf( Matcher.GameBoardElement, Matcher.Position ));

+------------------+ | Pool | Entitas in a nutshell |------------------| | e e | +-----------+ | e e---|----> | Entity | | e e | |-----------| | e e e | | Component | | e e | | | +-----------+ | e e | | Component-|----> | Component | | e e e | | | |-----------| | e e e | | Component | | Data | +------------------+ +-----------+ +-----------+ | | | +-------------+ Groups: | | e | Subsets of entities in the pool | | e e | for blazing fast querying +---> | +------------+ | e | | | | e | e | e | +--------|----+ e | | e | | e e | +------------+

Behaviour

System4 Start / Execute

4 No State!!!

+------------------+ +-----------------------------+ | Pool | | System | |------------------| |-----------------------------| | e e | | - Execute | | e e | | | | e e | | +-------------+ | | e e e | | | e | Groups | | e e |+----|->| e e | | | e e | | | +------------+ | | e e e | | | e | | | | | e e e | | | e | e | e | | +------------------+ | +--------|----+ e | | | | e | | | | e e | | | +------------+ | +-----------------------------+

MoveSystem

public void Execute() { var movables = _pool.GetGroup( Matcher.AllOf( Matcher.Move, Matcher.Position ));

foreach (var e in movables.GetEntities()) { var move = e.move; var pos = e.position; e.ReplacePosition(pos.x, pos.y + move.speed, pos.z); }}

Chain of Responsibility| ||-------------------------------- Game Loop --------------------------------|| |

+------------+ +------------+ +------------+ +------------+| | | | | | | || System | +---> | System | +---> | System | +---> | System || | | | | | | |+------------+ +------------+ +------------+ +------------+

return new Systems() .Add( pool.CreateGameBoardSystem ()) .Add( pool.CreateCreateGameBoardCacheSystem ()) .Add( pool.CreateFallSystem ()) .Add( pool.CreateFillSystem ())

.Add( pool.CreateProcessInputSystem ())

.Add( pool.CreateRemoveViewSystem ()) .Add( pool.CreateAddViewSystem ()) .Add( pool.CreateRenderPositionSystem ())

.Add( pool.CreateDestroySystem ()) .Add( pool.CreateScoreSystem ());

Reacting to changes in a Group4 On Entity added

4 On Entity removed

ScoreLabelController

void Start() { _pool.GetGroup(Matcher.Score).OnEntityAdded += (group, entity) => updateScore(entity.score.value);

updateScore(_pool.score.value);}

void updateScore(int score) { _label.text = "Score " + score;}

Reactive System4 Executed only when entities in a group have changed

4 Aggregate and process changes

Render Position Systempublic class RenderPositionSystem : IReactiveSystem { public IMatcher trigger { get { return Matcher.AllOf(Matcher.Position, Matcher.View); } }

public GroupEventType eventType { get { return GroupEventType.OnEntityAdded; } }

public void Execute(Entity[] entities) { foreach (var e in entities) { var pos = e.position; e.view.gameObject.transform.position = new Vector3(pos.x, pos.y); } }}

Optimizations

Componentsmutable vs immutable

EntityDictionary vs Array

Dictionarye.AddComponent(new PositionComponent());

var component = e.GetComponent<PositionComponent>();

Arraye.AddComponent(new PositionComponent(), 5);

var component = (PositionComponent)e.GetComponent(5);

Code Generator

Before Code Generation

PositionComponent component;if (e.HasComponent(ComponentIds.Position)) { e.WillRemoveComponent(ComponentIds.Position); component = (PositionComponent)e.GetComponent(ComponentIds.Position);} else { component = new PositionComponent();}component.x = 10;component.y = 10;e.ReplaceComponent(ComponentIds.Position, component);

After Code Generation

e.ReplacePosition(10, 10);

Code Generator Demo

var pool = Pools.pool;var e = pool.CreateEntity();

e.AddPosition(1, 2, 3);e.ReplacePosition(4, 5, 6);e.RemovePosition();

var posX = e.position.x;var hasPos = e.hasPosition;

e.isMovable = true;e.isMovable = false;var isMovable = e.isMovable;

Visual Debugging Demo

Entitas is

open sourcegithub.com/sschmid/Entitas-CSharp

Recap

Unity pain points4 Testability

4 Code sharing

4 Co-dependent logic

4 Querying

4 Deleting code

Advantages4 Straightforward to achieve Determinism and

therefore Replay

4 Simulation Speed (2x, 4x)

4 Headless Simulation, just remove systems which rely on GameObjects (render systems)

4 Save Game (Serialization / Deserialization) send data to backend on change

Q&AMaxim Zaks | @icex33 | github.com/mzaks

Simon Schmid | @s_schmid | github.com/sschmid

tinyurl.com/entitas