IEnumerator SpawnWave(Wave wave, float delay) { yield return new WaitForSeconds(delay); Debug.Log(gameObject.name+" - start spawning wave "+currentWaveIDX); if(currentWaveIDX>0) spawnHP+=hitPointIncrement; if(wave.subWaveList.Count==0) Debug.LogWarning("Trying to spawn an empty wave", thisT); wave.subWaveSpawned=0; //start coroutine for each subwave for(int i=0; i<wave.subWaveList.Count; i++) StartCoroutine(SpawnSubWave(wave, i)); //wait until all of the wubwave finish spawning while(wave.subWaveSpawned<wave.subWaveList.Count) yield return null; wave.spawned=true; Debug.Log(gameObject.name+" - wave "+currentWaveIDX+" spawned complete"); }
//function call to spawn a subwave IEnumerator SpawnSubWave(Wave wave, int subWaveIdx) { SubWave subWave=wave.subWaveList[subWaveIdx]; TDSArea sArea=subWave.spawnArea!=null ? subWave.spawnArea : spawnAreaList[0]; //use the default spawn area if nothing has been assigned for the subwave //wait for start delay yield return new WaitForSeconds(subWave.startDelay); if(subWave.unitPrefab!=null){ for(int i=0; i<subWave.count; i++){ //wait for the spawn cooldown if(i>0) yield return new WaitForSeconds(subWave.interval); Quaternion rot=!randomRotation ? sArea.GetRotation() : Quaternion.Euler(0, Random.Range(0, 360), 0); UnitAI unitInstance=SpawnUnit(subWave.unitPrefab.gameObject, sArea.GetPosition(), rot, subWave.unitPrefab.gameObject.name+"_"+spawnCount); unitInstance.SetWaveID(this, wave.waveID); //assign the unit with the waveID so they know they belong to a wave (unit with valid waveID will call UnitCleared() callback) wave.activeUnitCount+=1; } } //increase the subWaveSpawned counter wave.subWaveSpawned+=1; yield return null; }
//called to generate a spawn wave using the procedural generation parameter Wave GenerateWave(int waveIDX) { Wave wave=new Wave(); wave.waveID=waveIDX; wave.spawnArea=spawnAreaList[Random.Range(0, spawnAreaList.Count)]; wave.creditGain=startingCredit+creditIncrement*waveIDX; wave.scoreGain=startingScore+scoreIncrement*waveIDX; int subWaveCount=Random.Range(1, waveIDX); subWaveCount=Mathf.Clamp(subWaveCount, 1, maxSubWaveCount); subWaveCount=Mathf.Clamp(subWaveCount, 1, spawnUnitList.Count); List<int> countList=new List<int>(); for(int i=0; i<subWaveCount; i++) countList.Add(1); int totalUnitCount=unitCount+unitCountInc*waveIDX-subWaveCount; if(subWaveCount<=0) totalUnitCount=0; int count=0; while(totalUnitCount>0){ int rand=Random.Range(1, totalUnitCount); countList[count]+=rand; totalUnitCount-=rand; if((count+=1)>=subWaveCount) count=0; } List<Unit> unitList=new List<Unit>( spawnUnitList ); wave.subWaveList=new List<SubWave>(); for(int i=0; i<subWaveCount; i++){ SubWave subWave=new SubWave(); subWave.count=countList[i]; int rand=Random.Range(0, unitList.Count); subWave.unitPrefab=unitList[rand]; unitList.RemoveAt(rand); subWave.startDelay=0.5f; subWave.interval=Random.Range(1f, 2f); wave.subWaveList.Add(subWave); } return wave; }
//spawn a generated wave, for endless mode only void SpawnGeneratedWave(float delay=0) { waveE=GenerateWave(currentWaveIDX+=1); StartCoroutine(SpawnWave(waveE, delay)); }
Vector2 DrawSpawnerConfigurator(float startX, float startY, UnitSpawner spawner) { int mode = (int)spawner.spawnMode; cont = new GUIContent("Spawn Mode:", "The spawn mode to use"); EditorGUI.LabelField(new Rect(startX, startY, width, height), cont, headerStyle); contL = new GUIContent[spawnModeLabel.Length]; for (int i = 0; i < contL.Length; i++) { contL[i] = new GUIContent(spawnModeLabel[i], spawnModeTooltip[i]); } mode = EditorGUI.Popup(new Rect(startX + spaceX, startY, width, 15), new GUIContent(""), mode, contL); spawner.spawnMode = (_SpawnMode)mode; if (spawner.spawnMode == _SpawnMode.WaveBased) { cont = new GUIContent("- Endless", "Enable to activate endless mode (wave will be generated procedurally)"); EditorGUI.LabelField(new Rect(startX + spaceX + width + 25, startY, width, height), cont, headerStyle); spawner.endlessWave = EditorGUI.Toggle(new Rect(startX + spaceX + width + 10, startY, 40, height), spawner.endlessWave); } startY += 10; cont = new GUIContent("Spawn Upon Start:", "Check to have the spawner start spawning automatically as soon as the game start"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); spawner.spawnUponStart = EditorGUI.Toggle(new Rect(startX + spaceX, startY, width, height), spawner.spawnUponStart); cont = new GUIContent("Start Delay:", "Delay (in second) before the spawning start"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); //if(spawner.spawnUponStart) spawner.startDelay = EditorGUI.FloatField(new Rect(startX + spaceX, startY, 40, height), spawner.startDelay); //else // EditorGUI.LabelField(new Rect(startX+spaceX, startY, 40, height), "-"); startY += 10; cont = new GUIContent("Random Rotation:", "Check to have the unit spawned facing random rotation, otherwise the rotation of the spawn area will be used"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); spawner.randomRotation = EditorGUI.Toggle(new Rect(startX + spaceX, startY, width, height), spawner.randomRotation); startY += 10; for (int i = 0; i < spawner.spawnAreaList.Count - 1; i++) { if (spawner.spawnAreaList[i] == null) { spawner.spawnAreaList.RemoveAt(i); i -= 1; } } if (spawner.spawnAreaList.Count == 0) { spawner.spawnAreaList.Add(null); } cont = new GUIContent("Spawn Area:", "The area which the unit should be spawn in\nIf unspecified, the unit will simply be spawned at the position of the spawner\nRequire game object with a TDSArea component"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); spawner.spawnAreaList[0] = (TDSArea)EditorGUI.ObjectField(new Rect(startX + spaceX, startY, width, height), spawner.spawnAreaList[0], typeof(TDSArea), true); if (spawner.spawnAreaList[0] == null) { TDSArea existingArea = spawner.gameObject.GetComponent <TDSArea>(); if (GUI.Button(new Rect(startX + spaceX + width + 10, startY, 75, height), "Add Area")) { if (existingArea != null) { spawner.spawnAreaList[0] = existingArea; } else { spawner.spawnAreaList[0] = spawner.gameObject.AddComponent <TDSArea>(); } } } //only show extra spawn area in free form or endless mode if (spawner.spawnMode == _SpawnMode.FreeForm || (spawner.spawnMode == _SpawnMode.WaveBased && spawner.endlessWave)) { EditorGUI.HelpBox(new Rect(startX + spaceX + width + 20, startY, 1.5f * width, (spawner.spawnAreaList.Count + 1) * spaceY), "Alternate spawn-area will be randomly selected in freeform and endless mode", MessageType.None); for (int i = 1; i < spawner.spawnAreaList.Count; i++) { EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), " - Alt " + i + ":"); spawner.spawnAreaList[i] = (TDSArea)EditorGUI.ObjectField(new Rect(startX + spaceX, startY, width, height), spawner.spawnAreaList[i], typeof(TDSArea), true); if (GUI.Button(new Rect(startX + spaceX + width + 10, startY, 55, height), "remove")) { spawner.spawnAreaList.RemoveAt(i); i -= 1; } } if (GUI.Button(new Rect(startX + spaceX, startY += spaceY, width / 2, height), "Add")) { spawner.spawnAreaList.Add(null); } if (GUI.Button(new Rect(startX + spaceX + width / 2, startY, width / 2, height), "Remove")) { spawner.spawnAreaList.RemoveAt(spawner.spawnAreaList.Count - 1); } } startY += 10; Vector2 v2 = DrawOverrideHitPoint(startX, startY, spawner); startY = v2.y - 10; if (spawner.spawnMode == _SpawnMode.FreeForm) { int modeL = (int)spawner.limitType; cont = new GUIContent("Limit Type:", "Which mode to determine if the spawning is finished"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont, headerStyle); contL = new GUIContent[limitModeLabel.Length]; for (int i = 0; i < contL.Length; i++) { contL[i] = new GUIContent(limitModeLabel[i], limitModeTooltip[i]); } modeL = EditorGUI.Popup(new Rect(startX + spaceX, startY, width, 15), new GUIContent(""), modeL, contL); spawner.limitType = (_SpawnLimitType)modeL; if (spawner.limitType == _SpawnLimitType.Count) { cont = new GUIContent(" - Count Limit:", "The maximum amount of unit to be spawned. The spawner will stop spawning after it has spawned this many unit."); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); spawner.limitSpawnCount = EditorGUI.IntField(new Rect(startX + spaceX, startY, 40, height), spawner.limitSpawnCount); } else if (spawner.limitType == _SpawnLimitType.Timed) { cont = new GUIContent(" - Time Limit:", "The time duration in second which the spawner will be spawning. The spawner will stop spawning when the time is due"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); spawner.limitSpawnTime = EditorGUI.IntField(new Rect(startX + spaceX, startY, 40, height), spawner.limitSpawnTime); } else if (spawner.limitType == _SpawnLimitType.None) { EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), ""); EditorGUI.LabelField(new Rect(startX + spaceX, startY, width, height), "Infinite Spawn"); } cont = new GUIContent("Spawn Cooldown:", "The cooldown between each unit spawn"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); spawner.spawnCD = EditorGUI.FloatField(new Rect(startX + spaceX, startY, 40, height), spawner.spawnCD); cont = new GUIContent("Active Limit:", "The maximum amount of active spawned unit at any given time"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); spawner.activeLimit = EditorGUI.IntField(new Rect(startX + spaceX, startY, 40, height), spawner.activeLimit); startY += 15; v2 = DrawSpawnUnitList(startX, startY, spawner); startY = v2.y; } else if (spawner.spawnMode == _SpawnMode.WaveBased) { cont = new GUIContent("Waves Cooldown:", "cooldown between each wave"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); spawner.delayBetweenWave = EditorGUI.FloatField(new Rect(startX + spaceX, startY, 40, height), spawner.delayBetweenWave); startY += 10; if (spawner.endlessWave) { cont = new GUIContent("MaxSubWaveCount:", "Maximum subwave allow for each generated wave"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); spawner.maxSubWaveCount = EditorGUI.IntField(new Rect(startX + spaceX, startY, 40, height), spawner.maxSubWaveCount); startY += 5; float cachedX = startX; float spX = 70; cont = new GUIContent("Unit Count:", "starting unit count for each wave"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); spawner.unitCount = EditorGUI.IntField(new Rect(startX + spX, startY, 40, height), spawner.unitCount); cont = new GUIContent("Increment:", "increment in unit count for each subsequent wave"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); spawner.unitCountInc = EditorGUI.IntField(new Rect(startX + spX, startY, 40, height), spawner.unitCountInc); startY -= 2 * spaceY; startX += 125; cont = new GUIContent("Credit:", "starting unit count for each wave"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); spawner.startingCredit = EditorGUI.IntField(new Rect(startX + spX, startY, 40, height), spawner.startingCredit); cont = new GUIContent("Increment:", "increment in unit count for each subsequent wave"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); spawner.creditIncrement = EditorGUI.IntField(new Rect(startX + spX, startY, 40, height), spawner.creditIncrement); startY -= 2 * spaceY; startX += 125; cont = new GUIContent("Score:", "starting unit count for each wave"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); spawner.startingScore = EditorGUI.IntField(new Rect(startX + spX, startY, 40, height), spawner.startingScore); cont = new GUIContent("Increment:", "increment in unit count for each subsequent wave"); EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont); spawner.scoreIncrement = EditorGUI.IntField(new Rect(startX + spX, startY, 40, height), spawner.scoreIncrement); startY += 15; startX = cachedX; v2 = DrawSpawnUnitList(startX, startY, spawner); startY = v2.y; } else { EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), "Waves Count: " + spawner.waveList.Count, headerStyle); if (GUI.Button(new Rect(startX + spaceX, startY, 40, 16), "+")) { spawner.waveList.Add(new Wave()); } if (GUI.Button(new Rect(startX + spaceX + 50, startY, 40, 16), "-")) { if (spawner.waveList.Count > 1) { spawner.waveList.RemoveAt(spawner.waveList.Count - 1); } } for (int i = 0; i < spawner.waveList.Count; i++) { Wave wave = spawner.waveList[i]; startY += spaceY + 10; GUI.Box(new Rect(startX + 25, startY, 655, (2 + wave.subWaveList.Count) * spaceY + 15), ""); startX += 5; startY += 5; EditorGUI.LabelField(new Rect(startX, startY, width, height), (i + 1) + "."); startX += 25; //cont=new GUIContent("Credit:", "The credit gained upon clearing the wave"); //EditorGUI.LabelField(new Rect(startX, startY, width, height), cont); //wave.creditGain=EditorGUI.IntField(new Rect(startX+45, startY, 40, height), wave.creditGain); cont = new GUIContent("Score:", "The score gained upon clearing the wave"); EditorGUI.LabelField(new Rect(startX + 110, startY, width, height), cont); wave.scoreGain = EditorGUI.IntField(new Rect(startX + 154, startY, 40, height), wave.scoreGain); GUI.color = new Color(1f, 0.7f, 0.7f, 1f); if (GUI.Button(new Rect(startX + 585, startY, 55, 16), "remove")) { spawner.waveList.RemoveAt(i); i -= 1; continue; } GUI.color = Color.white; startY += 5; EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), "Sub Waves:"); if (GUI.Button(new Rect(startX + spaceX - 20, startY, 40, 16), "+")) { wave.subWaveList.Add(new SubWave()); } if (GUI.Button(new Rect(startX + spaceX + 30, startY, 40, 16), "-")) { if (wave.subWaveList.Count > 1) { wave.subWaveList.RemoveAt(wave.subWaveList.Count - 1); } } for (int n = 0; n < wave.subWaveList.Count; n++) { SubWave subWave = wave.subWaveList[n]; EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, 15), "-"); int unitIdx = subWave.unitPrefab != null?TDSEditor.GetUnitAIIndex(subWave.unitPrefab.prefabID) : 0; unitIdx = EditorGUI.Popup(new Rect(startX + 20, startY, width, 15), unitIdx, unitAILabel); if (unitIdx == 0) { subWave.unitPrefab = null; } else if (unitIdx > 0) { subWave.unitPrefab = unitAIDB.unitList[unitIdx - 1]; } float cachedX = startX; cont = new GUIContent("Count:", "The number of unit to be spawned"); EditorGUI.LabelField(new Rect(startX += 180, startY, width, height), cont); subWave.count = EditorGUI.IntField(new Rect(startX + 45, startY, 25, height), subWave.count); cont = new GUIContent("Delay:", "Delay (in second) before the spawning start"); EditorGUI.LabelField(new Rect(startX += 90, startY, width, height), cont); subWave.startDelay = EditorGUI.FloatField(new Rect(startX + 42, startY, 25, height), subWave.startDelay); cont = new GUIContent("Interval:", "The spawn interval (in second) between each unit"); EditorGUI.LabelField(new Rect(startX += 80, startY, width, height), cont); subWave.interval = EditorGUI.FloatField(new Rect(startX + 52, startY, 25, height), subWave.interval); cont = new GUIContent("Alt-Area:", "The area which the unit of this wave should be spawned, replacing the default area (optional)"); EditorGUI.LabelField(new Rect(startX += 90, startY, width, height), cont); wave.spawnArea = (TDSArea)EditorGUI.ObjectField(new Rect(startX + 60, startY, 100, height), wave.spawnArea, typeof(TDSArea), true); if (wave.subWaveList.Count > 1) { if (GUI.Button(new Rect(startX + 180, startY, 20, 16), "X")) { wave.subWaveList.RemoveAt(n); n -= 1; } } startX = cachedX; } startX -= 5; startY += 5; startX -= 25; } } } return(new Vector2(startX, startY + (2 * spaceY))); }