Files
Net.Like.Xue.Tokyo/Packages-Local/Com.Project.B.Unity/Npc/NpcSpawnManager.cs
2025-06-24 23:49:13 +08:00

103 lines
3.1 KiB
C#

using UnityEngine;
using UnityEngine.AI;
using System.Collections.Generic;
using BITKit;
namespace Net.Project.B.AI
{
public class SpawnManager : MonoBehaviour
{
public float spawnRadius = 20f; // 刷怪区域半径
public int maxSpawnPoints = 10; // 最大刷怪点数量
public float minDistanceBetweenSpawns = 5f; // 最小刷怪点间距
public float clearanceCheckDistance = 3f; // 空旷度检测半径
public GameObject enemyPrefab; // 怪物预制体
void Start()
{
List<Vector3> spawnPoints = GenerateSpawnPoints(transform.position, spawnRadius, minDistanceBetweenSpawns,
maxSpawnPoints);
foreach (var point in spawnPoints)
{
Instantiate(enemyPrefab, point, Quaternion.identity);
Debug.DrawRay(point, Vector3.up * 2, Color.green, 5f); // 可视化调试
}
}
List<Vector3> GenerateSpawnPoints(Vector3 center, float radius, float minDist, int maxPoints)
{
List<Vector3> spawnPoints = new List<Vector3>();
int attempts = 0;
while (spawnPoints.Count < maxPoints && attempts < maxPoints * 10)
{
Vector3 randomPoint = center + Random.insideUnitSphere * radius;
randomPoint.y = center.y; // 保持 Y 轴位置
if (NavMesh.SamplePosition(randomPoint, out NavMeshHit hit, 2f, NavMesh.AllAreas))
{
if (IsClearArea(hit.position, minDist, spawnPoints) && IsSpacious(hit.position))
{
spawnPoints.Add(hit.position);
}
}
attempts++;
}
return spawnPoints;
}
// 确保刷怪点不会过近
bool IsClearArea(Vector3 pos, float minDist, List<Vector3> points)
{
foreach (var p in points)
{
if (Vector3.Distance(p, pos) < minDist)
return false;
}
return true;
}
// 确保周围没有障碍物,区域足够空旷
bool IsSpacious(Vector3 pos)
{
for (int i = 0; i < 8; i++)
{
Vector3 dir = Quaternion.Euler(0, i * 45, 0) * Vector3.forward * clearanceCheckDistance;
if (NavMesh.Raycast(pos, pos + dir, out _, NavMesh.AllAreas))
{
return false; // 遇到障碍,位置不合适
}
}
return true;
}
#if UNITY_EDITOR
[BIT]
private void Sample()
{
_spawnPoints =
GenerateSpawnPoints(transform.position, spawnRadius, minDistanceBetweenSpawns, maxSpawnPoints);
}
private List<Vector3> _spawnPoints = new();
// 可视化调试刷怪点
void OnDrawGizmos()
{
if (Application.isPlaying) return;
Gizmos.color = Color.red;
foreach (var point in _spawnPoints)
{
Gizmos.DrawSphere(point, 0.5f);
}
}
#endif
}
}