将 Enemy 攻击冷却计时器 由 Enemy 内部维护迁移到 TimerModule 维护

This commit is contained in:
SepComet 2026-06-18 23:09:44 +08:00
parent 0dc5889417
commit 25f36d38c9
3 changed files with 25 additions and 23 deletions

View File

@ -1,6 +1,7 @@
using SepCore.Components; using SepCore.Components;
using SepCore.CustomUtility; using SepCore.CustomUtility;
using SepCore.Definition; using SepCore.Definition;
using SepCore.Timer;
using UnityEngine; using UnityEngine;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;
@ -23,7 +24,8 @@ namespace SepCore.Entity
private int _attackDamage = 1; private int _attackDamage = 1;
private float _sqrAttackRange; private float _sqrAttackRange;
private float _currAttackTimer; private TimerHandle _attackTimerHandle;
private bool _canAttack;
private AttackStateType _attackState = AttackStateType.Idle; private AttackStateType _attackState = AttackStateType.Idle;
@ -69,7 +71,8 @@ namespace SepCore.Entity
_attackDamage = Mathf.Max(1, _meleeEnemyData.AttackDamage); _attackDamage = Mathf.Max(1, _meleeEnemyData.AttackDamage);
_sqrAttackRange = _attackRange * _attackRange; _sqrAttackRange = _attackRange * _attackRange;
_currAttackTimer = 0f; _canAttack = false;
_attackTimerHandle = GameEntry.Timer.ScheduleOnce(_attackCooldown, () => _canAttack = true, this);
_attackState = AttackStateType.Idle; _attackState = AttackStateType.Idle;
_targetableTarget = null; _targetableTarget = null;
@ -93,7 +96,8 @@ namespace SepCore.Entity
_movementComponent.OnReset(); _movementComponent.OnReset();
_healthComponent.OnReset(); _healthComponent.OnReset();
_targetableTarget = null; _targetableTarget = null;
_currAttackTimer = 0f; GameEntry.Timer.Cancel(_attackTimerHandle);
_attackTimerHandle = TimerHandle.Invalid;
_attackState = AttackStateType.Idle; _attackState = AttackStateType.Idle;
base.OnHide(isShutdown, userData); base.OnHide(isShutdown, userData);
@ -109,8 +113,6 @@ namespace SepCore.Entity
private void UpdateAttackState(float elapseSeconds) private void UpdateAttackState(float elapseSeconds)
{ {
_currAttackTimer += elapseSeconds;
switch (_attackState) switch (_attackState)
{ {
case AttackStateType.Idle: case AttackStateType.Idle:
@ -151,8 +153,10 @@ namespace SepCore.Entity
return; return;
} }
if (_currAttackTimer >= _attackCooldown) if (_canAttack)
{ {
_canAttack = false;
_attackTimerHandle = GameEntry.Timer.ScheduleOnce(_attackCooldown, () => _canAttack = true, this);
TransitionTo(AttackStateType.Attack); TransitionTo(AttackStateType.Attack);
} }
@ -169,21 +173,15 @@ namespace SepCore.Entity
SetMove(false); SetMove(false);
} }
if (_attackState == AttackStateType.Check_InRange && _currAttackTimer >= _attackCooldown)
{
TransitionTo(AttackStateType.Attack);
return;
}
if (_attackState == AttackStateType.Attack) if (_attackState == AttackStateType.Attack)
{ {
SetMove(false); SetMove(false);
ExecuteAttack(); ExecuteAttack();
_currAttackTimer = 0f;
TransitionTo(AttackStateType.Check_InRange); TransitionTo(AttackStateType.Check_InRange);
} }
} }
private bool HasValidTarget() private bool HasValidTarget()
{ {
if (_target == null) return false; if (_target == null) return false;

View File

@ -3,6 +3,7 @@ using SepCore.AsyncTask;
using SepCore.CustomUtility; using SepCore.CustomUtility;
using SepCore.Definition; using SepCore.Definition;
using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks;
using SepCore.Timer;
using UnityEngine; using UnityEngine;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;
@ -27,7 +28,8 @@ namespace SepCore.Entity
private float _attackRangeSquared; private float _attackRangeSquared;
private float _attackCooldown = 1f; private float _attackCooldown = 1f;
private int _attackDamage = 1; private int _attackDamage = 1;
private float _currAttackTimer; private TimerHandle _attackTimerHandle;
private bool _canAttack;
[SerializeField] private float _projectileSpeed = 12f; [SerializeField] private float _projectileSpeed = 12f;
[SerializeField] private float _projectileLifeTime = 3f; [SerializeField] private float _projectileLifeTime = 3f;
@ -81,7 +83,8 @@ namespace SepCore.Entity
_projectileSpawnHeightOffset); _projectileSpawnHeightOffset);
_projectileAssetName = ReadStringParam(ProjectileAssetNameParamKey, _projectileAssetName); _projectileAssetName = ReadStringParam(ProjectileAssetNameParamKey, _projectileAssetName);
_currAttackTimer = 0f; _canAttack = false;
_attackTimerHandle = GameEntry.Timer.ScheduleOnce(_attackCooldown, () => _canAttack = true, this);
this.CachedTransform.position = enemyData.Position; this.CachedTransform.position = enemyData.Position;
} }
else else
@ -94,8 +97,6 @@ namespace SepCore.Entity
{ {
base.OnUpdate(elapseSeconds, realElapseSeconds); base.OnUpdate(elapseSeconds, realElapseSeconds);
_currAttackTimer += elapseSeconds;
if (_target == null) if (_target == null)
{ {
_movementComponent.SetMove(false); _movementComponent.SetMove(false);
@ -108,7 +109,12 @@ namespace SepCore.Entity
if (distanceSquared <= _attackRangeSquared) if (distanceSquared <= _attackRangeSquared)
{ {
_movementComponent.SetMove(false); _movementComponent.SetMove(false);
TryFireProjectile(); if (_canAttack)
{
TryFireProjectile();
_canAttack = false;
_attackTimerHandle = GameEntry.Timer.ScheduleOnce(_attackCooldown, () => _canAttack = true, this);
}
} }
else else
{ {
@ -121,14 +127,14 @@ namespace SepCore.Entity
{ {
_movementComponent.OnReset(); _movementComponent.OnReset();
_healthComponent.OnReset(); _healthComponent.OnReset();
_currAttackTimer = 0f; GameEntry.Timer.Cancel(_attackTimerHandle);
_attackTimerHandle = TimerHandle.Invalid;
base.OnHide(isShutdown, userData); base.OnHide(isShutdown, userData);
} }
private void TryFireProjectile() private void TryFireProjectile()
{ {
if (_currAttackTimer < _attackCooldown || _target == null) return;
if (!EnsureEnemyProjectileGroup()) return; if (!EnsureEnemyProjectileGroup()) return;
Vector3 spawnPosition = this.CachedTransform.position + Vector3 spawnPosition = this.CachedTransform.position +
@ -165,8 +171,6 @@ namespace SepCore.Entity
EnemyProjectileGroupName, EnemyProjectileGroupName,
Constant.AssetPriority.BulletAsset, Constant.AssetPriority.BulletAsset,
projectileData).Forget(); projectileData).Forget();
_currAttackTimer = 0f;
} }
private static bool EnsureEnemyProjectileGroup() private static bool EnsureEnemyProjectileGroup()

View File

@ -81,7 +81,7 @@ namespace SepCore.Timer
public TimerHandle ScheduleOnce(float delay, Action callback, object owner = null, public TimerHandle ScheduleOnce(float delay, Action callback, object owner = null,
TimerTimeMode timeMode = TimerTimeMode.Scaled) TimerTimeMode timeMode = TimerTimeMode.Scaled)
{ {
return Schedule(new TimerTask(delay, 0f, 1, callback, owner, timeMode)); return Schedule(new TimerTask(delay, delay, 1, callback, owner, timeMode));
} }
/// <summary> /// <summary>