- 调整优化了 CombatNodeComponent 相关实体的生命周期管理
- 总结了一份 CombatNodeComponent 文档 CombatNodeArchitecture.md
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using GameFramework.DataTable;
|
||||
using GeometryTD.CustomEvent;
|
||||
using GeometryTD.DataTable;
|
||||
using GeometryTD.Definition;
|
||||
using UnityEngine;
|
||||
@@ -65,9 +66,8 @@ namespace GeometryTD.CustomComponent
|
||||
}
|
||||
|
||||
DRLevelPhase[] levelPhases = dtLevelPhase.GetAllDataRows();
|
||||
for (int i = 0; i < levelPhases.Length; i++)
|
||||
foreach (var phase in levelPhases)
|
||||
{
|
||||
DRLevelPhase phase = levelPhases[i];
|
||||
int levelId = phase.Id / 1000;
|
||||
if (!_levelsById.ContainsKey(levelId))
|
||||
{
|
||||
@@ -85,9 +85,8 @@ namespace GeometryTD.CustomComponent
|
||||
}
|
||||
|
||||
DRLevelSpawnEntry[] spawnEntries = dtSpawnEntry.GetAllDataRows();
|
||||
for (int i = 0; i < spawnEntries.Length; i++)
|
||||
foreach (var spawnEntry in spawnEntries)
|
||||
{
|
||||
DRLevelSpawnEntry spawnEntry = spawnEntries[i];
|
||||
int phaseId = spawnEntry.Id / 1000;
|
||||
int levelId = phaseId / 1000;
|
||||
if (!_levelsById.ContainsKey(levelId))
|
||||
@@ -171,6 +170,12 @@ namespace GeometryTD.CustomComponent
|
||||
|
||||
CurrentLevel = selectedLevel;
|
||||
_combatScheduler.Start(selectedLevel, phaseList, _selectedSpawnEntriesByPhaseId);
|
||||
GameEntry.Event.Fire(this, NodeEnterEventArgs.Create());
|
||||
}
|
||||
|
||||
public void EndCombat()
|
||||
{
|
||||
GameEntry.Event.Fire(this, NodeCompleteEventArgs.Create());
|
||||
}
|
||||
|
||||
public void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
@@ -252,4 +257,4 @@ namespace GeometryTD.CustomComponent
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,9 +23,9 @@ namespace GeometryTD.CustomComponent
|
||||
Failed = 4
|
||||
}
|
||||
|
||||
private readonly List<DRLevelPhase> _phaseBuffer = new List<DRLevelPhase>();
|
||||
private readonly Dictionary<int, IReadOnlyList<DRLevelSpawnEntry>> _spawnEntriesByPhaseId =
|
||||
new Dictionary<int, IReadOnlyList<DRLevelSpawnEntry>>();
|
||||
private readonly List<DRLevelPhase> _phaseBuffer = new();
|
||||
|
||||
private readonly Dictionary<int, IReadOnlyList<DRLevelSpawnEntry>> _spawnEntriesByPhaseId = new();
|
||||
|
||||
private readonly EnemyManager _enemyManager = new EnemyManager();
|
||||
|
||||
@@ -79,8 +79,8 @@ namespace GeometryTD.CustomComponent
|
||||
return;
|
||||
}
|
||||
|
||||
CleanupBattleEntities();
|
||||
_enemyManager.EndPhase();
|
||||
HideCurrentMapIfNeeded();
|
||||
ResetRuntime();
|
||||
|
||||
_currentLevel = level;
|
||||
@@ -145,8 +145,8 @@ namespace GeometryTD.CustomComponent
|
||||
return;
|
||||
}
|
||||
|
||||
CleanupBattleEntities();
|
||||
_enemyManager.OnDestroy();
|
||||
HideCurrentMapIfNeeded();
|
||||
ResetRuntime();
|
||||
UnsubscribeEntityEvents();
|
||||
_entity = null;
|
||||
@@ -253,7 +253,12 @@ namespace GeometryTD.CustomComponent
|
||||
{
|
||||
_state = SchedulerState.Completed;
|
||||
_currentPhase = null;
|
||||
if (_currentMap != null)
|
||||
{
|
||||
_entity.HideEntity(_currentMap);
|
||||
}
|
||||
Log.Info("CombatScheduler level completed. Level={0}.", _currentLevel != null ? _currentLevel.Id : 0);
|
||||
GameEntry.CombatNode.EndCombat();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -273,39 +278,6 @@ namespace GeometryTD.CustomComponent
|
||||
spawnEntries != null ? spawnEntries.Count : 0);
|
||||
}
|
||||
|
||||
private void HideCurrentMapIfNeeded()
|
||||
{
|
||||
if (_entity == null)
|
||||
{
|
||||
_currentMap = null;
|
||||
_loadingMapEntityId = 0;
|
||||
_loadedMapEntityId = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_loadingMapEntityId != 0)
|
||||
{
|
||||
EntityBase loadingMap = _entity.GetGameEntity(_loadingMapEntityId);
|
||||
if (loadingMap != null)
|
||||
{
|
||||
_entity.HideEntity(loadingMap);
|
||||
}
|
||||
}
|
||||
|
||||
if (_loadedMapEntityId != 0)
|
||||
{
|
||||
EntityBase loadedMap = _entity.GetGameEntity(_loadedMapEntityId);
|
||||
if (loadedMap != null)
|
||||
{
|
||||
_entity.HideEntity(loadedMap);
|
||||
}
|
||||
}
|
||||
|
||||
_loadingMapEntityId = 0;
|
||||
_loadedMapEntityId = 0;
|
||||
_currentMap = null;
|
||||
}
|
||||
|
||||
private void EnsureEntityEventSubscribed()
|
||||
{
|
||||
if (_isEntityEventSubscribed)
|
||||
@@ -340,9 +312,40 @@ namespace GeometryTD.CustomComponent
|
||||
_currentPhase = null;
|
||||
_currentPhaseIndex = -1;
|
||||
_currentPhaseElapsed = 0f;
|
||||
_loadingMapEntityId = 0;
|
||||
_loadedMapEntityId = 0;
|
||||
_currentMap = null;
|
||||
_state = SchedulerState.Idle;
|
||||
}
|
||||
|
||||
private void CleanupBattleEntities()
|
||||
{
|
||||
if (_entity == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_loadingMapEntityId != 0 && _entity.IsLoadingEntity(_loadingMapEntityId))
|
||||
{
|
||||
_entity.HideEntity(_loadingMapEntityId);
|
||||
}
|
||||
|
||||
if (_currentMap != null)
|
||||
{
|
||||
_entity.HideEntity(_currentMap);
|
||||
}
|
||||
else if (_loadedMapEntityId != 0)
|
||||
{
|
||||
UnityGameFramework.Runtime.Entity loadedMapEntity = _entity.GetEntity(_loadedMapEntityId);
|
||||
if (loadedMapEntity != null)
|
||||
{
|
||||
_entity.HideEntity(loadedMapEntity);
|
||||
}
|
||||
}
|
||||
|
||||
_enemyManager.CleanupTrackedEnemies();
|
||||
}
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
private void OnShowEntitySuccess(object sender, GameEventArgs e)
|
||||
|
||||
@@ -29,6 +29,8 @@ namespace GeometryTD.CustomComponent
|
||||
private readonly Dictionary<int, Spawner> _spawnerByOrder = new Dictionary<int, Spawner>();
|
||||
private readonly List<Vector3> _pathBuffer = new List<Vector3>();
|
||||
private readonly List<SpawnEntryRuntime> _spawnRuntimes = new List<SpawnEntryRuntime>();
|
||||
private readonly HashSet<int> _trackedEnemyEntityIds = new HashSet<int>();
|
||||
private readonly List<int> _trackedEnemyIdBuffer = new List<int>();
|
||||
|
||||
private CombatScheduler _combatScheduler;
|
||||
private EntityComponent _entity;
|
||||
@@ -66,6 +68,8 @@ namespace GeometryTD.CustomComponent
|
||||
_spawnerByOrder.Clear();
|
||||
_pathBuffer.Clear();
|
||||
_spawnRuntimes.Clear();
|
||||
_trackedEnemyEntityIds.Clear();
|
||||
_trackedEnemyIdBuffer.Clear();
|
||||
_phaseElapsed = 0f;
|
||||
_isPhaseRunning = false;
|
||||
IsPhaseSpawnCompleted = true;
|
||||
@@ -134,6 +138,7 @@ namespace GeometryTD.CustomComponent
|
||||
return;
|
||||
}
|
||||
|
||||
CleanupTrackedEnemies();
|
||||
EndPhase();
|
||||
GameEntry.Event.Unsubscribe(ShowEntitySuccessEventArgs.EventId, OnShowEntitySuccess);
|
||||
GameEntry.Event.Unsubscribe(ShowEntityFailureEventArgs.EventId, OnShowEntityFailure);
|
||||
@@ -142,12 +147,47 @@ namespace GeometryTD.CustomComponent
|
||||
_spawners.Clear();
|
||||
_spawnerByOrder.Clear();
|
||||
_pathBuffer.Clear();
|
||||
_trackedEnemyEntityIds.Clear();
|
||||
_trackedEnemyIdBuffer.Clear();
|
||||
_currentEnemyCount = 0;
|
||||
_currentMapEntityId = 0;
|
||||
_nextSpawnerIndex = 0;
|
||||
_combatScheduler = null;
|
||||
_initialized = false;
|
||||
}
|
||||
|
||||
public void CleanupTrackedEnemies()
|
||||
{
|
||||
if (_trackedEnemyEntityIds.Count <= 0)
|
||||
{
|
||||
_currentEnemyCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
_trackedEnemyIdBuffer.Clear();
|
||||
foreach (int trackedEnemyEntityId in _trackedEnemyEntityIds)
|
||||
{
|
||||
_trackedEnemyIdBuffer.Add(trackedEnemyEntityId);
|
||||
}
|
||||
|
||||
_trackedEnemyEntityIds.Clear();
|
||||
_currentEnemyCount = 0;
|
||||
|
||||
if (_entity == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _trackedEnemyIdBuffer.Count; i++)
|
||||
{
|
||||
int trackedEnemyEntityId = _trackedEnemyIdBuffer[i];
|
||||
if (_entity.HasEntity(trackedEnemyEntityId) || _entity.IsLoadingEntity(trackedEnemyEntityId))
|
||||
{
|
||||
_entity.HideEntity(trackedEnemyEntityId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SpawnEntryRuntime BuildSpawnRuntime(DRLevelSpawnEntry entry)
|
||||
{
|
||||
if (entry == null || entry.EntryType == EntryType.None)
|
||||
@@ -167,12 +207,12 @@ namespace GeometryTD.CustomComponent
|
||||
switch (entry.EntryType)
|
||||
{
|
||||
case EntryType.Stream:
|
||||
{
|
||||
float duration = Mathf.Max(0f, entry.Duration);
|
||||
runtime.EndTime = duration > 0f ? runtime.NextTriggerTime + duration : runtime.NextTriggerTime;
|
||||
runtime.Completed = entry.Count <= 0;
|
||||
return runtime;
|
||||
}
|
||||
{
|
||||
float duration = Mathf.Max(0f, entry.Duration);
|
||||
runtime.EndTime = duration > 0f ? runtime.NextTriggerTime + duration : runtime.NextTriggerTime;
|
||||
runtime.Completed = entry.Count <= 0;
|
||||
return runtime;
|
||||
}
|
||||
case EntryType.Burst:
|
||||
case EntryType.Boss:
|
||||
runtime.Completed = runtime.RemainingCount <= 0;
|
||||
@@ -311,6 +351,7 @@ namespace GeometryTD.CustomComponent
|
||||
}
|
||||
|
||||
int enemyEntityId = _entity.GenerateSerialId();
|
||||
_trackedEnemyEntityIds.Add(enemyEntityId);
|
||||
EnemyData enemyData = new EnemyData(
|
||||
enemyEntityId,
|
||||
enemyConfig.EntityId,
|
||||
@@ -434,17 +475,28 @@ namespace GeometryTD.CustomComponent
|
||||
|
||||
private void OnShowEntitySuccess(object sender, GameEventArgs e)
|
||||
{
|
||||
if (e is ShowEntitySuccessEventArgs ne)
|
||||
if (!(e is ShowEntitySuccessEventArgs ne)) return;
|
||||
|
||||
if (ne.EntityLogicType == typeof(EnemyEntity) &&
|
||||
_trackedEnemyEntityIds.Contains(ne.Entity.Id))
|
||||
{
|
||||
if (ne.EntityLogicType == typeof(EnemyEntity))
|
||||
{
|
||||
_currentEnemyCount++;
|
||||
}
|
||||
_currentEnemyCount++;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnShowEntityFailure(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is ShowEntityFailureEventArgs ne))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ne.EntityLogicType != typeof(EnemyEntity))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_trackedEnemyEntityIds.Remove(ne.EntityId);
|
||||
}
|
||||
|
||||
private void OnHideEntityComplete(object sender, GameEventArgs e)
|
||||
@@ -454,7 +506,7 @@ namespace GeometryTD.CustomComponent
|
||||
return;
|
||||
}
|
||||
|
||||
if (ne.EntityGroup.Name != "Enemy")
|
||||
if (!_trackedEnemyEntityIds.Remove(ne.EntityId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -462,4 +514,4 @@ namespace GeometryTD.CustomComponent
|
||||
_currentEnemyCount = Mathf.Max(0, _currentEnemyCount - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user