从 EnemyManager 里拆分出敌人的注册/管理/查询功能

This commit is contained in:
SepComet 2026-06-18 15:33:36 +08:00
parent b6a13b18fc
commit 921193f469
3 changed files with 109 additions and 75 deletions

View File

@ -17,18 +17,14 @@ namespace SepCore.EnemyManager
private const string EnemyGroupName = "Enemy"; private const string EnemyGroupName = "Enemy";
private EntityComponent _entity; private EntityComponent _entity;
private EnemyRegistry _enemyRegistry;
private List<EntityBase> _enemies; public List<EntityBase> Enemies => _enemyRegistry?.Enemies;
private Dictionary<int, EntityBase> _enemyById;
public List<EntityBase> Enemies => _enemies;
private float _spawnEnemyTimer; private float _spawnEnemyTimer;
[SerializeField] private int _spawnEnemyMaxCount = 5000; [SerializeField] private int _spawnEnemyMaxCount = 5000;
private int _currentEnemyCount;
[SerializeField] private int _spawnDistanceFromPlayer = 20; [SerializeField] private int _spawnDistanceFromPlayer = 20;
private int _currentSpawnEnemyId; private int _currentSpawnEnemyId;
@ -51,15 +47,14 @@ namespace SepCore.EnemyManager
public float SpawnRateScale => _spawnRateScale; public float SpawnRateScale => _spawnRateScale;
public float BattleDuration => _duration; public float BattleDuration => _duration;
public float ElapsedBattleTime => _spawnEnemyTimer; public float ElapsedBattleTime => _spawnEnemyTimer;
public int CurrentEnemyCount => _currentEnemyCount; public int CurrentEnemyCount => _enemyRegistry?.Count ?? 0;
#region FSM #region FSM
private void Start() private void Start()
{ {
_entity = GameEntry.Entity; _entity = GameEntry.Entity;
_enemies = new List<EntityBase>(); _enemyRegistry = new EnemyRegistry();
_enemyById = new Dictionary<int, EntityBase>();
GameEntry.Event.Subscribe(HideEntityCompleteEventArgs.EventId, OnHideEntityComplete); GameEntry.Event.Subscribe(HideEntityCompleteEventArgs.EventId, OnHideEntityComplete);
} }
@ -68,8 +63,7 @@ namespace SepCore.EnemyManager
{ {
GameEntry.Event.Unsubscribe(HideEntityCompleteEventArgs.EventId, OnHideEntityComplete); GameEntry.Event.Unsubscribe(HideEntityCompleteEventArgs.EventId, OnHideEntityComplete);
_enemies = null; _enemyRegistry = null;
_enemyById = null;
_entity = null; _entity = null;
} }
@ -87,7 +81,7 @@ namespace SepCore.EnemyManager
SetSpawnRateScale(_spawnRateScale); SetSpawnRateScale(_spawnRateScale);
_currentEnemyCount = 0; _enemyRegistry.Clear();
_currentSpawnEnemyId = 0; _currentSpawnEnemyId = 0;
} }
@ -124,8 +118,6 @@ namespace SepCore.EnemyManager
_nextSpawnTimes = null; _nextSpawnTimes = null;
ClearEnemies(); ClearEnemies();
_currentEnemyCount = 0;
} }
#endregion #endregion
@ -134,7 +126,7 @@ namespace SepCore.EnemyManager
{ {
if (_player == null) return; if (_player == null) return;
if (_currentEnemyCount >= _spawnEnemyMaxCount) return; if (_enemyRegistry.Count >= _spawnEnemyMaxCount) return;
int entityPoolId = _currentSpawnEnemyId % _spawnEnemyMaxCount; int entityPoolId = _currentSpawnEnemyId % _spawnEnemyMaxCount;
var enemyData = EntityDataFactory.Create(entityPoolId, enemyType, _currentLevel); var enemyData = EntityDataFactory.Create(entityPoolId, enemyType, _currentLevel);
enemyData.Position = _spawnPositionStrategy.GetSpawnPosition(_player); enemyData.Position = _spawnPositionStrategy.GetSpawnPosition(_player);
@ -146,37 +138,24 @@ namespace SepCore.EnemyManager
return; return;
} }
RegisterEnemy(enemy); enemy.SetTarget(_player);
_enemyRegistry.Register(enemy);
} }
public void ClearEnemies() public void ClearEnemies()
{ {
foreach (var enemy in _enemies) foreach (var enemy in _enemyRegistry.Enemies)
{ {
if (enemy == null || !enemy.Available) continue; if (enemy == null || !enemy.Available) continue;
_entity.HideEntity(enemy); _entity.HideEntity(enemy);
} }
_enemies.Clear(); _enemyRegistry.Clear();
_enemyById?.Clear();
} }
public bool TryGetEnemy(int entityId, out EntityBase enemy) public bool TryGetEnemy(int entityId, out EntityBase enemy)
{ {
enemy = null; return _enemyRegistry.TryGet(entityId, out enemy);
if (_enemyById == null || !_enemyById.TryGetValue(entityId, out EntityBase cachedEnemy))
{
return false;
}
if (cachedEnemy == null || !cachedEnemy.Available)
{
_enemyById.Remove(entityId);
return false;
}
enemy = cachedEnemy;
return true;
} }
public void SetSpawnRateScale(float scale) public void SetSpawnRateScale(float scale)
@ -226,20 +205,6 @@ namespace SepCore.EnemyManager
#region Event Handler #region Event Handler
private void RegisterEnemy(EnemyBase enemy)
{
if (enemy == null)
{
return;
}
_currentEnemyCount++;
enemy.SetTarget(_player);
RemoveEnemyFromCache(enemy.Id);
_enemies.Add(enemy);
_enemyById[enemy.Id] = enemy;
}
private void OnHideEntityComplete(object sender, GameEventArgs e) private void OnHideEntityComplete(object sender, GameEventArgs e)
{ {
if (e is not HideEntityCompleteEventArgs ne) return; if (e is not HideEntityCompleteEventArgs ne) return;
@ -247,34 +212,7 @@ namespace SepCore.EnemyManager
string entityGroupName = ne.EntityGroup.Name; string entityGroupName = ne.EntityGroup.Name;
if (entityGroupName == EnemyGroupName) if (entityGroupName == EnemyGroupName)
{ {
if (_currentEnemyCount > 0) _enemyRegistry.Remove(ne.EntityId);
{
_currentEnemyCount--;
}
RemoveEnemyFromCache(ne.EntityId);
}
}
private void RemoveEnemyFromCache(int entityId)
{
if (_enemyById != null)
{
_enemyById.Remove(entityId);
}
for (int i = _enemies.Count - 1; i >= 0; i--)
{
EntityBase cachedEnemy = _enemies[i];
if (cachedEnemy == null || cachedEnemy.Id == entityId)
{
if (cachedEnemy != null && _enemyById != null)
{
_enemyById.Remove(cachedEnemy.Id);
}
_enemies.RemoveAt(i);
}
} }
} }

View File

@ -0,0 +1,85 @@
using System.Collections.Generic;
using SepCore.Entity;
using UnityEngine;
namespace SepCore.EnemyManager
{
public class EnemyRegistry
{
private readonly List<EntityBase> _enemies;
private readonly Dictionary<int, EntityBase> _enemyById;
public int Count { get; private set; }
public List<EntityBase> Enemies => _enemies;
public EnemyRegistry()
{
_enemies = new List<EntityBase>();
_enemyById = new Dictionary<int, EntityBase>();
}
public void Register(EnemyBase enemy)
{
if (enemy == null) return;
Count++;
RemoveFromCache(enemy.Id);
_enemies.Add(enemy);
_enemyById[enemy.Id] = enemy;
}
public void Remove(int entityId)
{
if (Count > 0)
{
Count--;
}
RemoveFromCache(entityId);
}
public bool TryGet(int entityId, out EntityBase enemy)
{
enemy = null;
if (!_enemyById.TryGetValue(entityId, out EntityBase cachedEnemy))
{
return false;
}
if (cachedEnemy == null || !cachedEnemy.Available)
{
_enemyById.Remove(entityId);
return false;
}
enemy = cachedEnemy;
return true;
}
public void Clear()
{
_enemies.Clear();
_enemyById.Clear();
Count = 0;
}
private void RemoveFromCache(int entityId)
{
_enemyById.Remove(entityId);
for (int i = _enemies.Count - 1; i >= 0; i--)
{
EntityBase cachedEnemy = _enemies[i];
if (cachedEnemy == null || cachedEnemy.Id == entityId)
{
if (cachedEnemy != null)
{
_enemyById.Remove(cachedEnemy.Id);
}
_enemies.RemoveAt(i);
}
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7a24dd17510328f4392432d9da7ab6a5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: