155 lines
4.7 KiB
C#
155 lines
4.7 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Unity.Mathematics;
|
|
using Unity.VisualScripting;
|
|
using UnityEngine;
|
|
using UnityEngine.AI;
|
|
using UnityEngine.UIElements;
|
|
|
|
public class EnemySpawner : MonoBehaviour
|
|
{
|
|
// Shared
|
|
public int Wave = 0;
|
|
public float difficulty = 1f;
|
|
|
|
// Inspector
|
|
[SerializeField] private float difficultyIncreasePerWave = 1f;
|
|
[SerializeField] public float WaveTime = 20f;
|
|
[SerializeField] private List<float> enemyDifficulties;
|
|
[SerializeField] private float SpawnRadius = 10;
|
|
[SerializeField] private int NumEnemies = 6;
|
|
[SerializeField] private GameObject[] players;
|
|
[SerializeField] private float initialSpawnDelay = 5;
|
|
|
|
// local
|
|
private bool nextWaveRequested = false;
|
|
public float timer = 0f;
|
|
private Camera mainCam;
|
|
private GameObject SpawnedEnenmyHolder;
|
|
[SerializeField] private List<EnemyPrefabInfo> enemyList;
|
|
|
|
private bool SpawnerStarted = false;
|
|
|
|
private void Start()
|
|
{
|
|
mainCam = Camera.main;
|
|
SpawnedEnenmyHolder = new GameObject("SpawnedEnenmyHolder");
|
|
|
|
for (int i = 0; i < 6; i++)
|
|
{
|
|
enemyList.Add(new EnemyPrefabInfo() { Difficulty = i+1, prefabs = Resources.LoadAll<GameObject>("Enemies/" + (i+1)) });
|
|
}
|
|
|
|
timer = WaveTime - initialSpawnDelay;
|
|
|
|
StartSpawning();
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
if (SpawnerStarted)
|
|
timer += Time.deltaTime;
|
|
|
|
if (timer > WaveTime || nextWaveRequested)
|
|
{
|
|
Task.Factory.StartNew(() => { Task.Delay(100); timer = 0; });
|
|
|
|
SpawnWave(difficulty);
|
|
|
|
Wave++;
|
|
difficulty *= MathF.Cbrt(difficultyIncreasePerWave);
|
|
nextWaveRequested = false;
|
|
timer = 0;
|
|
}
|
|
|
|
}
|
|
|
|
public void StartSpawning() => SpawnerStarted = true;
|
|
public void StartNextWave() => nextWaveRequested = true;
|
|
|
|
void SpawnWave(float difficulty)
|
|
{
|
|
//SpawnStrongestFirst(difficulty);
|
|
|
|
if (Wave != 0 && Wave % 10 == 0)
|
|
SpawnStrongestFirst(difficulty);
|
|
else
|
|
SpawnRandom(difficulty);
|
|
}
|
|
|
|
void SpawnStrongestFirst(float difficulty)
|
|
{
|
|
var decendingList = enemyList.Where(x => x.Difficulty < difficulty).OrderByDescending(x => x.Difficulty).ToArray();
|
|
for (int i = 0; i < decendingList.Length; i++)
|
|
{
|
|
while (difficulty > decendingList[i].Difficulty)
|
|
{
|
|
GameObject enemy = Instantiate(decendingList[i].prefabs[UnityEngine.Random.Range(0, decendingList[i].prefabs.Length)], GetRandomPointOnCircle(SpawnRadius), Quaternion.identity, SpawnedEnenmyHolder.transform);
|
|
difficulty -= decendingList[i].Difficulty;
|
|
|
|
enemy.GetComponent<EnemyPathFinding>().targets = players.Select(x=>x.transform).ToArray();
|
|
}
|
|
}
|
|
}
|
|
|
|
void SpawnRandom(float difficulty)
|
|
{
|
|
difficulty *= 1.1f;
|
|
while (difficulty > 1f) // Spawn until difficulty is less than 0.5f
|
|
{
|
|
var validEnemies = enemyList.Where(x => x.Difficulty <= difficulty).ToArray();
|
|
int enemyIndex = UnityEngine.Random.Range(0, validEnemies.Length);
|
|
var enemyToSpawn = validEnemies[enemyIndex];
|
|
difficulty -= enemyToSpawn.Difficulty;
|
|
|
|
int variant = UnityEngine.Random.Range(0, enemyToSpawn.prefabs.Length);
|
|
GameObject variantToSpawn = enemyToSpawn.prefabs[variant];
|
|
|
|
GameObject enemy = Instantiate(variantToSpawn, GetRandomPointOnCircle(SpawnRadius), Quaternion.identity, SpawnedEnenmyHolder.transform);
|
|
|
|
enemy.GetComponent<EnemyPathFinding>().targets = players.Select(x => x.transform).ToArray();
|
|
}
|
|
}
|
|
|
|
public Vector3 GetRandomPointOnCircle(float radius)
|
|
{
|
|
Vector3 point;
|
|
do
|
|
{
|
|
float angle = UnityEngine.Random.Range(0f, 360f);
|
|
float radians = Mathf.Deg2Rad * angle;
|
|
|
|
Vector3 position = transform.position;
|
|
float x = position.x + radius * Mathf.Cos(radians);
|
|
float y = position.y + radius * Mathf.Sin(radians);
|
|
|
|
point = new Vector3(x, y, position.z);
|
|
} while (IsPointOnNavMesh(point));
|
|
|
|
return point;
|
|
}
|
|
|
|
bool IsPointOnNavMesh(Vector3 point)
|
|
{
|
|
NavMeshHit hit;
|
|
return NavMesh.SamplePosition(point, out hit, 0.1f, NavMesh.AllAreas);
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
Gizmos.color = Color.green;
|
|
Gizmos.DrawWireSphere(transform.position, SpawnRadius);
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
Gizmos.DrawWireSphere(GetRandomPointOnCircle(SpawnRadius), 0.25f);
|
|
}
|
|
}
|
|
#endif
|
|
}
|