void CompositionRoot() { _enginesRoot = new EnginesRoot(new UnityEntitiesSubmissionScheduler()); var entityFactory = _enginesRoot.GenerateEntityFactory(); var gameObjectFactory = new GameObjectFactory(); var playerSpawnerEngine = new PlayerSpawnerEngine(gameObjectFactory, entityFactory); _enginesRoot.AddEngine(playerSpawnerEngine); var playerInputEngine = new PlayerInputEngine(); _enginesRoot.AddEngine(playerInputEngine); var playerMovementEngine = new PlayerMovementEngine(); _enginesRoot.AddEngine(playerMovementEngine); }
void SetupEngines() { // "The core of Svelto.ECS" ??? m_EnginesRoot = new EnginesRoot(new UnitySumbmissionEntityViewScheduler()); // Factory for creating all entities (?) m_EntityFactory = m_EnginesRoot.GenerateEntityFactory(); // ??? IEntityFunctions entityFunctions = m_EnginesRoot.GenerateEntityFunctions(); // Factory used to create Unity GameObjects (wrapper around GameObject.Instantiate) GameObjectFactory gameObjectFactory = new GameObjectFactory(); IRayCaster rayCaster = new RayCaster(); ITime time = new FrameTimer(); PlayerInputEngine playerInputEngine = new PlayerInputEngine(); AimingEngine aimingEngine = new AimingEngine(); GunShootingEngine gunShootingEngine = new GunShootingEngine(rayCaster); GunEffectsEngine gunEffectsEngine = new GunEffectsEngine(gameObjectFactory); ZombieSpawnerEngine zombieSpawnerEngine = new ZombieSpawnerEngine(gameObjectFactory, m_EntityFactory); ZombieMovementEngine zombieMovementEngine = new ZombieMovementEngine(time); ZombieAnimationEngine zombieAnimationEngine = new ZombieAnimationEngine(); HUDEngine hudEngine = new HUDEngine(); DeathEngine deathEngine = new DeathEngine(entityFunctions); m_EnginesRoot.AddEngine(playerInputEngine); m_EnginesRoot.AddEngine(aimingEngine); m_EnginesRoot.AddEngine(gunShootingEngine); m_EnginesRoot.AddEngine(gunEffectsEngine); m_EnginesRoot.AddEngine(zombieSpawnerEngine); m_EnginesRoot.AddEngine(zombieMovementEngine); m_EnginesRoot.AddEngine(zombieAnimationEngine); m_EnginesRoot.AddEngine(hudEngine); m_EnginesRoot.AddEngine(deathEngine); }
/// <summary> /// Before to start, let's review some of the Svelto.ECS terms: /// - Entity: /// it must be a real and concrete entity that you can explain in terms of game design. The name of each /// entity should reflect a specific concept from the game design domain /// - Engines (Systems): /// Where all the logic lies. Engines operates on Entity Components /// - IEntityComponent: /// It's an Entity Component which can be used with Pure ECS /// - IEntityViewComponent: /// structs implementing this are used to wrap Objects that come from OOP libraries. You will never use it unless /// you are forced to mix your ECS code with OOP code because of external libraries or platforms. These special /// "Hybrid" component can hold only interfaces /// - Implementors: /// The EntityViewComponent exposed interfaces must be implemented by Implementors that are actually the /// Objects you need to wrap. /// - EntityDescriptors: /// Gives a way to formalise your Entity, it also defines the components that must /// be generated once the Entity is built /// </summary> void CompositionRoot(UnityContext contextHolder) { //the UnitySumbmissionEntityViewScheduler is the scheduler that is used by the EnginesRoot to know //when to submit the entities. Custom ones can be created for special cases. var unityEntitySubmissionScheduler = new UnityEntitiesSubmissionScheduler("survival"); //The Engines Root is the core of Svelto.ECS. You shouldn't inject the EngineRoot, //therefore the composition root class must hold a reference or it will be garbage collected. _enginesRoot = new EnginesRoot(unityEntitySubmissionScheduler); //The EntityFactory can be injected inside factories (or engine acting as factories) to build new entities //dynamically var entityFactory = _enginesRoot.GenerateEntityFactory(); //The entity functions is a set of utility operations on Entities, including removing an entity. I couldn't //find a better name so far. var entityFunctions = _enginesRoot.GenerateEntityFunctions(); var entityStreamConsumerFactory = _enginesRoot.GenerateConsumerFactory(); //wrap non testable unity static classes, so that can be mocked if needed (or implementation can change in general, without changing the interface). IRayCaster rayCaster = new RayCaster(); ITime time = new Time(); //GameObjectFactory allows to create GameObjects without using the Static method GameObject.Instantiate. //While it seems a complication it's important to keep the engines testable and not coupled with hard //dependencies var gameObjectFactory = new GameObjectFactory(); //Player related engines. ALL the dependencies must be solved at this point through constructor injection. var playerShootingEngine = new PlayerGunShootingEngine(rayCaster, time); var playerMovementEngine = new PlayerMovementEngine(rayCaster); var playerAnimationEngine = new PlayerAnimationEngine(); var playerDeathEngine = new PlayerDeathEngine(entityFunctions, entityStreamConsumerFactory); var playerInputEngine = new PlayerInputEngine(); var playerGunShootingFXsEngine = new PlayerGunShootingFXsEngine(entityStreamConsumerFactory); //Spawner engines are factories engines that can build entities var playerSpawnerEngine = new PlayerSpawnerEngine(gameObjectFactory, entityFactory); var restartGameOnPlayerDeath = new RestartGameOnPlayerDeathEngine(); //Player engines _enginesRoot.AddEngine(playerMovementEngine); _enginesRoot.AddEngine(playerAnimationEngine); _enginesRoot.AddEngine(playerShootingEngine); _enginesRoot.AddEngine(playerInputEngine); _enginesRoot.AddEngine(playerGunShootingFXsEngine); _enginesRoot.AddEngine(playerDeathEngine); _enginesRoot.AddEngine(playerSpawnerEngine); _enginesRoot.AddEngine(restartGameOnPlayerDeath); //Factory is one of the few OOP patterns that work very well with ECS. Its use is highly encouraged var enemyFactory = new EnemyFactory(gameObjectFactory, entityFactory); //Enemy related engines var enemyAnimationEngine = new EnemyChangeAnimationOnPlayerDeath(); var enemyDamageFX = new EnemySpawnEffectOnDamage(entityStreamConsumerFactory); var enemyAttackEngine = new EnemyAttackEngine(time); var enemyMovementEngine = new EnemyMovementEngine(); //Spawner engines are factories engines that can build entities var enemySpawnerEngine = new EnemySpawnerEngine(enemyFactory, entityFunctions); var enemyDeathEngine = new EnemyDeathEngine(entityFunctions, entityStreamConsumerFactory, time , new WaitForSubmissionEnumerator( unityEntitySubmissionScheduler)); //enemy engines _enginesRoot.AddEngine(enemySpawnerEngine); _enginesRoot.AddEngine(enemyAttackEngine); _enginesRoot.AddEngine(enemyMovementEngine); _enginesRoot.AddEngine(enemyAnimationEngine); _enginesRoot.AddEngine(enemyDeathEngine); _enginesRoot.AddEngine(enemyDamageFX); //abstract engines var applyDamageEngine = new ApplyDamageToDamageableEntitiesEngine(entityStreamConsumerFactory); var cameraFollowTargetEngine = new CameraFollowingTargetEngine(time); var deathEngine = new DispatchKilledEntitiesEngine(); //abstract engines (don't need to know the entity type) _enginesRoot.AddEngine(applyDamageEngine); _enginesRoot.AddEngine(deathEngine); _enginesRoot.AddEngine(cameraFollowTargetEngine); //hud and sound engines var hudEngine = new HUDEngine(entityStreamConsumerFactory); var damageSoundEngine = new DamageSoundEngine(entityStreamConsumerFactory); var scoreEngine = new UpdateScoreEngine(entityStreamConsumerFactory); //other engines _enginesRoot.AddEngine(damageSoundEngine); _enginesRoot.AddEngine(hudEngine); _enginesRoot.AddEngine(scoreEngine); var unsortedEngines = new SurvivalUnsortedEnginesGroup(new FasterList <IStepEngine>( new IStepEngine[] { playerMovementEngine, playerInputEngine, playerGunShootingFXsEngine, playerSpawnerEngine, playerAnimationEngine, enemySpawnerEngine, enemyMovementEngine, cameraFollowTargetEngine, hudEngine, restartGameOnPlayerDeath } )); var unsortedDamageEngines = new DamageUnsortedEngines(new FasterList <IStepEngine>( new IStepEngine[] { applyDamageEngine, damageSoundEngine, deathEngine } )); //Svelto ECS doesn't provide a tick system, hence it doesn't provide a solution to solve the order of execution //However it provides some option if you want to use them like the SortedEnginesGroup. _enginesRoot.AddEngine(new TickEnginesGroup(new FasterList <IStepEngine>(new IStepEngine[] { unsortedEngines , playerShootingEngine , enemyDamageFX , enemyAttackEngine , unsortedDamageEngines , playerDeathEngine , enemyDeathEngine , scoreEngine }))); BuildGUIEntitiesFromScene(contextHolder, entityFactory); }
void SetupEnginesAndEntities() { _enginesRoot = new EnginesRoot(new UnitySumbmissionEntityViewScheduler()); _entityFactory = _enginesRoot.GenerateEntityFactory(); _prefabsDictionary = new PrefabsDictionary(Application.persistentDataPath + "/prefabs.json"); var entityFunctions = _enginesRoot.GenerateEntityFunctions(); //GameObjectFactory factory = new GameObjectFactory(); _mapManager = GameObject.FindGameObjectWithTag("HexGrid").GetComponent <HexGrid>(); _uiService = _prefabsDictionary.Istantiate("UI Service").GetComponent <UIService>(); Sequencer battleTurnSequence = new Sequencer(); Sequencer abilityUsedSequence = new Sequencer(); ITime time = new Time(); MapGeneratorEngine mapGeneratorEngine = new MapGeneratorEngine(_mapManager, _entityFactory, _prefabsDictionary); UnitSpawnerEngine unitSpawnerEngine = new UnitSpawnerEngine(_prefabsDictionary, _entityFactory, _mapManager); PlayerInputEngine playerInputEngine = new PlayerInputEngine(_mapManager); BattleInitEngine battleInitEngine = new BattleInitEngine(entityFunctions, _prefabsDictionary, _entityFactory); TurnOrderEngine turnOrderEngine = new TurnOrderEngine(battleTurnSequence, _uiService); UnitTurnActionEngine unitTurnActionEngine = new UnitTurnActionEngine(battleTurnSequence); UnitMovementEngine unitMovementEngine = new UnitMovementEngine(_mapManager); UnitHighlightEngine unitHighlightEngine = new UnitHighlightEngine(_mapManager); BattleHudEngine battleHudEngine = new BattleHudEngine(_uiService); HealthEngine healthEngine = new HealthEngine(); AbilitySelectionEngine abilitySelectionEngine = new AbilitySelectionEngine(_uiService, abilityUsedSequence, _mapManager); AbilityTargetEngine abilityTargetEngine = new AbilityTargetEngine(); battleTurnSequence.SetSequence( new Steps { { turnOrderEngine, new To { unitTurnActionEngine, } }, { unitTurnActionEngine, new To { { TurnCondition.starting, new IStep[] { playerInputEngine, battleHudEngine } }, { TurnCondition.ending, new IStep[] { playerInputEngine, battleHudEngine, turnOrderEngine } } } }, } ); abilityUsedSequence.SetSequence( new Steps { { abilitySelectionEngine, new To { { new IStep[] { abilityTargetEngine } }, } } } ); AddEngine(mapGeneratorEngine); AddEngine(unitSpawnerEngine); AddEngine(playerInputEngine); AddEngine(battleInitEngine); AddEngine(turnOrderEngine); AddEngine(unitTurnActionEngine); AddEngine(unitMovementEngine); AddEngine(unitHighlightEngine); AddEngine(new CameraFollowTargetEngine(time)); AddEngine(battleHudEngine); AddEngine(healthEngine); AddEngine(abilitySelectionEngine); AddEngine(abilityTargetEngine); }