411 lines
10 KiB
Markdown
411 lines
10 KiB
Markdown
|
|
# 战斗系统优化建议
|
|||
|
|
|
|||
|
|
## 1. 状态管理优化
|
|||
|
|
|
|||
|
|
### 1.1 当前实现
|
|||
|
|
```csharp
|
|||
|
|
// LevelStateBattle.cs 中的状态管理
|
|||
|
|
public class LevelStateBattle : BaseLevelState
|
|||
|
|
{
|
|||
|
|
private bool _canUpdate;
|
|||
|
|
private bool _oldPauseStatus;
|
|||
|
|
|
|||
|
|
protected override void _OnRunning()
|
|||
|
|
{
|
|||
|
|
base._OnRunning();
|
|||
|
|
|
|||
|
|
PauseManager.instance.LogicUpdate(deltaTime);
|
|||
|
|
SkillManager.instance.LogicUpdate(deltaTime);
|
|||
|
|
if (AreaManager.instance.isInSkillPreview) return;
|
|||
|
|
|
|||
|
|
_level.LevelTime += deltaTime;
|
|||
|
|
BulletManager.instance.LogicUpdate(deltaTime);
|
|||
|
|
GameUnitManager.instance.LogicUpdate(deltaTime);
|
|||
|
|
BuffManager.instance.LogicUpdate(deltaTime);
|
|||
|
|
ExtLogicManager.instance.LogicUpdate(deltaTime);
|
|||
|
|
AreaManager.instance.LogicUpdate(deltaTime);
|
|||
|
|
// ...其他更新
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 1.2 优化建议
|
|||
|
|
1. 优化状态管理和更新逻辑:
|
|||
|
|
```csharp
|
|||
|
|
public class LevelStateBattle : BaseLevelState
|
|||
|
|
{
|
|||
|
|
// 将更新逻辑分组
|
|||
|
|
private readonly List<ILogicUpdate> _basicUpdaters = new();
|
|||
|
|
private readonly List<ILogicUpdate> _battleUpdaters = new();
|
|||
|
|
|
|||
|
|
private void InitializeUpdaters()
|
|||
|
|
{
|
|||
|
|
// 基础更新组(无条件更新)
|
|||
|
|
_basicUpdaters.Add(PauseManager.instance);
|
|||
|
|
_basicUpdaters.Add(SkillManager.instance);
|
|||
|
|
|
|||
|
|
// 战斗更新组(非技能预览时更新)
|
|||
|
|
_battleUpdaters.Add(BulletManager.instance);
|
|||
|
|
_battleUpdaters.Add(GameUnitManager.instance);
|
|||
|
|
_battleUpdaters.Add(BuffManager.instance);
|
|||
|
|
_battleUpdaters.Add(AreaManager.instance);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override void _OnRunning()
|
|||
|
|
{
|
|||
|
|
base._OnRunning();
|
|||
|
|
|
|||
|
|
// 更新基础系统
|
|||
|
|
foreach (var updater in _basicUpdaters)
|
|||
|
|
{
|
|||
|
|
updater.LogicUpdate(deltaTime);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 技能预览时不更新战斗
|
|||
|
|
if (AreaManager.instance.isInSkillPreview)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
// 更新战斗系统
|
|||
|
|
foreach (var updater in _battleUpdaters)
|
|||
|
|
{
|
|||
|
|
updater.LogicUpdate(deltaTime);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新战斗时间和剧情
|
|||
|
|
UpdateBattleTime();
|
|||
|
|
UpdateStory();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public class LevelStateBattle : BaseLevelState
|
|||
|
|
{
|
|||
|
|
private BattlePhase _currentPhase;
|
|||
|
|
private Dictionary<BattlePhase, Action<float>> _phaseUpdaters;
|
|||
|
|
|
|||
|
|
private void InitializePhaseUpdaters()
|
|||
|
|
{
|
|||
|
|
_phaseUpdaters = new Dictionary<BattlePhase, Action<float>>
|
|||
|
|
{
|
|||
|
|
{ BattlePhase.Preparation, UpdatePreparationPhase },
|
|||
|
|
{ BattlePhase.UnitMovement, UpdateMovementPhase },
|
|||
|
|
{ BattlePhase.SkillExecution, UpdateSkillPhase },
|
|||
|
|
{ BattlePhase.PostProcess, UpdatePostProcessPhase }
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override void _OnRunning()
|
|||
|
|
{
|
|||
|
|
if (_phaseUpdaters.TryGetValue(_currentPhase, out var updater))
|
|||
|
|
{
|
|||
|
|
updater(deltaTime);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 2. 事件系统优化
|
|||
|
|
|
|||
|
|
### 2.1 当前实现存在的问题
|
|||
|
|
1. 事件注册和注销分散
|
|||
|
|
2. 事件名称字符串容易写错
|
|||
|
|
3. 缺乏事件参数类型安全检查
|
|||
|
|
|
|||
|
|
### 2.2 优化建议
|
|||
|
|
1. 实现类型安全的事件系统:
|
|||
|
|
```csharp
|
|||
|
|
public class BattleEventSystem
|
|||
|
|
{
|
|||
|
|
private readonly Dictionary<Type, Delegate> _eventHandlers = new();
|
|||
|
|
|
|||
|
|
public void Register<TEvent>(Action<TEvent> handler)
|
|||
|
|
where TEvent : IBattleEvent
|
|||
|
|
{
|
|||
|
|
var type = typeof(TEvent);
|
|||
|
|
if (_eventHandlers.TryGetValue(type, out var existing))
|
|||
|
|
{
|
|||
|
|
_eventHandlers[type] = Delegate.Combine(existing, handler);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
_eventHandlers[type] = handler;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void Send<TEvent>(TEvent eventData) where TEvent : IBattleEvent
|
|||
|
|
{
|
|||
|
|
if (_eventHandlers.TryGetValue(typeof(TEvent), out var handler))
|
|||
|
|
{
|
|||
|
|
((Action<TEvent>)handler)(eventData);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void UpdateUnit(GameUnit unit)
|
|||
|
|
{
|
|||
|
|
var gridPos = WorldToGrid(unit.transform.position);
|
|||
|
|
// 更新单位所在网格
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public List<GameUnit> GetUnitsInRange(Vector3 position, float radius)
|
|||
|
|
{
|
|||
|
|
var result = new List<GameUnit>();
|
|||
|
|
var gridPos = WorldToGrid(position);
|
|||
|
|
// 返回范围内的单位
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. 优化单位更新逻辑:
|
|||
|
|
```csharp
|
|||
|
|
public class GameUnitManager
|
|||
|
|
{
|
|||
|
|
private SpatialHashGrid _spatialGrid;
|
|||
|
|
|
|||
|
|
public void LogicUpdate(float dt)
|
|||
|
|
{
|
|||
|
|
// 使用Job System进行并行更新
|
|||
|
|
var unitUpdateJob = new UnitUpdateJob
|
|||
|
|
{
|
|||
|
|
deltaTime = dt,
|
|||
|
|
units = infightUnits.ToNativeArray()
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 执行Job
|
|||
|
|
var handle = unitUpdateJob.Schedule(infightUnits.count, 64);
|
|||
|
|
handle.Complete();
|
|||
|
|
|
|||
|
|
// 更新空间网格
|
|||
|
|
foreach (var unit in infightUnits)
|
|||
|
|
{
|
|||
|
|
_spatialGrid.UpdateUnit(unit);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 3. 交互系统优化
|
|||
|
|
|
|||
|
|
### 3.1 当前问题
|
|||
|
|
- 点击处理逻辑分散在多处
|
|||
|
|
- 状态判断条件复杂
|
|||
|
|
- 缺乏统一的输入管理
|
|||
|
|
|
|||
|
|
### 3.2 优化建议
|
|||
|
|
1. 分离技能效果和表现:
|
|||
|
|
```csharp
|
|||
|
|
public abstract class SkillEffect
|
|||
|
|
{
|
|||
|
|
public abstract void Apply(GameUnit caster, GameUnit target);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public class DamageEffect : SkillEffect
|
|||
|
|
{
|
|||
|
|
public float damageAmount;
|
|||
|
|
|
|||
|
|
public override void Apply(GameUnit caster, GameUnit target)
|
|||
|
|
{
|
|||
|
|
var finalDamage = CalculateDamage(caster, target, damageAmount);
|
|||
|
|
target.TakeDamage(finalDamage);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public class Skill
|
|||
|
|
{
|
|||
|
|
private List<SkillEffect> _effects;
|
|||
|
|
private SkillVisual _visual;
|
|||
|
|
|
|||
|
|
public async UniTask Execute(GameUnit caster, GameUnit target)
|
|||
|
|
{
|
|||
|
|
// 播放技能表现
|
|||
|
|
await _visual.PlayAsync();
|
|||
|
|
|
|||
|
|
// 应用技能效果
|
|||
|
|
foreach (var effect in _effects)
|
|||
|
|
{
|
|||
|
|
effect.Apply(caster, target);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. 使用对象池优化技能特效:
|
|||
|
|
```csharp
|
|||
|
|
public class SkillEffectPool : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
private Dictionary<string, Queue<GameObject>> _effectPools;
|
|||
|
|
|
|||
|
|
public GameObject Get(string effectId)
|
|||
|
|
{
|
|||
|
|
if (!_effectPools.ContainsKey(effectId))
|
|||
|
|
{
|
|||
|
|
CreatePool(effectId);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var pool = _effectPools[effectId];
|
|||
|
|
if (pool.Count > 0)
|
|||
|
|
{
|
|||
|
|
var effect = pool.Dequeue();
|
|||
|
|
effect.SetActive(true);
|
|||
|
|
return effect;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return CreateNewEffect(effectId);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void Return(string effectId, GameObject effect)
|
|||
|
|
{
|
|||
|
|
effect.SetActive(false);
|
|||
|
|
_effectPools[effectId].Enqueue(effect);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 4. 性能优化建议
|
|||
|
|
|
|||
|
|
### 4.1 批处理渲染
|
|||
|
|
对于相同材质的单位模型,使用GPU Instancing:
|
|||
|
|
```csharp
|
|||
|
|
public class UnitRenderer : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
private static MaterialPropertyBlock _propertyBlock;
|
|||
|
|
private static List<UnitRenderer> _instances = new List<UnitRenderer>();
|
|||
|
|
|
|||
|
|
private void OnEnable()
|
|||
|
|
{
|
|||
|
|
_instances.Add(this);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void OnDisable()
|
|||
|
|
{
|
|||
|
|
_instances.Remove(this);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static void UpdateAllInstances()
|
|||
|
|
{
|
|||
|
|
// 使用GPU Instancing进行批量渲染
|
|||
|
|
if (_propertyBlock == null)
|
|||
|
|
_propertyBlock = new MaterialPropertyBlock();
|
|||
|
|
|
|||
|
|
foreach (var instance in _instances)
|
|||
|
|
{
|
|||
|
|
// 更新材质属性
|
|||
|
|
instance.UpdateProperties(_propertyBlock);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.2 区域计算优化
|
|||
|
|
使用Job System优化区域计算:
|
|||
|
|
```csharp
|
|||
|
|
public struct AreaCalculationJob : IJobParallelFor
|
|||
|
|
{
|
|||
|
|
[ReadOnly] public NativeArray<int> CenterCells;
|
|||
|
|
[ReadOnly] public int Range;
|
|||
|
|
public NativeArray<bool> Results;
|
|||
|
|
|
|||
|
|
public void Execute(int index)
|
|||
|
|
{
|
|||
|
|
var centerCell = CenterCells[index];
|
|||
|
|
// 计算范围内的格子
|
|||
|
|
Results[index] = CalculateArea(centerCell, Range);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public class AreaManager
|
|||
|
|
{
|
|||
|
|
public void CalculateAreas(List<int> centerCells, int range)
|
|||
|
|
{
|
|||
|
|
var job = new AreaCalculationJob
|
|||
|
|
{
|
|||
|
|
CenterCells = new NativeArray<int>(centerCells.ToArray(), Allocator.TempJob),
|
|||
|
|
Range = range,
|
|||
|
|
Results = new NativeArray<bool>(centerCells.Count, Allocator.TempJob)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 执行Job
|
|||
|
|
var handle = job.Schedule(centerCells.Count, 64);
|
|||
|
|
handle.Complete();
|
|||
|
|
|
|||
|
|
// 使用结果
|
|||
|
|
ProcessResults(job.Results);
|
|||
|
|
|
|||
|
|
// 释放资源
|
|||
|
|
job.CenterCells.Dispose();
|
|||
|
|
job.Results.Dispose();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 5. 数据管理优化
|
|||
|
|
|
|||
|
|
### 5.1 配置数据加载
|
|||
|
|
使用ScriptableObject优化配置数据:
|
|||
|
|
```csharp
|
|||
|
|
[CreateAssetMenu(fileName = "UnitConfig", menuName = "Battle/UnitConfig")]
|
|||
|
|
public class UnitConfig : ScriptableObject
|
|||
|
|
{
|
|||
|
|
public List<UnitData> unitDataList;
|
|||
|
|
|
|||
|
|
// 使用字典缓存数据
|
|||
|
|
private Dictionary<int, UnitData> _unitDataCache;
|
|||
|
|
|
|||
|
|
public UnitData GetUnitData(int id)
|
|||
|
|
{
|
|||
|
|
if (_unitDataCache == null)
|
|||
|
|
{
|
|||
|
|
_unitDataCache = unitDataList.ToDictionary(data => data.id);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return _unitDataCache.TryGetValue(id, out var data) ? data : null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.2 运行时数据管理
|
|||
|
|
使用对象池和组件池优化内存:
|
|||
|
|
```csharp
|
|||
|
|
public class ComponentPool<T> where T : Component
|
|||
|
|
{
|
|||
|
|
private Queue<T> _pool;
|
|||
|
|
private T _prefab;
|
|||
|
|
private Transform _parent;
|
|||
|
|
|
|||
|
|
public T Get()
|
|||
|
|
{
|
|||
|
|
if (_pool.Count > 0)
|
|||
|
|
{
|
|||
|
|
var component = _pool.Dequeue();
|
|||
|
|
component.gameObject.SetActive(true);
|
|||
|
|
return component;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return GameObject.Instantiate(_prefab, _parent);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void Return(T component)
|
|||
|
|
{
|
|||
|
|
component.gameObject.SetActive(false);
|
|||
|
|
_pool.Enqueue(component);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 6. 后续优化方向
|
|||
|
|
|
|||
|
|
1. 战斗逻辑
|
|||
|
|
- 实现更细粒度的状态管理
|
|||
|
|
- 优化单位间的交互逻辑
|
|||
|
|
- 增加战斗回放功能
|
|||
|
|
|
|||
|
|
2. 性能优化
|
|||
|
|
- 使用ECS重构部分热点逻辑
|
|||
|
|
- 优化寻路算法
|
|||
|
|
- 实现LOD系统
|
|||
|
|
|
|||
|
|
3. 内存优化
|
|||
|
|
- 实现资源预加载策略
|
|||
|
|
- 优化对象池系统
|
|||
|
|
- 增加内存监控工具
|