Created
October 9, 2017 23:56
-
-
Save Protonz/2744e3d37170b012d5b9715e773b01f2 to your computer and use it in GitHub Desktop.
[Rx] Spawn prefabs at pre-defined spawn points. There can be a delay before spawning, then the prefabs can be spawned in batches with a delay between each batch.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UniRx; | |
using System; | |
/// <summary> | |
/// Spawn prefabs at pre-defined spawn points. | |
/// There can be a delay before spawning, then the prefabs can be spawned in batches with a delay between each batch. | |
/// </summary> | |
public class ListSpawnerRx : MonoBehaviour { | |
public GameObject[] PrefabList; | |
public Transform[] SpawnPoints; | |
public float SpawnDelay = 0f; | |
public float SpawnRepeatRate = 0.5f; | |
public int SpawnBatchSize = 3; | |
struct SpawnEvent { | |
public long EnemyId; | |
public GameObject Prefab; | |
public Transform SpawnPoint; | |
} | |
void Start () { | |
// A Timer that emits a value after the SpawnDelay, then repeats based on the SpawnRepeatRate | |
// |0---1---2---> | |
var spawnTimer = Observable.Timer(TimeSpan.FromSeconds(SpawnDelay), TimeSpan.FromSeconds(SpawnRepeatRate)); | |
// Make the spawn timer emit multiple values so that you can spawn multiple enemies per timer tick | |
// |012---345---678---> | |
var batchSpawnTimer = spawnTimer | |
.SelectMany(timerIndex => Observable.Range((int)timerIndex * SpawnBatchSize, SpawnBatchSize)); | |
// A stream of all the prefabs to be spawned | |
var prefabStream = PrefabList.ToObservable(); | |
// A stream of spawn points that loops so it has enough to handle all the prefabs | |
var spawnPointStream = SpawnPoints.ToObservable() | |
.Repeat() // Reuse spawn points if there are more Prefabs than Spawn Points | |
.Take(PrefabList.Length); // Repeat will infinitely loop and freeze without the Take to limit it | |
// Create a stream of SpawnEvents by zipping together 3 streams: batchSpawnTimer, prefabStream, spawnPointStream | |
IObservable<SpawnEvent> spawnEventStream = Observable.Zip( batchSpawnTimer, prefabStream, spawnPointStream, | |
( timerLoopIndex, prefab, spawnPoint ) => new SpawnEvent { | |
EnemyId = timerLoopIndex, | |
Prefab = prefab, | |
SpawnPoint = spawnPoint | |
}); | |
// Listen for any Spawn Events and Instantiate the Prefab | |
spawnEventStream | |
.Subscribe(e => { | |
Debug.Log("Spawning Enemy #" + e.EnemyId); | |
var newGO = Instantiate(e.Prefab); | |
newGO.transform.position = e.SpawnPoint.position; | |
}).AddTo(this); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment