提交GAS 打算做一个帧同步的GAS

This commit is contained in:
DESKTOP-5RP3AKU\Jisol
2024-10-18 03:16:09 +08:00
parent b0a2e4a900
commit d9b0c78827
726 changed files with 76601 additions and 0 deletions

View File

@@ -0,0 +1,402 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace GAS.Runtime
{
public class AbilitySystemComponent : MonoBehaviour, IAbilitySystemComponent
{
[SerializeField]
private AbilitySystemComponentPreset preset;
public AbilitySystemComponentPreset Preset => preset;
public int Level { get; protected set; }
public GameplayEffectContainer GameplayEffectContainer { get; private set; }
public GameplayTagAggregator GameplayTagAggregator { get; private set; }
public AbilityContainer AbilityContainer { get; private set; }
public AttributeSetContainer AttributeSetContainer { get; private set; }
public object UserData { get; set; }
private bool _ready;
private void Prepare()
{
if (_ready) return;
AbilityContainer = new AbilityContainer(this);
GameplayEffectContainer = new GameplayEffectContainer(this);
AttributeSetContainer = new AttributeSetContainer(this);
GameplayTagAggregator = new GameplayTagAggregator(this);
_ready = true;
}
public void Enable()
{
AttributeSetContainer.OnEnable();
}
public void Disable()
{
AttributeSetContainer.OnDisable();
DisableAllAbilities();
ClearGameplayEffects();
GameplayTagAggregator?.OnDisable();
}
private void Awake()
{
Prepare();
}
private void OnDestroy()
{
AttributeSetContainer.OnDestroy();
UserData = null;
}
private void OnEnable()
{
Prepare();
GameplayAbilitySystem.GAS.Register(this);
GameplayTagAggregator?.OnEnable();
Enable();
}
private void OnDisable()
{
Disable();
GameplayAbilitySystem.GAS.Unregister(this);
}
public void SetPreset(AbilitySystemComponentPreset ascPreset)
{
preset = ascPreset;
}
public void Init(GameplayTag[] baseTags, Type[] attrSetTypes, AbilityAsset[] baseAbilities, int level)
{
Prepare();
SetLevel(level);
if (baseTags != null) GameplayTagAggregator.Init(baseTags);
if (attrSetTypes != null)
{
foreach (var attrSetType in attrSetTypes)
AttributeSetContainer.AddAttributeSet(attrSetType);
}
if (baseAbilities != null)
{
foreach (var info in baseAbilities)
GrantAbility(info);
}
}
private void GrantAbility(AbilityAsset info)
{
if (info == null)
{
Debug.LogWarning($"[EX] Try To Grant a NULL Ability!");
return;
}
try
{
var ability = Activator.CreateInstance(info.AbilityType(), args: info) as AbstractAbility;
AbilityContainer.GrantAbility(ability);
}
#pragma warning disable CS0168 // 声明了变量,但从未使用过
catch (MissingMethodException e)
#pragma warning restore CS0168 // 声明了变量,但从未使用过
{
// 踩坑日志:
// 复制了某个AbilityAsset实现类的代码但忘记更新AbilityType()方法的返回值。
// 一般来说AbilityAsset和Ability应该是配套的, 比如在"GAA_xxx"中返回"GA_xxx"的类型.
Debug.LogError($"[EX] 创建能力失败: " +
$"请检查AbilityAsset实现类'{info.GetType().FullName}'中的AbilityType()方法" +
$"是否正确返回了能力类型(当前为'{info.AbilityType()?.FullName ?? "null"}')。");
throw;
}
}
public void SetLevel(int level)
{
Level = level;
}
public bool HasTag(in GameplayTag gameplayTag)
{
return GameplayTagAggregator.HasTag(gameplayTag);
}
public bool HasAllTags(in GameplayTagSet tags)
{
return GameplayTagAggregator.HasAllTags(tags);
}
public bool HasAnyTags(in GameplayTagSet tags)
{
return GameplayTagAggregator.HasAnyTags(tags);
}
public void AddFixedTags(in GameplayTagSet tags)
{
GameplayTagAggregator.AddFixedTag(tags);
}
public void RemoveFixedTags(in GameplayTagSet tags)
{
GameplayTagAggregator.RemoveFixedTag(tags);
}
public void AddFixedTag(in GameplayTag gameplayTag)
{
GameplayTagAggregator.AddFixedTag(gameplayTag);
}
public void RemoveFixedTag(in GameplayTag gameplayTag)
{
GameplayTagAggregator.RemoveFixedTag(gameplayTag);
}
public void RemoveGameplayEffect(GameplayEffectSpec spec)
{
GameplayEffectContainer.RemoveGameplayEffectSpec(spec);
}
public void RemoveGameplayEffect(in EntityRef<GameplayEffectSpec> spec)
{
GameplayEffectContainer.RemoveGameplayEffectSpec(spec);
}
public void RemoveGameplayEffectWithAnyTags(in GameplayTagSet tags)
{
GameplayEffectContainer.RemoveGameplayEffectWithAnyTags(tags);
}
public EntityRef<GameplayEffectSpec> ApplyGameplayEffectTo(GameplayEffectSpec gameplayEffectSpec, AbilitySystemComponent target)
{
return target.AddGameplayEffect(this, gameplayEffectSpec);
}
public EntityRef<GameplayEffectSpec> ApplyGameplayEffectTo(in EntityRef<GameplayEffectSpec> gameplayEffectSpecRef, AbilitySystemComponent target)
{
var gameplayEffectSpec = gameplayEffectSpecRef.Value;
if (gameplayEffectSpec == null)
{
#if UNITY_EDITOR
Debug.LogError($"[EX] Try To Apply a invalid EntityRef of GameplayEffectSpec From {name} To {target.name}!");
#endif
return null;
}
return target.AddGameplayEffect(this, gameplayEffectSpec);
}
public EntityRef<GameplayEffectSpec> ApplyGameplayEffectTo(GameplayEffect gameplayEffect, AbilitySystemComponent target)
{
if (gameplayEffect == null)
{
#if UNITY_EDITOR
Debug.LogError($"[EX] Try To Apply a NULL GameplayEffect From {name} To {target.name}!");
#endif
return null;
}
var spec = gameplayEffect.CreateSpec();
return ApplyGameplayEffectTo(spec, target);
}
public EntityRef<GameplayEffectSpec> ApplyGameplayEffectTo(GameplayEffect gameplayEffect, AbilitySystemComponent target, int effectLevel)
{
if (gameplayEffect == null)
{
#if UNITY_EDITOR
Debug.LogError($"[EX] Try To Apply a NULL GameplayEffect From {name} To {target.name}!");
#endif
return null;
}
var spec = gameplayEffect.CreateSpec();
spec.Value.SetLevel(effectLevel);
return ApplyGameplayEffectTo(spec, target);
}
public EntityRef<GameplayEffectSpec> ApplyGameplayEffectToSelf(GameplayEffectSpec gameplayEffectSpec)
{
return ApplyGameplayEffectTo(gameplayEffectSpec, this);
}
public EntityRef<GameplayEffectSpec> ApplyGameplayEffectToSelf(GameplayEffect gameplayEffect)
{
return ApplyGameplayEffectTo(gameplayEffect, this);
}
public void RemoveGameplayEffectSpec(GameplayEffectSpec gameplayEffectSpec)
{
GameplayEffectContainer.RemoveGameplayEffectSpec(gameplayEffectSpec);
}
public void RemoveGameplayEffectSpec(in EntityRef<GameplayEffectSpec> gameplayEffectSpecRef)
{
GameplayEffectContainer.RemoveGameplayEffectSpec(gameplayEffectSpecRef);
}
public AbilitySpec GrantAbility(AbstractAbility ability)
{
AbilityContainer.GrantAbility(ability);
return AbilityContainer.AbilitySpecs()[ability.Name];
}
public void RemoveAbility(string abilityName)
{
AbilityContainer.RemoveAbility(abilityName);
}
public AttributeValue? GetAttributeAttributeValue(string attrSetName, string attrShortName)
{
var value = AttributeSetContainer.GetAttributeAttributeValue(attrSetName, attrShortName);
return value;
}
public CalculateMode? GetAttributeCalculateMode(string attrSetName, string attrShortName)
{
var value = AttributeSetContainer.GetAttributeCalculateMode(attrSetName, attrShortName);
return value;
}
public float? GetAttributeCurrentValue(string setName, string attributeShortName)
{
var value = AttributeSetContainer.GetAttributeCurrentValue(setName, attributeShortName);
return value;
}
public float? GetAttributeBaseValue(string setName, string attributeShortName)
{
var value = AttributeSetContainer.GetAttributeBaseValue(setName, attributeShortName);
return value;
}
public void Tick()
{
AbilityContainer.Tick();
GameplayEffectContainer.Tick();
}
public Dictionary<string, float> DataSnapshot()
{
return AttributeSetContainer.Snapshot();
}
public bool TryActivateAbility(string abilityName, object arg = null)
{
return AbilityContainer.TryActivateAbility(abilityName, arg, null);
}
internal bool TryActivateAbility(string abilityName, GameplayEffectSpec gameplayEffectSpec)
{
return AbilityContainer.TryActivateAbility(abilityName, null, gameplayEffectSpec);
}
public void TryEndAbility(string abilityName)
{
AbilityContainer.EndAbility(abilityName);
}
public void TryCancelAbility(string abilityName)
{
AbilityContainer.CancelAbility(abilityName);
}
public void ApplyModFromInstantGameplayEffect(GameplayEffectSpec spec)
{
foreach (var modifier in spec.Modifiers)
{
var attributeValue = GetAttributeAttributeValue(modifier.AttributeSetName, modifier.AttributeShortName);
if (attributeValue == null) continue;
if (attributeValue.Value.IsSupportOperation(modifier.Operation) == false)
{
throw new InvalidOperationException("Unsupported operation.");
}
if (attributeValue.Value.CalculateMode != CalculateMode.Stacking)
{
throw new InvalidOperationException(
$"[EX] Instant GameplayEffect Can Only Modify Stacking Mode Attribute! " +
$"But {modifier.AttributeSetName}.{modifier.AttributeShortName} is {attributeValue.Value.CalculateMode}");
}
var magnitude = modifier.CalculateMagnitude(spec, modifier.ModiferMagnitude);
var baseValue = attributeValue.Value.BaseValue;
switch (modifier.Operation)
{
case GEOperation.Add:
baseValue += magnitude;
break;
case GEOperation.Minus:
baseValue -= magnitude;
break;
case GEOperation.Multiply:
baseValue *= magnitude;
break;
case GEOperation.Divide:
baseValue /= magnitude;
break;
case GEOperation.Override:
baseValue = magnitude;
break;
default:
throw new ArgumentOutOfRangeException();
}
AttributeSetContainer.Sets[modifier.AttributeSetName]
.ChangeAttributeBase(modifier.AttributeShortName, baseValue);
}
}
public CooldownTimer CheckCooldownFromTags(in GameplayTagSet tags)
{
return GameplayEffectContainer.CheckCooldownFromTags(tags);
}
public T AttrSet<T>() where T : AttributeSet
{
AttributeSetContainer.TryGetAttributeSet<T>(out var attrSet);
return attrSet;
}
public void ClearGameplayEffect()
{
// _abilityContainer = new AbilityContainer(this);
// GameplayEffectContainer = new GameplayEffectContainer(this);
// _attributeSetContainer = new AttributeSetContainer(this);
// tagAggregator = new GameplayTagAggregator(this);
GameplayEffectContainer.ClearGameplayEffect();
}
private EntityRef<GameplayEffectSpec> AddGameplayEffect(AbilitySystemComponent source, GameplayEffectSpec effectSpec)
{
return GameplayEffectContainer.AddGameplayEffectSpec(source, effectSpec);
}
private EntityRef<GameplayEffectSpec> AddGameplayEffect(AbilitySystemComponent source, GameplayEffectSpec effectSpec, int effectLevel)
{
return GameplayEffectContainer.AddGameplayEffectSpec(source, effectSpec, true, effectLevel);
}
private void DisableAllAbilities()
{
AbilityContainer.CancelAllAbilities();
}
private void ClearGameplayEffects()
{
GameplayEffectContainer.ClearGameplayEffect();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 183fdb9275244e99bf882bd2e9cb85d5
timeCreated: 1701941555

View File

@@ -0,0 +1,53 @@
using System.Linq;
using GAS.General;
using Sirenix.OdinInspector;
using UnityEngine;
namespace GAS.Runtime
{
[CreateAssetMenu(fileName = "AbilitySystemComponentPreset", menuName = "GAS/AbilitySystemComponentPreset")]
public class AbilitySystemComponentPreset : ScriptableObject
{
private const int WIDTH_LABEL = 70;
[TitleGroup("Base")]
[HorizontalGroup("Base/H1", Width = 1 - 0.618f)]
[TabGroup("Base/H1/V1", "Summary", SdfIconType.InfoSquareFill, TextColor = "#0BFFC5", Order = 1)]
[HideLabel]
[MultiLineProperty(10)]
public string Description;
[TabGroup("Base/H1/V2", "Attribute Sets", SdfIconType.PersonLinesFill, TextColor = "#FF7F00", Order = 2)]
[LabelText(GASTextDefine.ASC_AttributeSet)]
[LabelWidth(WIDTH_LABEL)]
[ValueDropdown("@ValueDropdownHelper.AttributeSetChoices", IsUniqueList = true)]
[ListDrawerSettings(ShowFoldout = true, ShowItemCount = false, DraggableItems = false)]
[DisableContextMenu(disableForMember: false, disableCollectionElements: true)]
[CustomContextMenu("排序", "@SortAttributeSets()")]
public string[] AttributeSets;
private void SortAttributeSets() => AttributeSets = AttributeSets.OrderBy(x => x).ToArray();
[HorizontalGroup("Base/H2", Width = 1 - 0.618f)]
[TabGroup("Base/H2/V1", "Tags", SdfIconType.TagsFill, TextColor = "#45B1FF", Order = 1)]
[LabelText(GASTextDefine.ASC_BASE_TAG)]
[ValueDropdown("@ValueDropdownHelper.GameplayTagChoices", IsUniqueList = true, HideChildProperties = true)]
[ListDrawerSettings(ShowFoldout = true, ShowItemCount = false, DraggableItems = false)]
[DisableContextMenu(disableForMember: false, disableCollectionElements: true)]
[CustomContextMenu("排序", "@BaseTags = TagHelper.Sort($value)")]
public GameplayTag[] BaseTags;
[TabGroup("Base/H2/V2", "Abilities", SdfIconType.YinYang, TextColor = "#D6626E", Order = 2)]
[LabelText(GASTextDefine.ASC_BASE_ABILITY)]
[ListDrawerSettings(ShowFoldout = true, ShowItemCount = false, DraggableItems = false)]
[DisableContextMenu(disableForMember: false, disableCollectionElements: true)]
[CustomContextMenu("排序", "@SortBaseAbilities()")]
[AssetSelector]
[ValidateInput("@ValidateInput_BaseAbilities()", "存在无效的能力")]
public AbilityAsset[] BaseAbilities;
private void SortBaseAbilities() => BaseAbilities = BaseAbilities.OrderBy(x => x.name).ToArray();
bool ValidateInput_BaseAbilities() => BaseAbilities != null && BaseAbilities.All(ability => ability != null);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 85dd2a6201f04545b5a8b020edcb2690
timeCreated: 1703831206

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
namespace GAS.Runtime
{
public interface IAbilitySystemComponent
{
void SetPreset(AbilitySystemComponentPreset ascPreset);
void Init(GameplayTag[] baseTags, Type[] attrSetTypes, AbilityAsset[] baseAbilities, int level);
void SetLevel(int level);
bool HasTag(in GameplayTag tag);
bool HasAllTags(in GameplayTagSet tags);
bool HasAnyTags(in GameplayTagSet tags);
void AddFixedTags(in GameplayTagSet tags);
void AddFixedTag(in GameplayTag gameplayTag);
void RemoveFixedTags(in GameplayTagSet tags);
void RemoveFixedTag(in GameplayTag gameplayTag);
EntityRef<GameplayEffectSpec> ApplyGameplayEffectTo(GameplayEffect gameplayEffect, AbilitySystemComponent target);
EntityRef<GameplayEffectSpec> ApplyGameplayEffectToSelf(GameplayEffect gameplayEffect);
void ApplyModFromInstantGameplayEffect(GameplayEffectSpec spec);
void RemoveGameplayEffect(GameplayEffectSpec spec);
void Tick();
Dictionary<string, float> DataSnapshot();
AbilitySpec GrantAbility(AbstractAbility ability);
void RemoveAbility(string abilityName);
float? GetAttributeCurrentValue(string setName, string attributeShortName);
float? GetAttributeBaseValue(string setName, string attributeShortName);
bool TryActivateAbility(string abilityName, object arg = null);
void TryEndAbility(string abilityName);
CooldownTimer CheckCooldownFromTags(in GameplayTagSet tags);
T AttrSet<T>() where T : AttributeSet;
void ClearGameplayEffect();
public object UserData { get; set; }
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f87bef00028d4db28c8c66dd5b24d412
timeCreated: 1701941525