Kategoriak: All - unity - features - components - extensions

arabera Mike Ton 7 years ago

1069

Unity3D_Entitas

In a game development context, a detailed structure is presented focusing on various components and functionalities crucial for building a game using Unity. It includes a breakdown of essential elements like rendering resources, game board components, input handling, and destruction mechanisms.

Unity3D_Entitas

Entitas

Overview

App

(prefab resource string)

public static class Res { ... }

const

Piece2 = "Piece2";

Piece1 = "Piece1";

Piece0 = "red/Piece0";

Blocker = "Blocker";

// NameString must match path to Resources/folder

(generated components)

public static class PoolExtensions { ... }

CreateBlocker( this Pool pool, int x, int y) { ... }

.AddResource(Res.Blocker);

CreateRandomPiece( this Pool pool, int x, int y) { ... }

.AddResource(_pieces[Random.Range(0, _pieces.Length)]);

// instantiate game object

.IsInteractive(true)

.IsMovable(true)

.IsGameBoardElement(true)

??? why this Pool pool ???\

static readonly string[]

_pieces = { ... }

Res.Piece2,

Res.Piece1,

Res.Piece0,

// captures pool/spawn logic used by system specific to this game/app

Editor

DefaultInstanceCreator/

DefaultInstanceCreator.cs

Module
(Optional)

Entitas.CodeGenerator

ISystemCodeGenerator

(pool)

IPoolCodeGenerator

IComponentCodeGenerator

(flag)

(single)

[SingleEntity] public class AnimatingComponent : IComponent {}

// all from flag component plus methods for the pool var e = pool.animatingEntity; var isAnimating = pool.isAnimating; pool.isAnimating = true; pool.isAnimating = false;

// single flag component that is meant to exist only once in the pool (e.g. AnimatingComponent)

??? Flag that exist once in the pool ???

public class MovableComponent : IComponent {}

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

// flag component without any fields (e.g. MovableComponent)

(single/User)

[SingleEntity] public class UserComponent : IComponent { public string name; public int age; }

// all from standard component plus methods for the pool var e = pool.userEntity; var name = pool.user.name; var has = pool.hasUser; pool.SetUser("John", 42); pool.ReplaceUser("Max", 24); pool.RemoveUser();

// single standard component that is meant to exist only once in the pool

(standard)

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

(generated)

var pos = e.position; var has = e.hasPosition; e.AddPosition(x, y, z); e.ReplacePosition(x, y, z); e.RemovePosition();

// when to add vs. replace ???

// standard component with public fields (e.g. PositionComponent)

// Contains the optional but highly recommended code generator

(Unity)

Entitas.Unity.VisualDebugging

// Integrates Entitas into Unity. Inspect pools, entities, components and systems

Entitas.Unity.CodeGenerator

// Plugs into the Entitas preferences panel and adds convenient menu items

Entitas.Unity

// Contains the plugin based Entitas preferences panel for Unity

Matcher

struct

TriggerOnEvent { ... }

TriggerOnEvent(IMatcher trigger, GroupEventType eventType) { ... }

this.eventType = eventType;

this.trigger = trigger;

GroupEventType

eventType;

trigger;

AbstractMatcher.cs

AllOfMatcher.cs

(example)

public class ProcessInputSystem : IReactiveSystem, ISetPool { ... }

public void Execute(List entities) { ... }

_pool.DestroyEntity(inputEntity);

// _pool={Entitas.Pool}

// how does pool.DestroyEntity and DestroySystem work together ???

// A : pool.DestroyEnity is destroying the controller, e.isDestroy allows piece to be dispatched on the next available cycle

if (e != null && e.isInteractive) { ... }

e.isDestroy = true;

// true== add DestroyComponent/flag, so eligible for DestroySystem to remove from scene.

??? Why check if e.isinteractive ???

// A : To make sure that blockers are not destroyed

var e = _pool.gameBoardCache.grid[input.x, input.y];

// e.resource.name="red/Piece0"

// e.view.gameObject={Piece0(Clone)(UnityEngine.GameObject)}

// _pool.gameBoardCache.grid(6, 7)

// {Entity64(GameBoardElementComponent, InteractiveComponent, MoveableComponent, PositionComponent, ResourceComponent, ViewComponent)}

var input = inputEntity.input;

// {InputComponent}

//x=6, y=7

var inputEntity = entities.SingleEntity();

// {Entity75(InputComponent)}

??? Where is execute(List entities) called

Execute(entities=Count=1) { ... }

if (_buffer.Count != 0) { ... }

_subsystem.Execute(_buffer);

// _subsystem={ProcessingInputSystem}

DebugSystems.cs

double

monitorSystemExecutionDuration(IExecuteSystem system) { ... }

system.Execute();

Step() { ... };

var duration = monitorSystemExecutionDuration(system);

// system={Entitas.ReactiveSystem}

Execute() { ... };

if (!paused) { ... }

Step();

_systems.Execute;

// _systems={Entitas.Unity.VisualDebugging.DebugSystems}

get{ ... }

return Matcher.Input.OnEntityAdded();

// {Entitas.TriggerOnEvent}

//(Matcher)trigger{Input}

//(GroupEvent)evenType=OnEntityAdded;

??? How is this trigger set ???

(call stack)

(Entita)

Constructor(pool={Entitas.Pool}, subSystem={ProcessingInputSystem}, triggers={Entities.TriggerOnEvent[1]})

indices[0] = 4

ComponentIds Input = 4

Constructor(pool={Entitas.Pool}, subSystem={ProcessingInputSystem})

CreateSystem(pool=[Entitas.Pool], system={ProcessingInputSystem}) { ... }

CreateSystem(pool=[Entitas.Pool], systemType={ProcessingInputSystem}) { ... }

??? why systemType, followed by system ???

CreateSystem(pool={Entitas.Pool})

(app)

createSystems(pool={Entitas.Pool}) { ... }

// _systems=null

(type)

ReactiveSystem : IExecuteSystem { ... }

(observer)

Deactivate() { ... }

_observer.Deactivate();

Activate() { ... }

_observer.Activate();

(IExecuteSystem)

(constructor)

ReactiveSystem(Pool pool, IReactiveExecuteSystem subSystem, TriggerOnEvent[] triggers) { ... }

_buffer = new List();

_observer = new GroupObserver(groups, eventTypes);

// {Entitas.GroupObserver}

// groups=matcher{Input}, eventType=OnEntityAdded

for (int i = 0; i < triggersLength; i++) { ... }

eventTypes[i] = trigger.eventType;

groups[i] = pool.GetGroup(trigger.trigger);

// [0]={Group(Input)}

// matcher={Input}

// Count=0

var trigger = triggers[i];

// {Entitas.TriggerOnEvent[1]}

// [0]={Entitas.TriggerOnEvent}

// trigger={Input}

// eventType=OnEntityAdded

var eventTypes = new GroupEventType[triggersLength];

// {Entitas.GroupEventType[1]}

// [0]=OnEntityAdded

var groups = new Group[triggersLength];

// {Entitas.Group[1]}

//matcher={Input}

//Count=0

var triggersLength = triggers.Length;

// 1

(excludeComponents)

(ensureComponents)

_subsystem = subSystem;

ReactiveSystem(Pool pool, IMultiReactiveSystem subSystem) :

this(pool, subSystem, subSystem.triggers) { ...... }

??? MultiReact vs. IReact

ReactiveSystem(Pool pool, IReactiveSystem subSystem) :

this(pool, subSystem, new [] { subSystem.trigger }) { ...... }

(others)

_subsystem;

subsystem { get{ ... } }

return _subsystem;

interface


namespace Entitas{
    public interface ISystem {
    }
}


IReactiveExecuteSystem

using Entitas;

using UnityEngine;

public class RenderPositionSystem : IReactiveSystem {

public TriggerOnEvent trigger { get { return Matcher.AllOf(Matcher.Position, Matcher.View).OnEntityAdded(); } }

public void Execute(List<Entity> entities) {

// Gets executed only if the observed group changed.

// Changed entities are passed as an argument

foreach (var e in entities) {

var pos = e.position;

e.view.gameObject.transform.position = new Vector3(pos.x, pos.y, pos.z);

}

}

}

Executes when the observed group changes (system.Execute(Entity[]))

// Entitas also provides a special system called ReactiveSystem, which is using an Group Observer under the hood. It holds changed entities of interest at your fingertips. Be sure to check out the example projects.

IReactiveSystem : IReactiveExecuteSystem { ... }

TriggerOnEvent trigger { get; }

IReactiveExecuteSystem : ISystem { ... }

void Execute(List entities);

using Entitas;

public class MoveSystem : IExecuteSystem, ISetPool {

Group _group;

public void SetPool(Pool pool) {

_group = pool.GetGroup(Matcher.AllOf(Matcher.Move, Matcher.Position));

}

public void Execute() {

foreach (var e in _group.GetEntities()) {

var move = e.move;

var pos = e.position;

e.ReplacePosition(pos.x, pos.y + move.speed, pos.z);

}

}

}

IExecuteSystem : System { ... }

void Execute();

// Executes every frame (system.Execute())

IStartSystem

Executes once (system.Start())

public static class PoolExtension { ... }

setPool(ISystem system, Pool pool) { ... }

if (poolSystem != null) { ... }

poolSystem.SetPool(pool);

var poolSystem = system as ISetPool;

ISystem

CreatSystem(args...)

(signatures)

CreateSystem(this Pool pool, ISystem system) { ... }

return system;

if (multiReactiveSystem != null) { ... }

return new ReactiveSystem(pool, multiReactiveSystem);

var multiReactiveSystem = system as IMultiReactiveSystem;

if (reactiveSystem != null) { ... }

return new ReactiveSystem(pool, reactiveSystem);

var reactiveSystem = system as IReactiveSystem;

setPool(system, pool);

CreateSystem(this Pool pool, Type systemType) { ... }

return pool.CreateSystem(system);

var system = (ISystem)Activator.CreateInstance(systemType);

Entity[]

GetEntities(this Pool pool, IMatcher matcher) { ... }

return pool.GetGroup(matcher).GetEntities();

public interface ISetPool { ... }

void SetPool(Pool pool);

//Create systems for each single task or behaviour in your application and execute them in a defined order

(reactive to pool change)

public class RenderPositionSystem : IReactiveSystem { ... }

e.view.gameObject.transform.DOMove(new Vector3(pos.x, pos.y, 0f), 0.3f);

return Matcher.AllOf(Matcher.Position, Matcher.View).OnEntityAdded();

(execute from set pool)

public class MoveSystem : IExecuteSystem, ISetPool { ... }

_group;

//This helps to keep your app deterministic.

The Pool is the factory where you create and destroy entities. Use it to filter entities of interest.

// Pools.pool is kindly generated for you by the code generator

var pool = Pools.pool;

var entity = pool.CreateEntity();

entity.isMovable = true;

// Returns all entities having MovableComponent and PositionComponent.

// Matchers are also generated for you.

var entities = pool.GetEntities(Matcher.AllOf(Matcher.Movable, Matcher.Position));

foreach (var e in entities) {

// do something

}

Groups enable super quick filtering on entities in the pool. They are continuously updated when entities change and can return groups of entities instantly. Imagine you have thousands of entities and you only want those who have a PositionComponent - just ask the pool for this group, it already has the result waiting for you in no time.

pool.GetGroup(Matcher.Position).GetEntities();

Both the group and getting the entities is cached, so even calling this method multiple times is super fast. Always try to use goups when possible. pool.GetEntities(Matcher.Movable) internally uses groups, too.

Groups have events for OnEntityAdded, OnEntityRemoved and OnEntityUpdated to directly react to changes in the group.

pool.GetGroup(Matcher.Position).OnEntityAdded += (group, entity, index, component) => {

// Do something

};

If you want to aggregate and process changes, consider using a Group Observer.

Group Observer

The Group Observer provides an easy way to react to changes in a group over time. Let's say you want to collect and process all the entities where a PositionComponent was added or replaced.

var group = pool.GetGroup(Matcher.Position);

var observer = group.CreateObserver(GroupEventType.OnEntityAdded);

foreach (var e in observer.collectedEntities) {

// do something

}

observer.ClearCollectedEntities();

To stop observing, simply deactivate the observer.

observer.Deactivate();

GroupUpdated(Group group, Entity entity, int index, IComponent previousComponent, IComponent newComponent);

GroupChanged(Group group, Entity entity, int index, IComponent component);

GroupChanged

// need example

/// Occurs when a component of an entity in the group gets replaced.

/// Occurs when an entity gets removed.

/// Occurs when an entity gets added.

(Collect and process all the entities where a PositionComponent was added or replaced)

// To stop observing

observer.Deactivate();

observer.ClearCollectedEntities();

// why do I need to do this

??? release memory ???

foreach (var e in observer.collectedEntities) { ... }

// do something

var observer = group.CreateObserver(GroupEventType.OnEntityAdded);

var group = pool.GetGroup(Matcher.Position);

//The Group Observer provides an easy way to react to changes in a group over time

//Subsets of entities in the pool blazing fast querying

(react to changes in the group)

OnEntityUpdated

OnEntityRemoved

OnEntityAdded

pool.GetGroup(Matcher.Position).OnEntityAdded += (group, entity, index, component) => { // Do something };

//They are continuously updated when entities change and can return groups of entities instantly

Entity

An entity is a container holding data to represent certain objects in your application. You can add, replace or remove data from entities in form of IComponent. Entities have corresponding events to let you know if components were added, replaced or removed.

Here's how you can interact with an entity. To enjoy a more natural and more readable API, simply use the code generator that comes with Entitas. In this example you can see some generated methods for PositionComponent, HealthComponent, MovableComponent.

entity.AddPosition(3, 7);

entity.AddHealth(100);

entity.isMovable = true;

entity.ReplacePosition(10, 100);

entity.ReplaceHealth(entity.health.value - 1);

entity.isMovable = false;

entity.RemovePosition();

var hasPos = entity.hasPosition;

var movable = entity.isMovable;

(composition)

Component (id)

string NameOfObject

int GUID

Component (transtform)

Quaternion rot

Data

Vector3 pos

//Entities have corresponding events to let you know if components were added, replaced or removed

//The Pool is the factory where you create and destroy entities. Use it to filter entities of interest.

(diagram)

(pic)

(text)

+------------------+ | 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 | +------------------+ +-----------+ +-----------+ | | | +-------------+ Groups: | | e | Subsets of entities in the pool | | e e | for blazing fast querying +---> | +------------+ | e | | | | e | e | e | +--------|----+ e | | e | | e e | +------------+

// Contains the complete ECS, basically everything you need to get started

Usage

...bunch of other files...don't care

(Manual edits are wiped on each update)

(Useful for commenting out error when components are changed)

Unity
2dPlatformer

Libraries

// from asset store and github

CreateOnTriggerEnter()

CreateOnCollision()

spawnPlayer()

(physics)

Update

ViewTransform

ViewResource

Events

UI

State

OnCollision

IO

Audio

FX

Level

_Project

Utility

__gUtility.cs

__gEXTENSIONS.cs

(data)

Interfaces

enums

structs

_Engine

Dotween

Settings

_CONSTANTComponent.cs

_GravityComponent.cs

_IO_HubComponent.cs

_ResourcePaths.cs

Controller

(gameobject)

goPositionUpdateController

goOnTriggerController

goOnCollisionController

goCharUpdateController

goAnimatorUpdateController

(other)

LevelPrefabController

UI_UpdateController

_InputUpdateController

_MainGameController

Examples

Editing

renaming

comment out to get rid of errors

// use break points to mark lines changed

deleting

fields

Entitas Regenerate

Delete Generated file

Sources/

(misc)

Generated/

// Project must be in a buildable state for generated objects to update

Editor/

Features/

Physics/

RenderForceSystem.cs

RenderForceSystem : IReactiveSystem, IEnsureComponents { ... }

Destroy/

Events/

State/

stateVMotionComponent.cs

// essentially capture of previous/last state on an entity

eventVMotionComponent.cs

// must have ID for system to map

Update/

RenderResource/

RenderPosition/

(Updates Unity View)

RenderPositionSystem :

Execute (List entities){ ... }

e.view.gameObject.transform.position = new Vector3(pos.x, pos.y, pos.z);

return Matcher.AllOf(Matcher.View, Matcher.Position).OnEntityAdded();

IEnsureComponents

IMatcher ensureComponents { get { ... } }

return Matcher.View;

// What is ensureComponents ???

// When communicating with Unity Objects ???

(Updates from inMotion to Position)

MoveSystem :

_group = pool.GetGroup(Matcher.AllOf(Matcher.Move, Matcher.Position));

Group _group;

IExecuteSystem

e.ReplacePosition(pos.x, pos.y + move.speed, pos.z);

var pos = e.position;

(accelerationInput from standstill to inMotion)

AccelerateSystem :

ISetPool

_group = pool.GetGroup(Matcher.AllOf(Matcher.Acceleratable, Matcher.Move));

Group _group

NOTE : ISetPool interface not enough to generate system, must have IReactiveSystem or IExecuteSystem

IReactiveSystem

foreach (var e in _group.GetEntities()) { ... }

e.ReplaceMove(speed, move.maxSpeed);

var speed = accelerate ? move.maxSpeed : 0;

var move = e.move;

var accelerate = entities.SingleEntity().isAccelerating;

TriggerOnEvent trigger { get { ... } }

return Matcher.Accelerating.OnEntityAddedOrRemoved();

// interesting add or remove

Components/

// pure components => no systems

IO/

// on touch event => funcs

// pieces are destroyed by touch, input also destroyed on complete

// affected by touch ?

// blockers don't respond to touch; pieces do

// touch position

GameBoard/

GameBoardLogic.cs

// used by other system and features : FillSystem and FallSystem

EntityExtensions.cs

// functions to handle collisions (OnSpawn)

FindEmptyPosition(this Entity entity, float radius, Bounds bounds, IEnumerable entities) { ... }

CollidesWithOthers(this Entity entity, Vector2 pos, IEnumerable entities) { ... }

foreach (var e in entities) { ... }

if (delta.sqrMagnitude < minDistSqr)

return true;

var minDistSqr = minDist*minDist;

var minDist = entity.collisionRadius.radius + e.collisionRadius.radius;

var delta = new Vector2(pos.x - e.position.x, pos.y - e.position.y);

if (e == entity)

if (!e.hasCollisionRadius || !e.hasPosition)

continue;

// Whereas "break" exits the loop entirely

// The "continue" keyword makes the program skip around to the next iteration of the 'for' loop

// functions to instantiate, add components and set propertyvalues to gameobjects

CreateCollision(this Pool pool, Collision2D collision) { ... }

.IsDestroying(true);

// Marks object for DestroySystem

.AddCollision(collision)

(resourcesPath)

Res.cs

Resources/

Prefabs/

Fx/

Particles/

UI/

Audio/

Environments/

Characters/

Weapon/

(prefab)

CollisionsController : MonoBehaviour { ... }

void OnCollisionEnter2D(Collision2D coll) { ... }

Pools.pool.CreateCollision(coll);

GunController : MonoBehaviour { ... }

void OnDestroy() { ... }

Pools.pool.DestroyEntity(_gun);

void Start() { ... }

_gun = Pools.pool.CreateGun(gameObject);

private Entity _gun;

Scripts/

(prefabs)

CollisionsController.cs

GunController.cs

(events)

UIController.cs

HudController.cs

OnScoreChanged(Group @group, Entity entity, int index, Component component) { ... }

scoreTxt.text = "" + entity.score.score;

??? @group

// @ symbol allows you to use reserved word

// doesn't

int class = 15;

// works

int @class = 15;

Start () { ... }

scores.OnEntityAdded += OnScoreChanged;

//

public event GroupChanged OnEntityAdded;

public delegate void GroupChanged(Group group, Entity entity, int index, IComponent component);

var scores = Pools.pool.GetGroup(Matcher.Score);

(input)

(init)

// sets up systems

Example

MatchOne

(GeneratedComponents)

(pools)

Pools.cs

pool { ... }

return _pool;

if (_pool == null) { ... }

#if (UNITY_EDITOR)

UnityEngine.Object.DontDestroyOnLoad(poolObserver.entitiesContainer);

var poolObserver = new Entitas.Unity.VisualDebugging.PoolObserver(_pool, "Pool");

// "Pool" is the parent transform for observer objects created while running in the editor

_pool = new Pool(ComponentIds.TotalComponents);

public static class Pools { ... }

(Componentids)

Score

ScoreSystem.cs

ScoreComponent.cs

RenderResource

ViewComponent.cs

RemoveViewSystem.cs

ResourceComponent.cs

AddViewSystem.cs

RenderPosition

RenderPositionSystem.cs

Input

ProcessInputSystem.cs

InteractiveComponent.cs

InputComponent.cs

GameBoard

GameBoardSystem.cs

GameBoardElementComponent.cs

GameBoardComponent.cs

GameBoardCacheComponent.cs

CreateGameBoardCacheSystem.cs

Fill

FillSystem.cs

Fall

FallSystem.cs

Destroy

DestroySystem.cs

DestroyComponent.cs

Components

PositionComponent.cs

MovableComponent.cs

PoolExtensions.cs

Unity/Assets

ScoreLabelController.cs

updateScore(int score) { ... }

Text

_label;

Update(){ ... }

burstMode;

createSystems(Pool pool) { ... }

return new Systems()

// Destroy

// Render

// Update

// Input

Start() { ... }

_systems = createSystems(Pools.pool);

Random.seed = 42;

_systems;

(scriptable)

DoTweenSettings

(sprites)

pieces0-5

blockers

Entitasteroids
Unity3D

Assets

Generated

InputComponentGeneratedExtension.cs

(filter)

Input { ... }

return _matcherInput;

if (_matcherInput == null) { ... }

_matcherInput = Matcher.AllOf(ComponentIds.Input);

_matcherInput;

(methods)

public Entity RemoveInput() { ... }

ReplaceInput(bool newAccelerate, bool newTurnLeft, bool newTurnRight, bool newFire) { ... }

AddInput(bool newAccelerate, bool newTurnLeft, bool newTurnRight, bool newFire) { ... }

ClearInputComponentPool() { ... }

_inputComponentPool.Clear();

// clears this

Stack

_inputComponentPool

new Stack();

hasInput { ... }

return HasComponent(ComponentIds.Input)

// Entity.cs checks if component exist using ComponentIds.Input lookup

Assets.Entitasteroids.Sources.Features.Input.InputComponent

input { ... }

return (Assets.Entitasteroids.Sources.Features.Input.InputComponent)GetComponent(ComponentIds.Input);

// gets an int and then casts it as InputComponent...is that also an int?

// Entity.cs get component using ComponentIds.Input lookup

public Assets.Entitasteroids.Sources.Features.Input.InputComponent input { get { return (Assets.Entitasteroids.Sources.Features.Input.InputComponent)GetComponent(ComponentIds.Input); } }

// WTH???

MTON.MtonBSGeneratedExtension.cs

namespace Entities { ... }

Matcher { ... }

MtonBS { ... }

return _matcherMtonBS;

if (_matcherMtonBS == null) { ... }

_matcherMtonBS = Matcher.AllOf(ComponentIds.MtonBS);

IMatcher

_matcherMtonBS;

isMtonBS { ... }

set { ... }

else { ... }

RemoveComponent(ComponentIds.MtonBS);

if (value != isMtonBS) { ... }

AddComponent(ComponentIds.MtonBS, mtonBSComponent);

// What ? setters can check value against current without caching manually???

get { ... }

return HasComponent(ComponentIds.MtonBS);

MTON.MtonBS

mtonBSComponent

= new MTON.MtonBS();

ComponentIds.cs

Scripts

Sources

Features

Gun

GunCooldownSystem.cs

GunFiringSystem.cs

(local)

private void Fire() { ... }

foreach (var entity in _guns.GetEntities()) { ... }

entity.ReplaceGun(entity.gun.minimumShotInterval, 0);

entity.isFireable = false;

_pool.CreateBullet(pos.x, pos.y, rot);

var rot = entity.view.gameObject.transform.rotation.eulerAngles.z;

var pos = entity.view.gameObject.transform.position;

(interface)

(ISetPool)

void SetPool(Pool pool) { ... }

_guns = pool.GetGroup(Matcher.AllOf(Matcher.Gun, Matcher.Controllable, Matcher.View, Matcher.Fireable));

(IReactiveSystem)

void Execute(List entities) { ... }

foreach (var entity in entities) { ... }

if (entity.input.fire) { ... }

Fire();

// ??? How is this sorting for input ???

TriggerOnEvent trigger { ... }

_guns;

FireableComponent.cs

GunComponent.cs

(system)

SpaceshipRespawningSystem.cs

public class SpaceshipRespawningSystem : IExecuteSystem, ISetPool { ... }

OnDeaththroesRemoved(Group group, Entity entity, int index, Component component){ ... }

_pool.CreateEntity()

.IsWaitingForSpace(true);

.AddCollisionRadius(5)

if (_lives.GetSingleEntity().lives.lives == 0) { ... }

Respawn(Entity entity) { ... }

_pool.CreatePlayer(true);

HasSpace(Vector2 pos, Entity entity) { ... }

return entity.CollidesWithOthers(pos, _asteroids.GetEntities());

SetPool(Pool pool){ ... }

_lives = _pool.GetGroup(Matcher.Lives);

_games = _pool.GetGroup(Matcher.AllOf(Matcher.Game, Matcher.Bounds));

_asteroids = pool.GetGroup(Matcher.AllOf(Matcher.Asteroid, Matcher.CollisionRadius));

_waiting = _pool.GetGroup(Matcher.AllOf(Matcher.WaitingForSpace, Matcher.Spaceship));

_pool.GetGroup(Matcher.SpaceshipDeathroes).OnEntityRemoved += OnDeaththroesRemoved;

// overrides ISetPool

Execute() { ... }

foreach (var entity in _waiting.GetEntities()) { ... }

if (HasSpace(pos, entity)) { ... }

Respawn(entity);

var pos = bounds.RandomPosition();

var bounds = game.bounds.bounds;

if (game == null) { ... }

return;

var game = _games.GetSingleEntity();

_waiting;

_asteroids;

_games;

SpaceshipCollisionSystem.cs

public class SpaceshipCollisionSystem : IReactiveSystem, ISetPool { ... }

DecrementLives(){ ... }

lives.ReplaceLives(lives.lives.lives - 1);

var lives = _lives.GetSingleEntity();

Collide(Entity ship) { ... }

DecrementLives();

_pool.CreateSpaceshipExplosionEffect(ship.position.x, ship.position.y).isSpaceshipDeathroes = true;

ship.isDestroying = true;

_lives = pool.GetGroup(Matcher.Lives);

_pool = pool;

if (ship != null) { ... }

Collide(ship);

var ship = _spaceships.GetEntities().FirstOrDefault(e => e.view.gameObject == obj);

var obj = entity.collision.collision.gameObject;

_pool;

_lives;

InputDestructionSystem.cs

(subscribes to input group, and removes frame after add?)

public class InputDestructionSystem : IReactiveSystem { ... }

trigger{ ... }

entity.isDestroying = true;

// removes input system per frame or when triggered?

SpaceshipControlsSystem.cs

(Spaceship subscribes to input events)

public class SpaceshipControlsSystem : IReactiveSystem, ISetPool { ... }

Rotate(int direction) { ... }

var torque = entity.force.torque + entity.spaceship.rotationRate*direction;

Accelerate() { ... }

foreach (var entity in _spaceships.GetEntities()) { ... }

entity.ReplaceForce(relativeForces, torque);

var torque = entity.force.torque;

relativeForces.Add(new Vector2(0, entity.spaceship.accelerationRate));

var relativeForces = entity.force.relativeForces;

TriggerOnEvent

trigger { ... }

get { return Matcher.Input.OnEntityAdded(); }

// ???

// overload from IReactiveSystem

SetPool(Pool pool) { ... }

_spaceships = pool.GetGroup(Matcher.AllOf(Matcher.Spaceship, Matcher.Controllable, Matcher.Force));

// ???

// overload from ISetPool

Execute(List entities) { ... }

foreach (var entity in entities){ ... }

(entity.input)

if (entity.input.turnRight) { ... }

Rotate(-1);

if (entity.input.turnLeft) { ... }

Rotate(1);

if (entity.input.accelerate) { ... }

Accelerate();

Group

_spaceships;

(component)

SpaceshipDeathroesComponent.cs

public class SpaceshipDeathroesComponent : IComponent { ... }

WaitingForSpaceComponent.cs

public class WaitingForSpaceComponent : IComponent { ... }

// empty

SpaceshipComponent.cs

public class SpaceshipComponent : IComponent { ... }

public float rotationRate;

public float accelerationRate;

Player

Player.cs

public class Player : IComponent { //empty }

Extensions

PoolExtensions

(fx)

(explosion)

(debris)

(go)

(camera)

(gun)

(bullet)

CreateBullet(this Pool pool, float x, float y, float rotation) { ... }

.AddResource("Prefabs/Bullet");

.AddForce(new List { new Vector2(0, 10) }, 0)

.AddMaxAge(1f)

.AddAge(0)

.AddRotation(rotation)

.AddPosition(x, y)

.IsBullet(true)

(player)

CreatePlayer(this Pool pool, bool controllable){ ... }

.AddResource("Prefabs/Spaceship");

.AddForce(new List(), 0)

// why List??

.IsWrappedAroundGameBounds(true)

.IsControllable(controllable)

.AddCollisionRadius(1)

.AddSpaceship(0.5f, 0.02f)

// injects acceleration and rotation

.AddPosition(0, 0)

.IsPlayer(true)

(game)

(collision)

(tick)

(state)

CreateGame(this Pool pool, bool playing, int level, Bounds bounds) { ... }

return pool.CreateEntity()

.IsPlaying(playing);

.AddScore(0)

.AddLives(3)

.AddLevel(level)

.AddBounds(bounds)

.IsGame(true)

// injects entity settings ?

EntityExtensions

BoundsExtensions.cs

Resources

Prefabs

(Asteroids)

Asteroid Small

Asteroid Medium

Asteroid Large

Bullet

Spaceship

(root)

System.cs

ReactiveSystem.cs

GroupObserver.cs

Group.cs

Pool.cs

Entity.cs

namespace Entitas { ... }

EntityEqualityComparer : IEqualityComparer { ... }

(Exception)

EntityIsAlreadyReleasedException : Exception { ... }

EntityIsNotEnabledException : Exception { ... }

EntityDoesNotHaveComponentException : Exception { ... }

EntityAlreadyHasComponentException : Exception { ... }

partial

class

// WTH is there a 2nd one lower ???

Entity { ... }

HasComponent(int index) { ... }

return _components[index] != null;

IComponent

GetComponent(int index) { ... }

Entity

...

AddComponent(int index, IComponent component) { ... }

Entity(int totalComponents) { .. }

_components = new IComponent[totalComponents];

// why can this use the class name

??? Constructor

string

_toStringCache;

int[]

_componentIndicesCache;

_componentsCache;

readonly

IComponent[]

_components;

// what is this...an array of interfaces....how does it resolve the index passed to it????

internal

bool

_isEnabled = true;

_creationIndex;

private is for class scope (i.e. accessible only from code in the same class).

internal is for assembly scope (i.e. only accessible from code in the same .exe or .dll)

int

creationIndex { get { return _creationIndex; } }

delegate

ComponentReplaced(Entity entity, int index, IComponent previousComponent, IComponent newComponent);

EntityChanged(Entity entity, int index, IComponent component);

event

ComponentReplaced

OnComponentReplaced;

EntityChanged

OnComponentRemoved;

OnComponentAdded;

Matcher/

TriggerOnEvent.cs

// how do structs and interface communicate ???

Interfaces/

IReactiveSystem.cs

Extensions/

PoolExtension.cs

Main.unity

(scene)

(ui)

EventSystem

Canvas

MainCamera

(runtime)

Views

(Monobehaviours?)

(e)

Pool

Groups

30

Reusable

13

Entitiies

7

(Type)

Total

22

???

Execute

21

Initialize

0

InputController.cs

GameController.cs

(func)

Bounds

GetBounds(){ ... }

return new Bounds(Vector3.zero, new Vector3(size.x * 2, size.y * 2));

var size = Camera.main.ScreenToWorldPoint(new Vector2(Screen.width, Screen.height));

CreateSystems(Pool pool) { .. }

.Add(pool.CreateSystem());

Add(pool.CreateSystem())

.Add(pool.CreateSystem())

// PoolExtension.cs

public

static

System

CreateSystem(this Pool pool) where T: ISystem, new() { ... }

return pool.CreateSystem(typeof(T));

// Systems are bathed at Assets.Entitasteroids.Sources.Features.

void

CreateGame() { ... }

Pools.pool.CreateGame(true, 0, bounds);

??? static function ???

// PoolExtensions.cs

var bounds = GetBounds();

Update() { ... }

_systems.Execute();

Awake() {...}

CreateGame();

_systems.Initialize();

// Entitias.Systems.cs

_systems = CreateSystems(Pools.pool);

(var)

private

Systems

_systems