CapabilitySystem/Assets/CapabilitySystem/Core/CapabilityComponent.cs
2026-04-15 19:47:09 +08:00

344 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace CapabilitySystem
{
/// <summary>
/// Capability组件挂载到GameObject上管理Capability
/// </summary>
public class CapabilityComponent : MonoBehaviour
{
[SerializeField]
[Tooltip("默认应用的Sheet列表")]
private List<CapabilitySheet> defaultSheets = new List<CapabilitySheet>();
// 所有Capability实例
private List<Capability> capabilities = new List<Capability>();
// Capability引用计数Type -> (Capability, RefCount)
private Dictionary<Type, (Capability capability, int refCount)> capabilityRegistry = new Dictionary<Type, (Capability, int)>();
// 标签阻塞器Tag -> Instigator列表
private Dictionary<CapabilityTag, List<Instigator>> tagBlockers = new Dictionary<CapabilityTag, List<Instigator>>();
// 已应用的Sheet用于运行时管理
private HashSet<CapabilitySheet> appliedSheets = new HashSet<CapabilitySheet>();
// 黑板系统用于Capability间通信
private CapabilityBlackboard blackboard = new CapabilityBlackboard();
// 时间记录器(用于调试和回放)
private TemporalLogger temporalLogger;
#region Unity Lifecycle
private void Awake()
{
// 初始化 TemporalLogger不能在字段初始化器中创建因为会调用 Time.time
temporalLogger = new TemporalLogger();
// 应用默认Sheet
foreach (var sheet in defaultSheets)
{
if (sheet != null)
{
AddSheet(sheet);
}
}
}
private void OnDestroy()
{
// 销毁所有Capability
foreach (var capability in capabilities.ToList())
{
capability.Destroy();
}
capabilities.Clear();
}
#endregion
#region Sheet Management
/// <summary>
/// 添加Sheet
/// </summary>
public void AddSheet(CapabilitySheet sheet)
{
if (sheet == null || appliedSheets.Contains(sheet))
return;
appliedSheets.Add(sheet);
sheet.ApplyToGameObject(gameObject, this);
}
/// <summary>
/// 移除Sheet
/// </summary>
public void RemoveSheet(CapabilitySheet sheet)
{
if (sheet == null || !appliedSheets.Contains(sheet))
return;
appliedSheets.Remove(sheet);
// 移除Sheet创建的Capability通过引用计数
sheet.RemoveFromGameObject(this);
}
#endregion
#region Capability Management
/// <summary>
/// 添加Capability实例内部使用支持引用计数
/// </summary>
internal void AddCapability(Capability capability, bool incrementRefCount = true)
{
if (capability == null)
return;
Type capabilityType = capability.GetType();
// 检查是否已存在
if (capabilityRegistry.ContainsKey(capabilityType))
{
if (incrementRefCount)
{
// 增加引用计数
var entry = capabilityRegistry[capabilityType];
capabilityRegistry[capabilityType] = (entry.capability, entry.refCount + 1);
}
return;
}
// 添加新Capability
capabilities.Add(capability);
capabilityRegistry[capabilityType] = (capability, 1);
}
/// <summary>
/// 移除Capability实例内部使用支持引用计数
/// </summary>
internal void RemoveCapability(Capability capability, bool decrementRefCount = true)
{
if (capability == null)
return;
Type capabilityType = capability.GetType();
if (!capabilityRegistry.ContainsKey(capabilityType))
return;
if (decrementRefCount)
{
var entry = capabilityRegistry[capabilityType];
int newRefCount = entry.refCount - 1;
if (newRefCount > 0)
{
// 还有其他引用,只减少计数
capabilityRegistry[capabilityType] = (entry.capability, newRefCount);
return;
}
}
// 引用计数为0真正移除
capabilities.Remove(capability);
capabilityRegistry.Remove(capabilityType);
capability.Destroy();
}
/// <summary>
/// 运行时添加Capability泛型方法
/// </summary>
public T AddCapability<T>() where T : Capability, new()
{
return AddCapability<T>(null);
}
/// <summary>
/// 运行时添加Capability泛型方法带配置数据
/// </summary>
public T AddCapability<T>(CapabilityData data) where T : Capability, new()
{
Type capabilityType = typeof(T);
// 检查是否已存在
if (capabilityRegistry.ContainsKey(capabilityType))
{
Debug.LogWarning($"[CapabilityComponent] Capability of type {capabilityType.Name} already exists on {gameObject.name}");
return capabilityRegistry[capabilityType].capability as T;
}
// 创建新实例
T capability = new T();
capability.Initialize(gameObject, this, data);
AddCapability(capability, false);
return capability;
}
/// <summary>
/// 运行时移除Capability泛型方法
/// </summary>
public void RemoveCapability<T>() where T : Capability
{
Type capabilityType = typeof(T);
if (capabilityRegistry.TryGetValue(capabilityType, out var entry))
{
RemoveCapability(entry.capability, false);
}
}
/// <summary>
/// 获取Capability泛型方法
/// </summary>
public T GetCapability<T>() where T : Capability
{
Type capabilityType = typeof(T);
if (capabilityRegistry.TryGetValue(capabilityType, out var entry))
{
return entry.capability as T;
}
return null;
}
/// <summary>
/// 检查是否有指定类型的Capability
/// </summary>
public bool HasCapability<T>() where T : Capability
{
return capabilityRegistry.ContainsKey(typeof(T));
}
/// <summary>
/// 检查是否有指定类型的Capability非泛型版本
/// </summary>
public bool HasCapabilityOfType(Type capabilityType)
{
return capabilityRegistry.ContainsKey(capabilityType);
}
/// <summary>
/// 获取所有Capability
/// </summary>
public IReadOnlyList<Capability> GetAllCapabilities()
{
return capabilities.AsReadOnly();
}
/// <summary>
/// 获取黑板系统
/// </summary>
public CapabilityBlackboard Blackboard => blackboard;
/// <summary>
/// 获取时间记录器
/// </summary>
public TemporalLogger TemporalLogger => temporalLogger;
/// <summary>
/// 获取所有Capability的激活历史记录用于调试器
/// </summary>
public List<(Capability capability, CapabilityActivationRecord record)> GetActivationHistory()
{
var allRecords = new List<(Capability capability, CapabilityActivationRecord record)>();
foreach (var capability in capabilities)
{
foreach (var record in capability.ActivationHistory)
{
allRecords.Add((capability: capability, record: record));
}
}
// 按激活时间排序
allRecords.Sort((a, b) => a.record.ActivateTime.CompareTo(b.record.ActivateTime));
return allRecords;
}
#endregion
#region Tag Blocking
/// <summary>
/// 阻塞指定Tag
/// </summary>
public void BlockTag(CapabilityTag tag, Instigator instigator)
{
if (tag == null || instigator == null)
return;
if (!tagBlockers.ContainsKey(tag))
{
tagBlockers[tag] = new List<Instigator>();
}
if (!tagBlockers[tag].Contains(instigator))
{
tagBlockers[tag].Add(instigator);
}
}
/// <summary>
/// 解除阻塞指定Tag
/// </summary>
public void UnblockTag(CapabilityTag tag, Instigator instigator)
{
if (tag == null || instigator == null)
return;
if (tagBlockers.ContainsKey(tag))
{
tagBlockers[tag].Remove(instigator);
// 如果没有阻塞者了,移除字典项
if (tagBlockers[tag].Count == 0)
{
tagBlockers.Remove(tag);
}
}
}
/// <summary>
/// 检查Tag是否被阻塞
/// </summary>
public bool IsTagBlocked(CapabilityTag tag)
{
if (tag == null)
return false;
return tagBlockers.ContainsKey(tag) && tagBlockers[tag].Count > 0;
}
/// <summary>
/// 获取阻塞指定Tag的所有Instigator
/// </summary>
public IReadOnlyList<Instigator> GetTagBlockers(CapabilityTag tag)
{
if (tag == null || !tagBlockers.ContainsKey(tag))
return new List<Instigator>().AsReadOnly();
return tagBlockers[tag].AsReadOnly();
}
/// <summary>
/// 获取所有被阻塞的Tag
/// </summary>
public IEnumerable<CapabilityTag> GetBlockedTags()
{
return tagBlockers.Keys;
}
#endregion
}
}