public Wave Generate(int waveID) { if (pathList.Count == 0) { Debug.Log("no path at all"); return(null); } Wave wave = new Wave(); wave.waveID = waveID; waveID += 1; int _subWaveCount = Mathf.Max(1, (int)subWaveCount.GetValueAtWave(waveID)); int totalUnitCount = (int)unitCount.GetValueAtWave(waveID); _subWaveCount = Mathf.Min(totalUnitCount, _subWaveCount); //filter thru all the units, only use the one that meets the wave requirement (>minWave) List <ProceduralUnitSetting> availableUnitList = new List <ProceduralUnitSetting>(); int nearestAvailableID = 0; float currentNearestValue = Mathf.Infinity; for (int i = 0; i < unitSettingList.Count; i++) { if (!unitSettingList[i].enabled) { continue; } if (unitSettingList[i].minWave <= waveID) { availableUnitList.Add(unitSettingList[i]); } //while we are at it, check which unit has the lowest wave requirement, just in case if (availableUnitList.Count == 0 && unitSettingList[i].minWave < currentNearestValue) { currentNearestValue = unitSettingList[i].minWave; nearestAvailableID = i; } } //if no unit available, simply uses the one with lowest requirement if (availableUnitList.Count == 0) { availableUnitList.Add(unitSettingList[nearestAvailableID]); } //we are going to just iterate thru the pathlist and assign them to each subwave. //So here we introduce an offset so it doesnt always start from the first path in the list int startingPathID = Random.Range(0, pathList.Count); for (int i = 0; i < _subWaveCount; i++) { SubWave subWave = new SubWave(); int unitID = Random.Range(0, availableUnitList.Count); ProceduralUnitSetting unitSetting = availableUnitList[unitID]; subWave.unit = unitSetting.unit.gameObject; subWave.overrideHP = unitSetting.HP.GetValueAtWave(waveID); subWave.overrideShield = unitSetting.shield.GetValueAtWave(waveID); subWave.overrideMoveSpd = unitSetting.speed.GetValueAtWave(waveID); //limit the minimum interval to 0.25f subWave.interval = Mathf.Max(0.25f, unitSetting.interval.GetValueAtWave(waveID)); //iterate through the path, randomly skip one int pathID = startingPathID + (Random.Range(0f, 1f) > 0.75f ? 1 : 0); while (pathID >= pathList.Count) { pathID -= pathList.Count; } subWave.path = pathList[pathID]; subWave.delay = i * Random.Range(2f, 3f); wave.subWaveList.Add(subWave); } //fill up the unit count int remainingUnitCount = totalUnitCount; while (remainingUnitCount > 0) { for (int i = 0; i < _subWaveCount; i++) { if (wave.subWaveList[i].count == 0) { wave.subWaveList[i].count = 1; remainingUnitCount -= 1; } else { int rand = Random.Range(0, 3); rand = Mathf.Min(rand, remainingUnitCount); wave.subWaveList[i].count += rand; remainingUnitCount -= rand; } } } wave.duration = wave.CalculateSpawnDuration(); //get the slowest moving unit and the longest path so we know which subwave is going to take the longest to finish float longestDuration = 0; for (int i = 0; i < _subWaveCount; i++) { float pathDist = wave.subWaveList[i].path.GetPathDistance(); float moveSpeed = wave.subWaveList[i].overrideMoveSpd; float duration = pathDist / moveSpeed; if (duration > longestDuration) { longestDuration = duration; } } //add the longest to the existing duration wave.duration += longestDuration * Random.Range(0.5f, 0.8f); for (int i = 0; i < rscSettingList.Count; i++) { wave.rscGainList.Add((int)rscSettingList[i].GetValueAtWave(waveID)); } return(wave); }
Vector2 DrawProceduralUnitSetting(float startX, float startY, ProceduralUnitSetting unitSetting) { if (unitSetting.enabled) { GUI.Box(new Rect(startX, startY, 185 * 4, 32 + 5 * 17 + 12), ""); } else { GUI.Box(new Rect(startX, startY, 185 * 4, 32 + 10), ""); } startX += 5; startY += 5; Vector2 v2 = default(Vector2); float cachedX = startX; int unitID = -1; for (int n = 0; n < creepList.Count; n++) { if (unitSetting.unit == creepList[n].gameObject) { unitID = n; } } EditorUtilities.DrawSprite(new Rect(startX, startY, 30, 30), creepList[unitID].iconSprite); EditorGUI.LabelField(new Rect(startX + 32, startY += -2, width, height), creepList[unitID].unitName); cont = new GUIContent("enabled: ", "Check to enable unit in the procedural generation otherwise unit will not be considered at all"); EditorGUI.LabelField(new Rect(startX + 32, startY += spaceY - 5, width, height), cont); unitSetting.enabled = EditorGUI.Toggle(new Rect(startX + 32 + 60, startY, width, height), unitSetting.enabled); if (!unitSetting.enabled) { return(new Vector2(cachedX, startY)); } cont = new GUIContent("Min Wave:", "The minimum wave in which the creep will start appear in"); EditorGUI.LabelField(new Rect(startX += 185, startY - 8, width, height), cont); unitSetting.minWave = EditorGUI.IntField(new Rect(startX + 70, startY - 8, 40, height), unitSetting.minWave); EditorGUI.LabelField(new Rect(cachedX, startY + 7, 185 * 4 - 10, height), "______________________________________________________________________________________________________________________"); startY += spaceY; startX = cachedX; cont = new GUIContent("HitPoint (HP):"); v2 = DrawProceduralVariable(startX, startY, unitSetting.HP, cont); startX += v2.x + 20; cont = new GUIContent("Shield:"); v2 = DrawProceduralVariable(startX, startY, unitSetting.shield, cont); startX += v2.x + 20; cont = new GUIContent("Move Speed:"); v2 = DrawProceduralVariable(startX, startY, unitSetting.speed, cont); startX += v2.x + 20; cont = new GUIContent("Spawn Interval:"); v2 = DrawProceduralVariable(startX, startY, unitSetting.interval, cont); startX += v2.x + 20; return(v2); }
private static void GetSpawnManager() { instance = (SpawnManager)FindObjectOfType(typeof(SpawnManager)); if (instance != null) { window.waveFoldList = new List <bool>(); for (int i = 0; i < instance.waveList.Count; i++) { window.waveFoldList.Add(true); } //if path is empty, get a path if (instance.defaultPath == null) { instance.defaultPath = (PathTD)FindObjectOfType(typeof(PathTD)); } //verify and setup the procedural wave generation unit list List <ProceduralUnitSetting> unitSettingList = instance.waveGenerator.unitSettingList; List <ProceduralUnitSetting> newSettingList = new List <ProceduralUnitSetting>(); for (int i = 0; i < creepList.Count; i++) { bool match = false; for (int n = 0; n < unitSettingList.Count; n++) { if (unitSettingList[n].unit == creepList[i].gameObject) { newSettingList.Add(unitSettingList[n]); match = true; break; } } if (!match) { ProceduralUnitSetting unitSetting = new ProceduralUnitSetting(); unitSetting.unit = creepList[i].gameObject; newSettingList.Add(unitSetting); } } instance.waveGenerator.unitSettingList = newSettingList; instance.waveGenerator.CheckPathList(); if (instance.defaultPath != null && instance.waveGenerator.pathList.Count == 0) { instance.waveGenerator.pathList.Add(instance.defaultPath); } List <ProceduralVariable> rscSettingList = instance.waveGenerator.rscSettingList; while (rscList.Count > rscSettingList.Count) { rscSettingList.Add(new ProceduralVariable(10, 500)); } while (rscList.Count < rscSettingList.Count) { rscSettingList.RemoveAt(rscSettingList.Count - 1); } EditorUtility.SetDirty(instance); } }
Vector2 WaveGeneratorSetting(float startX, float startY) { float cachedX = startX; WaveGenerator waveGen = instance.waveGenerator; Vector2 v2; cont = new GUIContent("Sub Wave Count:"); v2 = DrawProceduralVariable(startX, startY, waveGen.subWaveCount, cont); startX += v2.x + 20; cont = new GUIContent("Total Creep Count:"); v2 = DrawProceduralVariable(startX, startY, waveGen.unitCount, cont); startX += v2.x + 20; //startY=v2.y; startX += 140; showProceduralPathList = EditorGUI.Foldout(new Rect(startX, startY, 60, height), showProceduralPathList, "Path List " + (showProceduralPathList ? "" : "(" + waveGen.pathList.Count + ")")); if (showProceduralPathList) { int count = waveGen.pathList.Count; count = EditorGUI.IntField(new Rect(startX + spaceX, startY, 40, height - 2), count); while (count < waveGen.pathList.Count) { waveGen.pathList.RemoveAt(waveGen.pathList.Count - 1); } while (count > waveGen.pathList.Count) { waveGen.pathList.Add(null); } for (int i = 0; i < waveGen.pathList.Count; i++) { EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), " - Element " + (i + 1)); waveGen.pathList[i] = (PathTD)EditorGUI.ObjectField(new Rect(startX + spaceX, startY, width, 15), waveGen.pathList[i], typeof(PathTD), true); } } if (startY < v2.y) { startY = v2.y; } startX = cachedX; startY += spaceY + 15; for (int i = 0; i < waveGen.rscSettingList.Count; i++) { EditorUtilities.DrawSprite(new Rect(startX, startY - 5, 22, 22), rscList[i].icon); cont = new GUIContent(" " + rscList[i].name + ":"); v2 = DrawProceduralVariable(startX, startY, waveGen.rscSettingList[i], cont); startX += v2.x + 20; //startY=v2.y; } startX = cachedX; startY = v2.y + spaceY + 15; for (int i = 0; i < waveGen.unitSettingList.Count; i++) { ProceduralUnitSetting unitSetting = waveGen.unitSettingList[i]; v2 = DrawProceduralUnitSetting(startX, startY, unitSetting); startY = v2.y + spaceY + 15; } contentWidth = 185 * 4 + 25; return(new Vector2(185 * 4, startY)); }