推进计时器逻辑的集中管理
- 将敌人的攻击计时任务放到基类中进行创建 - 将 EnemySpawnScheduler 敌人生成调度器的刷怪计时任务迁移到 TimerComponent
This commit is contained in:
+29
-67
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SepCore.DataTable;
|
||||
using SepCore.Definition;
|
||||
using SepCore.Timer;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SepCore.EnemyManager
|
||||
@@ -12,98 +12,67 @@ namespace SepCore.EnemyManager
|
||||
|
||||
private float _elapsedTime;
|
||||
private float[] _baseIntervals;
|
||||
private float[] _currentIntervals;
|
||||
private EnemyType[] _enemyTypes;
|
||||
private int[] _spawnCounts;
|
||||
private float[] _nextSpawnTimes;
|
||||
private TimerHandle[] _waveHandles;
|
||||
private float _spawnRateScale = 1f;
|
||||
private Action<EnemyType, int> _onSpawn;
|
||||
|
||||
public float SpawnRateScale => _spawnRateScale;
|
||||
public float ElapsedTime => _elapsedTime;
|
||||
public int WaveCount => _enemyTypes?.Length ?? 0;
|
||||
|
||||
public void Init(DRLevel level)
|
||||
public void Init(DRLevel level, Action<EnemyType, int> onSpawn)
|
||||
{
|
||||
GameEntry.Timer.CancelByOwner(this);
|
||||
|
||||
_onSpawn = onSpawn;
|
||||
_baseIntervals = (float[])level.Intervals.Clone();
|
||||
_currentIntervals = (float[])_baseIntervals.Clone();
|
||||
_enemyTypes = level.EntityTypes;
|
||||
_spawnCounts = level.EntityCounts;
|
||||
_elapsedTime = 0f;
|
||||
|
||||
SetSpawnRateScale(_spawnRateScale);
|
||||
_waveHandles = new TimerHandle[_baseIntervals.Length];
|
||||
for (int i = 0; i < _baseIntervals.Length; i++)
|
||||
{
|
||||
int waveIndex = i;
|
||||
float interval = GetScaledInterval(_baseIntervals[i], _spawnRateScale);
|
||||
_waveHandles[i] = GameEntry.Timer.ScheduleRepeat(interval, () => OnWaveTick(waveIndex), -1, this);
|
||||
}
|
||||
}
|
||||
|
||||
public List<SpawnRequest> Tick(float deltaTime)
|
||||
public void Tick(float deltaTime)
|
||||
{
|
||||
_elapsedTime += deltaTime;
|
||||
var requests = new List<SpawnRequest>();
|
||||
|
||||
if (_nextSpawnTimes == null) return requests;
|
||||
|
||||
for (int i = 0; i < _nextSpawnTimes.Length; i++)
|
||||
{
|
||||
if (_elapsedTime < _nextSpawnTimes[i]) continue;
|
||||
|
||||
requests.Add(new SpawnRequest
|
||||
{
|
||||
EnemyType = _enemyTypes[i],
|
||||
Count = _spawnCounts[i],
|
||||
WaveIndex = i
|
||||
});
|
||||
|
||||
_nextSpawnTimes[i] += _currentIntervals[i];
|
||||
}
|
||||
|
||||
return requests;
|
||||
}
|
||||
|
||||
public void SetSpawnRateScale(float scale)
|
||||
{
|
||||
float newScale = Mathf.Max(MinSpawnRateScale, scale);
|
||||
if (_baseIntervals == null || _baseIntervals.Length == 0)
|
||||
_spawnRateScale = Mathf.Max(MinSpawnRateScale, scale);
|
||||
if (_waveHandles == null) return;
|
||||
|
||||
for (int i = 0; i < _waveHandles.Length; i++)
|
||||
{
|
||||
_spawnRateScale = newScale;
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasRuntimeState = _nextSpawnTimes != null && _currentIntervals != null &&
|
||||
_nextSpawnTimes.Length == _baseIntervals.Length &&
|
||||
_currentIntervals.Length == _baseIntervals.Length;
|
||||
float oldScale = _spawnRateScale;
|
||||
_spawnRateScale = newScale;
|
||||
|
||||
if (!hasRuntimeState)
|
||||
{
|
||||
for (int i = 0; i < _baseIntervals.Length; i++)
|
||||
{
|
||||
_currentIntervals[i] = GetScaledInterval(_baseIntervals[i], _spawnRateScale);
|
||||
}
|
||||
|
||||
_nextSpawnTimes = (float[])_currentIntervals.Clone();
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _baseIntervals.Length; i++)
|
||||
{
|
||||
float oldInterval = GetScaledInterval(_baseIntervals[i], oldScale);
|
||||
float newInterval = GetScaledInterval(_baseIntervals[i], _spawnRateScale);
|
||||
|
||||
float remainTime = Mathf.Max(0f, _nextSpawnTimes[i] - _elapsedTime);
|
||||
float remainRatio = oldInterval > Mathf.Epsilon ? Mathf.Clamp01(remainTime / oldInterval) : 0f;
|
||||
|
||||
_currentIntervals[i] = newInterval;
|
||||
_nextSpawnTimes[i] = _elapsedTime + newInterval * remainRatio;
|
||||
GameEntry.Timer.SetInterval(_waveHandles[i], newInterval, adjustRemainingTime: true);
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
GameEntry.Timer.CancelByOwner(this);
|
||||
_elapsedTime = 0;
|
||||
_baseIntervals = null;
|
||||
_currentIntervals = null;
|
||||
_enemyTypes = null;
|
||||
_spawnCounts = null;
|
||||
_nextSpawnTimes = null;
|
||||
_waveHandles = null;
|
||||
_spawnRateScale = 1f;
|
||||
_onSpawn = null;
|
||||
}
|
||||
|
||||
private void OnWaveTick(int waveIndex)
|
||||
{
|
||||
_onSpawn?.Invoke(_enemyTypes[waveIndex], _spawnCounts[waveIndex]);
|
||||
}
|
||||
|
||||
private static float GetScaledInterval(float baseInterval, float scale)
|
||||
@@ -112,11 +81,4 @@ namespace SepCore.EnemyManager
|
||||
return baseInterval / safeScale;
|
||||
}
|
||||
}
|
||||
|
||||
public struct SpawnRequest
|
||||
{
|
||||
public EnemyType EnemyType;
|
||||
public int Count;
|
||||
public int WaveIndex;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user