ecs architecture with unity by example - unite europe 2016

67
ECS Architecture with Unity // by Example Entitas // @entitas_csharp // github.com/sschmid/Entitas-CSharp Maxim Zaks // @icex33 // github.com/mzaks Simon Schmid // @s_schmid // github.com/sschmid

Upload: simon-schmid

Post on 14-Apr-2017

1.260 views

Category:

Software


6 download

TRANSCRIPT

Page 1: ECS architecture with Unity by example - Unite Europe 2016

ECS Architecturewith Unity// by Example

Entitas // @entitas_csharp // github.com/sschmid/Entitas-CSharp

Maxim Zaks // @icex33 // github.com/mzaks

Simon Schmid // @s_schmid // github.com/sschmid

Page 2: ECS architecture with Unity by example - Unite Europe 2016
Page 3: ECS architecture with Unity by example - Unite Europe 2016
Page 4: ECS architecture with Unity by example - Unite Europe 2016
Page 5: ECS architecture with Unity by example - Unite Europe 2016
Page 6: ECS architecture with Unity by example - Unite Europe 2016

Unity pain points• Testability• Code sharing• Co-dependent logic• Querying• Deleting code

Page 7: ECS architecture with Unity by example - Unite Europe 2016

YouTubesearch

Entitas Unitytinyurl.com/entitas

Page 8: ECS architecture with Unity by example - Unite Europe 2016

Entitas isopen sourcegithub.com/sschmid/Entitas-CSharp

Page 9: ECS architecture with Unity by example - Unite Europe 2016

Agenda:• Introduction to Entitas• User Input• Integration with Unity Collision System• Replayable games• Integration with Unity UI System• Quizz

Page 10: ECS architecture with Unity by example - Unite Europe 2016
Page 11: ECS architecture with Unity by example - Unite Europe 2016
Page 12: ECS architecture with Unity by example - Unite Europe 2016
Page 13: ECS architecture with Unity by example - Unite Europe 2016
Page 14: ECS architecture with Unity by example - Unite Europe 2016
Page 15: ECS architecture with Unity by example - Unite Europe 2016

Unity Components:Data + Behaviour

Entitas ComponentsData only

Page 16: ECS architecture with Unity by example - Unite Europe 2016

// Data only - no behaviour

public class PositionComponent : IComponent { public Vector3 value;}

public class MovableComponent : IComponent {}

Page 17: ECS architecture with Unity by example - Unite Europe 2016

+------------------+ | 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 18: ECS architecture with Unity by example - Unite Europe 2016

Logic?

Page 19: ECS architecture with Unity by example - Unite Europe 2016

public class VelocitySystem : IExecuteSystem {

public void Execute() {

var movables = Pools.pool.GetGroup( Matcher.AllOf( Matcher.Velocity, Matcher.Position ));

foreach (var e in movables.GetEntities()) { var pos = e.position.value; e.ReplacePosition(pos + e.velocity.value); } }}

Page 20: ECS architecture with Unity by example - Unite Europe 2016

SystemsChain of Responsibility

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

Page 21: ECS architecture with Unity by example - Unite Europe 2016

Systems in Entitas• Initialize System• Execute System• Reactive System

• only processes changed entities

Page 22: ECS architecture with Unity by example - Unite Europe 2016

Agenda:• Introduction to Entitas ✅• User Input• Integration with Unity Collision System• Replayable games• Integration with Unity UI System• Quizz

Page 23: ECS architecture with Unity by example - Unite Europe 2016

Demo ShmupShoot ’em up• Entitas Visual Debugging• Blueprints

Page 24: ECS architecture with Unity by example - Unite Europe 2016

public class InputController : MonoBehaviour {

void Update() { var inputPool = Pools.input;

// Move var moveX = Input.GetAxisRaw("Horizontal"); var moveY = Input.GetAxisRaw("Vertical"); inputPool.CreateEntity() .AddMoveInput(new Vector3(moveX, moveY)) .AddInputOwner("Player1");

// Shoot var fire = Input.GetAxisRaw("Fire1"); if (fire != 0) { inputPool.CreateEntity() .IsShootInput(true) .AddInputOwner("Player1"); } }}

Page 25: ECS architecture with Unity by example - Unite Europe 2016
Page 26: ECS architecture with Unity by example - Unite Europe 2016

public class CollisionEmitter : MonoBehaviour {

public string targetTag;

void OnCollisionEnter(Collision collision) { if (collision.gameObject.CompareTag(targetTag)) { var link = gameObject.GetEntityLink(); var targetLink = collision.gameObject.GetEntityLink();

Pools.input .CreateEntity() .AddCollision(link.entity, targetLink.entity); } }}

Page 27: ECS architecture with Unity by example - Unite Europe 2016
Page 28: ECS architecture with Unity by example - Unite Europe 2016

Great, butPerformance?

Page 29: ECS architecture with Unity by example - Unite Europe 2016
Page 30: ECS architecture with Unity by example - Unite Europe 2016

Unity vs Entitas1000 objects with 2 components

• Memory: 9x (2.9 MB vs 0.32 MB)• CPU: 17x (105ms vs 6ms)

Page 31: ECS architecture with Unity by example - Unite Europe 2016
Page 32: ECS architecture with Unity by example - Unite Europe 2016

Entitas...• reuses Entities• reuses Components• caches Groups• can index Components

Page 33: ECS architecture with Unity by example - Unite Europe 2016

Entitas...• reuses Entities• reuses Components• caches Groups• can index Components

so nice

Page 34: ECS architecture with Unity by example - Unite Europe 2016
Page 35: ECS architecture with Unity by example - Unite Europe 2016

Agenda:• Introduction to Entitas ✅

• User Input ✅

• Integration with Unity Collision System ✅• Replayable games• Integration with Unity UI System• Quizz

Page 36: ECS architecture with Unity by example - Unite Europe 2016

Demo Reactive UI

Page 37: ECS architecture with Unity by example - Unite Europe 2016

Show me your tables, and I won’t usually need your flowcharts; they’ll be obvious.— Fred Brooks

Page 38: ECS architecture with Unity by example - Unite Europe 2016

[SingleEntity]public class TickComponent : IComponent{ public long currentTick;}

[SingleEntity]public class ElixirComponent : IComponent{ public float amount;}

public class ConsumeElixirComponent : IComponent{ public int amount;}

[SingleEntity]public class PauseComponent : IComponent {}

Page 39: ECS architecture with Unity by example - Unite Europe 2016

public class TickUpdateSystem : IInitializeSystem, IExecuteSystem, ISetPool{ Pool _pool;

public void SetPool(Pool pool) { _pool = pool; }

public void Initialize() { _pool.ReplaceTick(0); }

public void Execute() { if (!_pool.isPause) { _pool.ReplaceTick(_pool.tick.currentTick + 1); } }}

Page 40: ECS architecture with Unity by example - Unite Europe 2016

public class ProduceElixirSystem : IInitializeSystem, IReactiveSystem, ISetPool{

public TriggerOnEvent trigger { get { return Matcher.Tick.OnEntityAdded(); }}

public void Initialize() { _pool.ReplaceElixir(0); }

public void Execute(List<Entity> entities) { var newAmount = _pool.elixir.amount + ProductionStep; newAmount = Math.Min(ElixirCapacity, newAmount); _pool.ReplaceElixir(newAmount); }}

Page 41: ECS architecture with Unity by example - Unite Europe 2016
Page 42: ECS architecture with Unity by example - Unite Europe 2016
Page 43: ECS architecture with Unity by example - Unite Europe 2016

public class ConsumeButtonBehaviour : MonoBehaviour, IPauseListener, IElixirListener {

//...

public void ButtonPressed() { if(Pools.pool.isPause) return; Pools.pool.CreateEntity().AddConsumeElixir(consumptionAmount); }}

Page 44: ECS architecture with Unity by example - Unite Europe 2016
Page 45: ECS architecture with Unity by example - Unite Europe 2016

[SingleEntity]public class ConsumptionHistoryComponent : IComponent{ public List<ConsumptionEntry> entries;}

public class ConsumptionEntry{ public readonly long tick; public readonly int amount;

public ConsumptionEntry(long tick, int amount) { this.tick = tick; this.amount = amount; }}

Page 46: ECS architecture with Unity by example - Unite Europe 2016

public class JumpInTimeComponent : IComponent{ public long targetTick;}

public class TimePickerBehaviour : MonoBehaviour, IPauseListener{

// ...

public void ChangedValue() { Pools.pool.ReplaceJumpInTime((long)GetComponent<Slider>().value); }}

Page 47: ECS architecture with Unity by example - Unite Europe 2016
Page 48: ECS architecture with Unity by example - Unite Europe 2016
Page 49: ECS architecture with Unity by example - Unite Europe 2016

ReplaySystemfor tick: 0..< targetTick

Page 50: ECS architecture with Unity by example - Unite Europe 2016

How do we get a reference to Logic Systems?

Page 51: ECS architecture with Unity by example - Unite Europe 2016

Dependency managment with Entitas[SingleEntity]public class LogicSystemsComponent : IComponent{ public Systems systems;}

pool.SetLogicSystems(new Systems() .Add(pool.CreateSystem<TickUpdateSystem>()) .Add(pool.CreateSystem<ProduceElixirSystem>()) .Add(pool.CreateSystem<ConsumeElixirSystem>()) .Add(pool.CreateSystem<PersistConsumeElixirSystem>()) .Add(pool.CreateSystem<ConsumeElixirCleanupSystem>()));

Page 52: ECS architecture with Unity by example - Unite Europe 2016

UI notification systems• NotifyTickListenersSystem• NotifyPauseListenersSystem• NotifyElixirListenersSystem

Page 53: ECS architecture with Unity by example - Unite Europe 2016

public class NotifyTickListenersSystem : IReactiveSystem, ISetPool{ Group listeners;

public TriggerOnEvent trigger { get { return Matcher.Tick.OnEntityAddedOrRemoved(); } }

public void SetPool(Pool pool) { listeners = pool.GetGroup(Matcher.TickListener); }

public void Execute(List<Entity> entities) { var e = entities[0]; foreach (var entity in listeners.GetEntities()) { entity.tickListener.value.TickChanged(e.tick.currentTick); } }}

Page 54: ECS architecture with Unity by example - Unite Europe 2016

public interface ITickListener { void TickChanged(long currentTick);}

public interface IPauseListener { void PauseStateChanged(bool isPaused);}

public interface IElixirListener { void ElixirAmountChanged(float amount);}

Page 55: ECS architecture with Unity by example - Unite Europe 2016

Quiz!

Page 56: ECS architecture with Unity by example - Unite Europe 2016

Tick Listener?

Page 57: ECS architecture with Unity by example - Unite Europe 2016

Tick Listener!

Page 58: ECS architecture with Unity by example - Unite Europe 2016

Elixir Listener?

Page 59: ECS architecture with Unity by example - Unite Europe 2016

Elixir Listener!

Page 60: ECS architecture with Unity by example - Unite Europe 2016

Pause Listener?

Page 61: ECS architecture with Unity by example - Unite Europe 2016

Pause Listener!

Page 62: ECS architecture with Unity by example - Unite Europe 2016

public class ConsumeButtonBehaviour : MonoBehaviour, IPauseListener, IElixirListener{ void Awake() { Pools.pool.CreateEntity() .AddPauseListener(this) .AddElixirListener(this); }

public void PauseStateChanged (bool isPaused) { GetComponent<Button>().enabled = !isPaused; }

public void ElixirAmountChanged (float amount) { var ratio = 1 - Mathf.Min(1f, (amount / (float)consumptionAmount)); progressBox.fillAmount = ratio; GetComponent<Button>().enabled = (System.Math.Abs (ratio - 0) < Mathf.Epsilon); }}

Page 63: ECS architecture with Unity by example - Unite Europe 2016

Recap• Control your input, even if it is time• Input is a state change• Simulation is state change over time• State change drives UI updates• Persist only relevant parts of state for replay• Use Entitas to manage dependencies

Page 64: ECS architecture with Unity by example - Unite Europe 2016
Page 65: ECS architecture with Unity by example - Unite Europe 2016

Agenda:• Introduction to Entitas ✅

• User Input ✅

• Integration with Unity Collision System ✅

• Replayable games ✅

• Integration with Unity UI System ✅

• Quizz ✅

Page 66: ECS architecture with Unity by example - Unite Europe 2016

Bonus ThoughtHow hard is it to implement:• Multiplayer game• BackEnd validation• Tutorial and Quest systems• Any kind of Logging

Page 67: ECS architecture with Unity by example - Unite Europe 2016

Questions?#Entitas

@entitas_csharp

github.com/sschmid/Entitas-CSharp