von Mike Ton Vor 7 Jahren
1069
Mehr dazu
(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
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
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
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
_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
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
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 | +------------+
(Manual edits are wiped on each update)
(Useful for commenting out error when components are changed)
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
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
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
CollidesWithOthers(this Entity entity, Vector2 pos, IEnumerable
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
(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
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
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
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
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
.AddMaxAge(1f)
.AddAge(0)
.AddRotation(rotation)
.AddPosition(x, y)
.IsBullet(true)
(player)
CreatePlayer(this Pool pool, bool controllable){ ... }
.AddResource("Prefabs/Spaceship");
.AddForce(new List
// 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
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