IEnumerator ModifyMovementSpeed(EnemyMovementInfo info) { int targetId = info.entityID; EnemyEntityView entityView = null; // I dont feel like this is a good solution, but I'm not sure how else I can know when the entities have // finnished building. while (entityView == null) { yield return(null); entityViewsDB.TryQueryEntityView(targetId, out entityView); } entityView.movementComponent.moveSpeed += info.movementSpeed; }
public void Step(ref EnemyMovementInfo token, int condition) { ModifyMovementSpeed(token).Run(); }
IEnumerator IntervaledTick() { //OK this is of fundamental importance: Never create implementors as Monobehaviour just to hold //data. Data should always been retrieved through a service layer regardless the data source. //The benefit are numerous, including the fact that changing data source would require //only changing the service code. In this simple example I am not using a Service Layer //but you can see the point. //Also note that I am loading the data only once per application run, outside the //main loop. You can always exploit this trick when you now that the data you need //to use will never change var enemiestoSpawn = ReadEnemySpawningDataServiceRequest(); while (!levelFinnished) { //Svelto.Tasks allows to yield UnityYield instructions but this comes with a performance hit //so the fastest solution is always to use custom enumerators. To be honest the hit is minimal //but it's better to not abuse it. yield return(_waitForSecondsEnumerator); if (waveNumberOfEnemies == _numberOfEnemyKilled) { wave++; if (lastwave) { levelFinnished = true; } enemyWaveSequence.Next(this, ref wave); yield return(_wavewaitForSecondsEnumerator); foreach (var spawnData in enemiestoSpawn) { // The spawn time becomes normale spawntime + wavemodiefier times wave-1(wave-1 so the first wave is not //affected by the modiefier). float newSpawnTime = spawnData.spawnTime + (spawnData.waveSpawnModiefier * (wave - 1)); // make sure the spawntime is always higher then 0 if (newSpawnTime > 0) { spawnData.spawnTime = spawnData.timeLeft = newSpawnTime; } else { spawnData.spawnTime = spawnData.timeLeft = 1; } } } if (enemiestoSpawn != null) { for (int i = enemiestoSpawn.Length - 1; i >= 0 && _numberOfEnemyToSpawn > 0; --i) { var spawnData = enemiestoSpawn[i]; if (spawnData.timeLeft <= 0.0f) { // Find a random index between zero and one less than the number of spawn points. int spawnPointIndex = Random.Range(0, spawnData.spawnPoints.Length); // Create an instance of the enemy prefab at the randomly selected spawn point position and rotation. var go = _gameobjectFactory.Build(spawnData.enemyPrefab); //I have been lazy here and retrieving the data directly from the Monobehaviour //but still I am not creating an implementor for the purpose! var data = go.GetComponent <EnemyAttackDataHolder>(); //we are going to use a mix of implementors as Monobehaviours and //normal implementors here: List <IImplementor> implementors = new List <IImplementor>(); go.GetComponentsInChildren(implementors); implementors.Add(new EnemyAttackImplementor(data.timeBetweenAttacks, data.attackDamage)); //In this example every kind of enemy generates the same list of EntityViews //therefore I always use the same EntityDescriptor. However if the //different enemies had to create different EntityViews for different //engines, this would have been a good example where EntityDescriptorHolder //could have been used to exploit the the kind of polymorphism explained //in my articles. _entityFactory.BuildEntity <EnemyEntityDescriptor>( go.GetInstanceID(), implementors.ToArray()); var transform = go.transform; var spawnInfo = spawnData.spawnPoints[spawnPointIndex]; transform.position = spawnInfo.position; transform.rotation = spawnInfo.rotation; spawnData.timeLeft = spawnData.spawnTime; EnemyMovementInfo movementInfo = new EnemyMovementInfo(enemySpeedPercentageGain, go.GetInstanceID()); enemySpawnSequence.Next(this, ref movementInfo); _numberOfEnemyToSpawn--; } spawnData.timeLeft -= 1.0f; } } } }