Unity User Group Berlin Entitas

56
Entity sys tem architecture with Unity

Transcript of Unity User Group Berlin Entitas

Page 1: Unity User Group Berlin Entitas

Entity system architecturewith Unity

Page 2: Unity User Group Berlin Entitas

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

Page 3: Unity User Group Berlin Entitas

Wooga

Page 4: Unity User Group Berlin Entitas
Page 5: Unity User Group Berlin Entitas

Unity pain points4 Testability

4 Code sharing

4 Co-dependent logic

4 Querying

4 Deleting code

Page 6: Unity User Group Berlin Entitas

Testability

Page 7: Unity User Group Berlin Entitas

Code sharing

Page 8: Unity User Group Berlin Entitas

Co-dependent logic

Page 9: Unity User Group Berlin Entitas

Co-dependent logic

Page 10: Unity User Group Berlin Entitas

Co-dependent logic

Page 11: Unity User Group Berlin Entitas

Querying

Page 12: Unity User Group Berlin Entitas

Deleting code

Page 13: Unity User Group Berlin Entitas
Page 14: Unity User Group Berlin Entitas

EntitasMatch One Demo

Page 15: Unity User Group Berlin Entitas
Page 16: Unity User Group Berlin Entitas

Components are just data

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

4 no inheritance

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

Page 17: Unity User Group Berlin Entitas

PositionComponent

using Entitas;

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

Page 18: Unity User Group Berlin Entitas

GameBoardElementComponent

using Entitas;

public class GameBoardElementComponent : IComponent{

}

Page 19: Unity User Group Berlin Entitas

Entity is a container for components

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

Page 20: Unity User Group Berlin Entitas

Entity4 Add Components

4 Replace Components

4 Remove Components

Page 21: Unity User Group Berlin Entitas

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 22: Unity User Group Berlin Entitas

Pool contains all entities

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

Page 23: Unity User Group Berlin Entitas

Pool4 Create Entity

4 Destroy Entity

4 Get all Entities

4 Get Group

Page 24: Unity User Group Berlin Entitas

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 | +------------+

Page 25: Unity User Group Berlin Entitas

Get Group from pool

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

Page 26: Unity User Group Berlin Entitas

+------------------+ | 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 | +------------+

Page 27: Unity User Group Berlin Entitas

Behaviour

Page 28: Unity User Group Berlin Entitas

System4 Start / Execute

4 No State!!!

Page 29: Unity User Group Berlin Entitas

+------------------+ +-----------------------------+ | 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 | | | +------------+ | +-----------------------------+

Page 30: Unity User Group Berlin Entitas

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 31: Unity User Group Berlin Entitas

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

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

Page 32: Unity User Group Berlin Entitas

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

Page 33: Unity User Group Berlin Entitas

Reacting to changes in a Group4 On Entity added

4 On Entity removed

Page 34: Unity User Group Berlin Entitas

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 35: Unity User Group Berlin Entitas

Reactive System4 Executed only when entities in a group have changed

4 Aggregate and process changes

Page 36: Unity User Group Berlin Entitas

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

Page 37: Unity User Group Berlin Entitas

Optimizations

Page 38: Unity User Group Berlin Entitas

Componentsmutable vs immutable

Page 39: Unity User Group Berlin Entitas
Page 40: Unity User Group Berlin Entitas
Page 41: Unity User Group Berlin Entitas

EntityDictionary vs Array

Page 42: Unity User Group Berlin Entitas

Dictionarye.AddComponent(new PositionComponent());

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

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

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

Page 43: Unity User Group Berlin Entitas
Page 44: Unity User Group Berlin Entitas
Page 45: Unity User Group Berlin Entitas

Code Generator

Page 46: Unity User Group Berlin Entitas

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 47: Unity User Group Berlin Entitas

After Code Generation

e.ReplacePosition(10, 10);

Page 48: Unity User Group Berlin Entitas

Code Generator Demo

Page 49: Unity User Group Berlin Entitas

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;

Page 50: Unity User Group Berlin Entitas

Visual Debugging Demo

Page 51: Unity User Group Berlin Entitas
Page 52: Unity User Group Berlin Entitas

Entitas is

open sourcegithub.com/sschmid/Entitas-CSharp

Page 53: Unity User Group Berlin Entitas

Recap

Page 54: Unity User Group Berlin Entitas

Unity pain points4 Testability

4 Code sharing

4 Co-dependent logic

4 Querying

4 Deleting code

Page 55: Unity User Group Berlin Entitas

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

Page 56: Unity User Group Berlin Entitas

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

Simon Schmid | @s_schmid | github.com/sschmid

tinyurl.com/entitas