uniteeurope 2015

51
Entity system architecture with Unity

Upload: simon-schmid

Post on 13-Aug-2015

1.030 views

Category:

Software


1 download

TRANSCRIPT

Page 1: UniteEurope 2015

Entity system architecture

with Unity

Page 2: UniteEurope 2015

Maxim Zaks@icex33 | github.com/mzaks

Simon Schmid@s_schmid | github.com/sschmid

Page 3: UniteEurope 2015
Page 4: UniteEurope 2015
Page 5: UniteEurope 2015
Page 6: UniteEurope 2015

Unity pain points• Testability

• Code sharing

• Co-dependent logic

• Querying

• Deleting code

Page 7: UniteEurope 2015

Testability

Page 8: UniteEurope 2015

Code sharing

Page 9: UniteEurope 2015

Co-dependent logic

Page 10: UniteEurope 2015

Co-dependent logic

Page 11: UniteEurope 2015

Co-dependent logic

Page 12: UniteEurope 2015

Querying

Page 13: UniteEurope 2015

Deleting code

Page 14: UniteEurope 2015
Page 15: UniteEurope 2015

EntitasMatch One Demo

Page 16: UniteEurope 2015

PositionComponent

using Entitas;

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

Page 17: UniteEurope 2015

GameBoardElementComponent

using Entitas;

public class GameBoardElementComponent : IComponent {}

Page 18: UniteEurope 2015

Entity• Add

• Replace

• Remove

Page 19: UniteEurope 2015

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);}

Page 20: UniteEurope 2015

Pool• Create Entity

• Destroy Entity

• Get all Entities

• Get Group

Page 21: UniteEurope 2015

GroupPerformance optimization for querying

Matcher is a filter description

Page 22: UniteEurope 2015

Get Group

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

Page 23: UniteEurope 2015

+------------------+ | Pool | |------------------| | 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 | +------------------+ +-----------+ +-----------+ | | | +-------------+ | | e | Groups | | e e | +---> | +------------+ | e | | | | e | e | e | +--------|----+ e | | e | | e e | +------------+

Page 24: UniteEurope 2015

Behaviour

Page 25: UniteEurope 2015

System• Start / Execute

• No State

Page 26: UniteEurope 2015

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); }}

Page 27: UniteEurope 2015

Chain of Responsibility

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

Page 28: UniteEurope 2015

return new Systems() .Add(pool.CreateSystem <GameBoardSystem> ()) .Add(pool.CreateSystem <CreateGameBoardCacheSystem> ()) .Add(pool.CreateSystem <FallSystem> ()) .Add(pool.CreateSystem <FillSystem> ())

.Add(pool.CreateSystem <ProcessInputSystem> ())

.Add(pool.CreateSystem <RemoveViewSystem> ()) .Add(pool.CreateSystem <AddViewSystem> ()) .Add(pool.CreateSystem <RenderPositionSystem> ())

.Add(pool.CreateSystem <DestroySystem> ()) .Add(pool.CreateSystem <ScoreSystem> ());

Page 29: UniteEurope 2015

Reacting to changes in a Group• On Entity added

• On Entity removed

Page 30: UniteEurope 2015

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;}

Page 31: UniteEurope 2015

Reactive System• Executed only when entities in group have changed

Page 32: UniteEurope 2015

Render Position System

public class RenderPositionSystem : IReactiveSystem { public IMatcher GetTriggeringMatcher() { return Matcher.AllOf(Matcher.View, Matcher.Position); }

public GroupEventType GetEventType() { 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); } }}

Page 33: UniteEurope 2015

Optimizations

Page 34: UniteEurope 2015

Componentsmutable vs immutable

Page 35: UniteEurope 2015
Page 36: UniteEurope 2015
Page 37: UniteEurope 2015

EntityStore components inDictionary vs Array

Page 38: UniteEurope 2015

ComparisonDictionary

e.AddComponent(new PositionComponent());

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

Array

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

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

Page 39: UniteEurope 2015
Page 40: UniteEurope 2015
Page 41: UniteEurope 2015

Code Generator

Page 42: UniteEurope 2015

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);

Page 43: UniteEurope 2015

After Code Generation

e.ReplacePosition(10, 10);

Page 44: UniteEurope 2015

Code Generator Demo

Page 45: UniteEurope 2015

How does it work?

Page 46: UniteEurope 2015

Visual Debugging Demo

Page 47: UniteEurope 2015

Entitas isopen source

github.com/sschmid/Entitas-CSharp

Page 48: UniteEurope 2015

Recap

Page 49: UniteEurope 2015

Unity pain points• Testability

• Code sharing

• Co-dependent logic

• Querying

• Deleting code

Page 50: UniteEurope 2015

Advantages• Straightforward to achieve Determinism and therefore

Replay

• Simulation Speed (2x, 4x)

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

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

• For us it replaced all OO Design Patterns

Page 51: UniteEurope 2015

Q&Atinyurl.com/entitas