80 lines
2.9 KiB
C#
80 lines
2.9 KiB
C#
using UnityEngine;
|
||
using BaseGames.Core.Events;
|
||
using BaseGames.Core.Save;
|
||
|
||
namespace BaseGames.Core
|
||
{
|
||
/// <summary>
|
||
/// 难度管理器(单例 MonoBehaviour)。
|
||
/// 统一管理当前难度档位,并通过事件频道广播变化。
|
||
/// 订阅者通过 <see cref="CurrentScaler"/> 获取具体缩放数值。
|
||
/// </summary>
|
||
[DefaultExecutionOrder(-900)]
|
||
public class DifficultyManager : MonoBehaviour, ISaveable, IDifficultyService
|
||
{
|
||
[SerializeField] private DifficultyScalerSO[] _allScalers;
|
||
[SerializeField] private DifficultyChangedEventChannel _onDifficultyChanged;
|
||
|
||
public DifficultyLevel CurrentLevel { get; private set; } = DifficultyLevel.Normal;
|
||
public DifficultyScalerSO CurrentScaler { get; private set; }
|
||
|
||
private void Awake()
|
||
{
|
||
if (ServiceLocator.GetOrDefault<IDifficultyService>() != null) { Destroy(gameObject); return; }
|
||
ServiceLocator.Register<IDifficultyService>(this);
|
||
Apply(DifficultyLevel.Normal);
|
||
ServiceLocator.GetOrDefault<ISaveableRegistry>()?.Register(this);
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
ServiceLocator.Unregister<IDifficultyService>(this);
|
||
ServiceLocator.GetOrDefault<ISaveableRegistry>()?.Unregister(this);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在游戏流程中切换难度。
|
||
/// SteelSoul 模式一旦选定,中途无法降级。
|
||
/// </summary>
|
||
public void ChangeDifficulty(DifficultyLevel level)
|
||
{
|
||
if (CurrentLevel == DifficultyLevel.SteelSoul && level != DifficultyLevel.SteelSoul)
|
||
{
|
||
Debug.LogWarning("[DifficultyManager] SteelSoul 模式无法在游戏中途降级。");
|
||
return;
|
||
}
|
||
Apply(level);
|
||
}
|
||
|
||
/// <summary>按档位查找对应的缩放器,未配置时返回 null。</summary>
|
||
public DifficultyScalerSO GetScaler(DifficultyLevel level)
|
||
{
|
||
if (_allScalers == null) return null;
|
||
foreach (var s in _allScalers)
|
||
if (s != null && s.Level == level) return s;
|
||
return null;
|
||
}
|
||
|
||
private void Apply(DifficultyLevel level)
|
||
{
|
||
CurrentLevel = level;
|
||
CurrentScaler = GetScaler(level);
|
||
_onDifficultyChanged?.Raise(CurrentLevel);
|
||
}
|
||
|
||
// ── ISaveable ────────────────────────────────────────────────────────
|
||
|
||
public void OnSave(SaveData saveData)
|
||
{
|
||
if (saveData?.Meta != null)
|
||
saveData.Meta.IsSteelSoul = CurrentLevel == DifficultyLevel.SteelSoul;
|
||
}
|
||
|
||
public void OnLoad(SaveData saveData)
|
||
{
|
||
if (saveData?.Meta != null && saveData.Meta.IsSteelSoul)
|
||
Apply(DifficultyLevel.SteelSoul);
|
||
}
|
||
}
|
||
}
|