Download - UniteEurope 2015
![Page 1: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/1.jpg)
Entity system architecture
with Unity
![Page 2: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/2.jpg)
Maxim Zaks@icex33 | github.com/mzaks
Simon Schmid@s_schmid | github.com/sschmid
![Page 3: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/3.jpg)
![Page 4: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/4.jpg)
![Page 5: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/5.jpg)
![Page 6: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/6.jpg)
Unity pain points• Testability
• Code sharing
• Co-dependent logic
• Querying
• Deleting code
![Page 7: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/7.jpg)
Testability
![Page 8: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/8.jpg)
Code sharing
![Page 9: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/9.jpg)
Co-dependent logic
![Page 10: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/10.jpg)
Co-dependent logic
![Page 11: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/11.jpg)
Co-dependent logic
![Page 12: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/12.jpg)
Querying
![Page 13: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/13.jpg)
Deleting code
![Page 14: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/14.jpg)
![Page 15: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/15.jpg)
EntitasMatch One Demo
![Page 16: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/16.jpg)
PositionComponent
using Entitas;
public class PositionComponent : IComponent{ public int x; public int y;}
![Page 17: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/17.jpg)
GameBoardElementComponent
using Entitas;
public class GameBoardElementComponent : IComponent {}
![Page 18: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/18.jpg)
Entity• Add
• Replace
• Remove
![Page 19: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/19.jpg)
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](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/20.jpg)
Pool• Create Entity
• Destroy Entity
• Get all Entities
• Get Group
![Page 21: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/21.jpg)
GroupPerformance optimization for querying
Matcher is a filter description
![Page 22: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/22.jpg)
Get Group
_pool.GetGroup( Matcher.AllOf( Matcher.GameBoardElement, Matcher.Position ));
![Page 23: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/23.jpg)
+------------------+ | 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](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/24.jpg)
Behaviour
![Page 25: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/25.jpg)
System• Start / Execute
• No State
![Page 26: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/26.jpg)
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](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/27.jpg)
Chain of Responsibility
+------------+ +------------+ +------------+ +------------+| | | | | | | || System | +---> | System | +---> | System | +---> | System || | | | | | | |+------------+ +------------+ +------------+ +------------+
![Page 28: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/28.jpg)
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](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/29.jpg)
Reacting to changes in a Group• On Entity added
• On Entity removed
![Page 30: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/30.jpg)
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](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/31.jpg)
Reactive System• Executed only when entities in group have changed
![Page 32: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/32.jpg)
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](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/33.jpg)
Optimizations
![Page 34: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/34.jpg)
Componentsmutable vs immutable
![Page 35: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/35.jpg)
![Page 36: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/36.jpg)
![Page 37: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/37.jpg)
EntityStore components inDictionary vs Array
![Page 38: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/38.jpg)
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](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/39.jpg)
![Page 40: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/40.jpg)
![Page 41: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/41.jpg)
Code Generator
![Page 42: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/42.jpg)
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](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/43.jpg)
After Code Generation
e.ReplacePosition(10, 10);
![Page 44: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/44.jpg)
Code Generator Demo
![Page 45: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/45.jpg)
How does it work?
![Page 46: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/46.jpg)
Visual Debugging Demo
![Page 47: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/47.jpg)
Entitas isopen source
github.com/sschmid/Entitas-CSharp
![Page 48: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/48.jpg)
Recap
![Page 49: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/49.jpg)
Unity pain points• Testability
• Code sharing
• Co-dependent logic
• Querying
• Deleting code
![Page 50: UniteEurope 2015](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/50.jpg)
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](https://reader030.vdocument.in/reader030/viewer/2022013108/55cc9464bb61eb6e208b459e/html5/thumbnails/51.jpg)
Q&Atinyurl.com/entitas