- Add RoomStreamingManager to manage room loading and unloading based on player proximity. - Create StreamingBudgetConfigSO for memory and performance budgeting of the streaming system. - Introduce TransitionDirector to handle seamless and atmospheric fade transitions between rooms. - Develop WorldGraph to represent room connectivity and facilitate neighbor queries and distance calculations. - Implement RoomNode and RoomEdge classes to structure room data and connections.
96 lines
3.6 KiB
C#
96 lines
3.6 KiB
C#
using UnityEngine;
|
||
using BaseGames.Core;
|
||
using BaseGames.Core.Events;
|
||
|
||
namespace BaseGames.Enemies
|
||
{
|
||
/// <summary>
|
||
/// 敌人运行时数值组件(架构 07_EnemyModule §2)。
|
||
/// 由 EnemyBase.Awake() 通过 Initialize(EnemyStatsSO) 注入配置。
|
||
/// 同时订阅难度变更事件,支持游戏进行中切换难度(架构 19 §5)。
|
||
/// </summary>
|
||
public class EnemyStats : MonoBehaviour
|
||
{
|
||
private EnemyStatsSO _config;
|
||
|
||
[SerializeField] private DifficultyChangedEventChannel _onDifficultyChanged;
|
||
|
||
public int MaxHP { get; private set; }
|
||
public int CurrentHP { get; private set; }
|
||
public int Defense { get; private set; }
|
||
public float AttackCooldownTimer { get; private set; }
|
||
|
||
// ── 移动速度(透传 SO,供 BD 任务运行时读取)────────────────────────
|
||
public float WalkSpeed => _config?.WalkSpeed ?? 2f;
|
||
public float RunSpeed => _config?.RunSpeed ?? 4f;
|
||
|
||
// ── AI 追击配置(透传 SO)──────────────────────────────────────────
|
||
public float MaxChaseDistance => _config?.MaxChaseDistance ?? 15f;
|
||
public float LoseLinkTimeout => _config?.LoseLinkTimeout ?? 2f;
|
||
public float AlertDuration => _config?.AlertDuration ?? 0.6f;
|
||
public float InvestigateDuration => _config?.InvestigateDuration ?? 3f;
|
||
public float HomeRadius => _config?.HomeRadius ?? 0.5f;
|
||
|
||
/// <summary>
|
||
/// 每帧由 EnemyBase 更新(sqrMagnitude,避免 sqrt 开销)。
|
||
/// 使用方请与 range*range 比较,而非直接与 range 比较。
|
||
/// </summary>
|
||
public float SqrDistanceToPlayer { get; set; }
|
||
|
||
private readonly CompositeDisposable _subs = new();
|
||
|
||
private void OnEnable()
|
||
{
|
||
_onDifficultyChanged?.Subscribe(HandleDifficultyChanged).AddTo(_subs);
|
||
}
|
||
|
||
private void OnDisable()
|
||
{
|
||
_subs.Clear();
|
||
}
|
||
|
||
public void Initialize(EnemyStatsSO so)
|
||
{
|
||
_config = so;
|
||
Defense = so.Defense; // Defense 不随难度缩放(架构 19 §5)
|
||
ApplyHPScaler();
|
||
CurrentHP = MaxHP;
|
||
}
|
||
|
||
/// <summary>难度变更时重算 HP(保持 HP 比例,架构 19 §5)。</summary>
|
||
private void HandleDifficultyChanged(DifficultyLevel _)
|
||
{
|
||
if (_config == null) return;
|
||
float hpRatio = MaxHP > 0 ? (float)CurrentHP / MaxHP : 1f;
|
||
ApplyHPScaler();
|
||
CurrentHP = Mathf.Clamp(Mathf.RoundToInt(MaxHP * hpRatio), 1, MaxHP);
|
||
}
|
||
|
||
private void ApplyHPScaler()
|
||
{
|
||
if (_config == null) return;
|
||
var scaler = ServiceLocator.GetOrDefault<IDifficultyService>()?.CurrentScaler;
|
||
int raw = scaler != null
|
||
? Mathf.RoundToInt(_config.MaxHP * scaler.EnemyHPMultiplier)
|
||
: _config.MaxHP;
|
||
MaxHP = Mathf.Max(1, raw); // 防止 MaxHP=0 导致 HP 比例计算 NaN
|
||
}
|
||
|
||
public void TakeDamage(int amount)
|
||
{
|
||
CurrentHP = Mathf.Max(0, CurrentHP - amount);
|
||
}
|
||
|
||
public void TickAttackCooldown(float dt)
|
||
{
|
||
if (AttackCooldownTimer > 0f)
|
||
AttackCooldownTimer -= dt;
|
||
}
|
||
|
||
public void ResetAttackCooldown()
|
||
{
|
||
AttackCooldownTimer = _config.AttackCooldown;
|
||
}
|
||
}
|
||
}
|