mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-09-27 10:46:17 +00:00
提交GAS 打算做一个帧同步的GAS
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// 基于属性混合GE堆栈的MMC
|
||||
/// </summary>
|
||||
[CreateAssetMenu(fileName = "AttrBasedWithStackModCalculation", menuName = "GAS/MMC/AttrBasedWithStackModCalculation")]
|
||||
public class AttrBasedWithStackModCalculation:AttributeBasedModCalculation
|
||||
{
|
||||
public enum StackMagnitudeOperation
|
||||
{
|
||||
Add,
|
||||
Multiply
|
||||
}
|
||||
|
||||
[InfoBox(" 公式:StackCount * sK + sB")]
|
||||
[TabGroup("Default", "AttributeBasedModCalculation")]
|
||||
[Title("堆叠幅值计算")]
|
||||
[LabelText("系数(sK)")]
|
||||
public float sK = 1;
|
||||
|
||||
[TabGroup("Default", "AttributeBasedModCalculation")]
|
||||
[LabelText("常量(sB)")]
|
||||
public float sB = 0;
|
||||
|
||||
[TabGroup("Default", "AttributeBasedModCalculation")]
|
||||
[Title("最终结果")]
|
||||
[InfoBox(" 最终公式: \n" +
|
||||
"Add:(AttributeValue * k + b)+(StackCount * sK + sB); \n" +
|
||||
"Multiply:(AttributeValue * k + b)*(StackCount * sK + sB)")]
|
||||
[LabelText("Stack幅值与Attr幅值计算方式")]
|
||||
public StackMagnitudeOperation stackMagnitudeOperation;
|
||||
|
||||
[TabGroup("Default", "AttributeBasedModCalculation")]
|
||||
[LabelText("最终公式")]
|
||||
[ShowInInspector]
|
||||
[DisplayAsString(TextAlignment.Left, true)]
|
||||
public string FinalFormulae
|
||||
{
|
||||
get
|
||||
{
|
||||
var formulae = stackMagnitudeOperation switch
|
||||
{
|
||||
StackMagnitudeOperation.Add => $"({attributeName} * {k} + {b}) + (StackCount * {sK} + {sB})",
|
||||
StackMagnitudeOperation.Multiply => $"({attributeName} * {k} + {b}) * (StackCount * {sK} + {sB})",
|
||||
_ => ""
|
||||
};
|
||||
|
||||
return $"<size=15><b><color=green>{formulae}</color></b></size>";
|
||||
}
|
||||
}
|
||||
|
||||
public override float CalculateMagnitude(GameplayEffectSpec spec, float modifierMagnitude)
|
||||
{
|
||||
var attrMagnitude = base.CalculateMagnitude(spec, modifierMagnitude);
|
||||
|
||||
if (spec.Stacking.stackingType == StackingType.None) return attrMagnitude;
|
||||
|
||||
var stackMagnitude = spec.StackCount * sK + sB;
|
||||
|
||||
return stackMagnitudeOperation switch
|
||||
{
|
||||
StackMagnitudeOperation.Add => attrMagnitude + stackMagnitude,
|
||||
StackMagnitudeOperation.Multiply => attrMagnitude * stackMagnitude,
|
||||
_ => attrMagnitude + stackMagnitude
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8a883d343584d7d9b8a711cf045ca84
|
||||
timeCreated: 1717082065
|
@@ -0,0 +1,135 @@
|
||||
using System.Linq;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
[CreateAssetMenu(fileName = "AttributeBasedModCalculation", menuName = "GAS/MMC/AttributeBasedModCalculation")]
|
||||
public class AttributeBasedModCalculation : ModifierMagnitudeCalculation
|
||||
{
|
||||
public enum AttributeFrom
|
||||
{
|
||||
[LabelText("来源(Source)", SdfIconType.Magic)]
|
||||
Source,
|
||||
|
||||
[LabelText("目标(Target)", SdfIconType.Person)]
|
||||
Target
|
||||
}
|
||||
|
||||
public enum GEAttributeCaptureType
|
||||
{
|
||||
[LabelText("快照(SnapShot)", SdfIconType.Camera)]
|
||||
SnapShot,
|
||||
|
||||
[LabelText("实时(Track)", SdfIconType.Speedometer2)]
|
||||
Track
|
||||
}
|
||||
|
||||
[TabGroup("Default", "AttributeBasedModCalculation", SdfIconType.PersonBoundingBox, TextColor = "blue")]
|
||||
[InfoBox(" 以什么方式(Capture Type)从谁身上(Attribute From)捕获哪个属性的值(Attribute Name)。")]
|
||||
[EnumToggleButtons]
|
||||
[LabelText("捕获方式(Capture Type)")]
|
||||
public GEAttributeCaptureType captureType;
|
||||
|
||||
[TabGroup("Default", "AttributeBasedModCalculation")]
|
||||
[EnumToggleButtons]
|
||||
[LabelText("捕获目标(Attribute From)")]
|
||||
public AttributeFrom attributeFromType;
|
||||
|
||||
[TabGroup("Default", "AttributeBasedModCalculation")]
|
||||
[ValueDropdown("@ValueDropdownHelper.AttributeChoices", IsUniqueList = true)]
|
||||
[LabelText("属性的名称(Attribute Name)")]
|
||||
[OnValueChanged("@OnAttributeNameChanged()")]
|
||||
[ValidateInput("@AttributeValidator.IsValidAttributeName($value)", "属性名无效")]
|
||||
public string attributeName;
|
||||
|
||||
[TabGroup("Default", "Details", SdfIconType.Bug, TextColor = "orange")]
|
||||
[ReadOnly]
|
||||
public string attributeSetName;
|
||||
|
||||
[TabGroup("Default", "Details")]
|
||||
[ReadOnly]
|
||||
public string attributeShortName;
|
||||
|
||||
[InfoBox("计算逻辑与ScalableFloatModCalculation一致, 公式:AttributeValue * k + b")]
|
||||
[TabGroup("Default", "AttributeBasedModCalculation")]
|
||||
[LabelText("系数(k)")]
|
||||
public float k = 1;
|
||||
|
||||
[TabGroup("Default", "AttributeBasedModCalculation")]
|
||||
[LabelText("常量(b)")]
|
||||
public float b = 0;
|
||||
|
||||
public override float CalculateMagnitude(GameplayEffectSpec spec, float modifierMagnitude)
|
||||
{
|
||||
float attributeValue;
|
||||
if (attributeFromType == AttributeFrom.Source)
|
||||
{
|
||||
if (captureType == GEAttributeCaptureType.SnapShot)
|
||||
{
|
||||
var snapShot = spec.SnapshotSourceAttributes;
|
||||
if (snapShot == null || snapShot.TryGetValue(attributeName, out attributeValue) == false)
|
||||
{
|
||||
Debug.LogError($"Source snapshot Attribute '{attributeName}' not found in source snapshot for spec: '{spec.GameplayEffect.GameplayEffectName}'.");
|
||||
attributeValue = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var attributeCurrentValue = spec.Source.GetAttributeCurrentValue(attributeSetName, attributeShortName);
|
||||
if (attributeCurrentValue == null)
|
||||
{
|
||||
Debug.LogError($"Source Attribute '{attributeName}' not found in source for spec: '{spec.GameplayEffect.GameplayEffectName}'.");
|
||||
attributeValue = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
attributeValue = attributeCurrentValue.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (captureType == GEAttributeCaptureType.SnapShot)
|
||||
{
|
||||
var snapShot = spec.SnapshotTargetAttributes;
|
||||
if (snapShot == null || snapShot.TryGetValue(attributeName, out attributeValue) == false)
|
||||
{
|
||||
Debug.LogError($"Target snapshot Attribute '{attributeName}' not found in target snapshot for spec: '{spec.GameplayEffect.GameplayEffectName}'.");
|
||||
attributeValue = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var attributeCurrentValue = spec.Owner.GetAttributeCurrentValue(attributeSetName, attributeShortName);
|
||||
if (attributeCurrentValue == null)
|
||||
{
|
||||
Debug.LogError($"Source Attribute '{attributeName}' not found in source for spec: '{spec.GameplayEffect.GameplayEffectName}'.");
|
||||
attributeValue = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
attributeValue = attributeCurrentValue.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return attributeValue * k + b;
|
||||
}
|
||||
|
||||
private void OnAttributeNameChanged()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(attributeName))
|
||||
{
|
||||
var split = attributeName.Split('.');
|
||||
attributeSetName = split[0];
|
||||
attributeShortName = split[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
attributeSetName = null;
|
||||
attributeShortName = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c712e05924784c5593896e5c7c1d2708
|
||||
timeCreated: 1703494252
|
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public enum GEOperation
|
||||
{
|
||||
[LabelText(SdfIconType.PlusLg, Text = "加")]
|
||||
Add = 0,
|
||||
|
||||
[LabelText(SdfIconType.DashLg, Text = "减")]
|
||||
Minus = 3,
|
||||
|
||||
[LabelText(SdfIconType.XLg, Text = "乘")]
|
||||
Multiply = 1,
|
||||
|
||||
[LabelText(SdfIconType.SlashLg, Text = "除")]
|
||||
Divide = 4,
|
||||
|
||||
[LabelText(SdfIconType.Pencil, Text = "替")]
|
||||
Override = 2,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum SupportedOperation : byte
|
||||
{
|
||||
None = 0,
|
||||
|
||||
[LabelText(SdfIconType.PlusLg, Text = "加")]
|
||||
Add = 1 << GEOperation.Add,
|
||||
|
||||
[LabelText(SdfIconType.DashLg, Text = "减")]
|
||||
Minus = 1 << GEOperation.Minus,
|
||||
|
||||
[LabelText(SdfIconType.XLg, Text = "乘")]
|
||||
Multiply = 1 << GEOperation.Multiply,
|
||||
|
||||
[LabelText(SdfIconType.SlashLg, Text = "除")]
|
||||
Divide = 1 << GEOperation.Divide,
|
||||
|
||||
[LabelText(SdfIconType.Pencil, Text = "替")]
|
||||
Override = 1 << GEOperation.Override,
|
||||
|
||||
All = Add | Minus | Multiply | Divide | Override
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct GameplayEffectModifier
|
||||
{
|
||||
private const int LABEL_WIDTH = 70;
|
||||
|
||||
[LabelText("修改属性", SdfIconType.Fingerprint)]
|
||||
[LabelWidth(LABEL_WIDTH)]
|
||||
[OnValueChanged("OnAttributeChanged")]
|
||||
[ValueDropdown("@ValueDropdownHelper.AttributeChoices", IsUniqueList = true)]
|
||||
[ValidateInput("@ReflectionHelper.GetAttribute($value) != null", "无效属性")]
|
||||
[Tooltip("指的是GameplayEffect作用对象被修改的属性。")]
|
||||
[SuffixLabel("@ReflectionHelper.GetAttribute($value)?.CalculateMode")]
|
||||
[PropertyOrder(1)]
|
||||
public string AttributeName;
|
||||
|
||||
[HideInInspector]
|
||||
public string AttributeSetName;
|
||||
|
||||
[HideInInspector]
|
||||
public string AttributeShortName;
|
||||
|
||||
[LabelText("运算参数", SdfIconType.Activity)]
|
||||
[LabelWidth(LABEL_WIDTH)]
|
||||
[Tooltip("修改器的基础数值。这个数值如何使用由MMC的运行逻辑决定。\nMMC未指定时直接使用这个值。")]
|
||||
[ValidateInput("@Operation != GEOperation.Divide || ModiferMagnitude != 0", "除数不能为零")]
|
||||
[PropertyOrder(3)]
|
||||
public float ModiferMagnitude;
|
||||
|
||||
[LabelText("运算法则", SdfIconType.PlusSlashMinus)]
|
||||
[LabelWidth(LABEL_WIDTH)]
|
||||
[EnumToggleButtons]
|
||||
[PropertyOrder(2)]
|
||||
[ValidateInput("@ReflectionHelper.GetAttribute(AttributeName) == null || ReflectionHelper.GetAttribute(AttributeName).IsSupportOperation($value)", "非法运算: 该属性不支持的此运算法则")]
|
||||
public GEOperation Operation;
|
||||
|
||||
[LabelText("参数修饰", SdfIconType.CpuFill)]
|
||||
[LabelWidth(LABEL_WIDTH)]
|
||||
[AssetSelector]
|
||||
[Tooltip("ModifierMagnitudeCalculation,修改器,负责GAS中Attribute的数值计算逻辑。\n可以为空(不对\"计算参数\"做任何修改)。")]
|
||||
[PropertyOrder(4)]
|
||||
public ModifierMagnitudeCalculation MMC;
|
||||
|
||||
// TODO
|
||||
// public readonly GameplayTagSet SourceTag;
|
||||
|
||||
// TODO
|
||||
// public readonly GameplayTagSet TargetTag;
|
||||
|
||||
public GameplayEffectModifier(
|
||||
string attributeName,
|
||||
float modiferMagnitude,
|
||||
GEOperation operation,
|
||||
ModifierMagnitudeCalculation mmc = null)
|
||||
{
|
||||
AttributeName = attributeName;
|
||||
var splits = attributeName.Split('.');
|
||||
AttributeSetName = splits[0];
|
||||
AttributeShortName = splits[1];
|
||||
ModiferMagnitude = modiferMagnitude;
|
||||
Operation = operation;
|
||||
MMC = mmc;
|
||||
}
|
||||
|
||||
public float CalculateMagnitude(GameplayEffectSpec spec, float modifierMagnitude)
|
||||
{
|
||||
return MMC == null ? ModiferMagnitude : MMC.CalculateMagnitude(spec, modifierMagnitude);
|
||||
}
|
||||
|
||||
public void SetModiferMagnitude(float value)
|
||||
{
|
||||
ModiferMagnitude = value;
|
||||
}
|
||||
|
||||
void OnAttributeChanged()
|
||||
{
|
||||
var split = AttributeName.Split('.');
|
||||
AttributeSetName = split[0];
|
||||
AttributeShortName = split[1];
|
||||
|
||||
if (ReflectionHelper.GetAttribute(AttributeName)?.CalculateMode !=
|
||||
CalculateMode.Stacking)
|
||||
{
|
||||
Operation = GEOperation.Override;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0b20897a5ad4adc9ac45f147879fee1
|
||||
timeCreated: 1702376348
|
@@ -0,0 +1,56 @@
|
||||
using System.Linq;
|
||||
using GAS.General;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public abstract class ModifierMagnitudeCalculation : ScriptableObject
|
||||
{
|
||||
protected 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;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[TabGroup("Base/H1/V2", "General", SdfIconType.AwardFill, TextColor = "#FF7F00", Order = 2)]
|
||||
[TabGroup("Base/H1/V2", "Detail", SdfIconType.TicketDetailedFill, TextColor = "#BC2FDE")]
|
||||
[LabelText("类型名称", SdfIconType.FileCodeFill)]
|
||||
[LabelWidth(WIDTH_LABEL)]
|
||||
[ShowInInspector]
|
||||
[PropertyOrder(-1)]
|
||||
public string TypeName => GetType().Name;
|
||||
|
||||
[TabGroup("Base/H1/V2", "Detail")]
|
||||
[LabelText("类型全名", SdfIconType.FileCodeFill)]
|
||||
[LabelWidth(WIDTH_LABEL)]
|
||||
[ShowInInspector]
|
||||
[PropertyOrder(-1)]
|
||||
public string TypeFullName => GetType().FullName;
|
||||
|
||||
[TabGroup("Base/H1/V2", "Detail")]
|
||||
[ListDrawerSettings(ShowFoldout = true, ShowItemCount = false, ShowPaging = false)]
|
||||
[ShowInInspector]
|
||||
[LabelText("继承关系")]
|
||||
[LabelWidth(WIDTH_LABEL)]
|
||||
[PropertyOrder(-1)]
|
||||
public string[] InheritanceChain => GetType().GetInheritanceChain().Reverse().ToArray();
|
||||
#endif
|
||||
|
||||
public abstract float CalculateMagnitude(GameplayEffectSpec spec, float modifierMagnitude);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
// if(Application.isPlaying) return;
|
||||
// EditorUtility.SetDirty(this);
|
||||
// AssetDatabase.SaveAssets();
|
||||
// AssetDatabase.Refresh();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a19086b31e7847ccaa9ec35657197357
|
||||
timeCreated: 1702624467
|
@@ -0,0 +1,24 @@
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
[CreateAssetMenu(fileName = "ScalableFloatModCalculation", menuName = "GAS/MMC/ScalableFloatModCalculation")]
|
||||
public class ScalableFloatModCalculation : ModifierMagnitudeCalculation
|
||||
{
|
||||
private const string Desc = "计算公式:ModifierMagnitude * k + b";
|
||||
|
||||
private const string Detail =
|
||||
"ScalableFloatModCalculation:可缩放浮点数计算\n该类型是根据Magnitude计算Modifier模值的,计算公式为:ModifierMagnitude * k + b 实际上就是一个线性函数,k和b为可编辑参数,可以在编辑器中设置。";
|
||||
|
||||
[DetailedInfoBox(Desc, Detail, InfoMessageType.Info)] [SerializeField]
|
||||
private float k = 1f;
|
||||
|
||||
[SerializeField] private float b = 0f;
|
||||
|
||||
public override float CalculateMagnitude(GameplayEffectSpec spec, float input)
|
||||
{
|
||||
return input * k + b;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b127451ee4eb4575be21eb8e5744a5da
|
||||
timeCreated: 1703493960
|
@@ -0,0 +1,18 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
[CreateAssetMenu(fileName = "SetByCallerFromName", menuName = "GAS/MMC/SetByCallerFromNameModCalculation")]
|
||||
public class SetByCallerFromNameModCalculation : ModifierMagnitudeCalculation
|
||||
{
|
||||
[SerializeField] private string valueName;
|
||||
public override float CalculateMagnitude(GameplayEffectSpec spec,float input)
|
||||
{
|
||||
var value = spec.GetMapValue(valueName);
|
||||
#if UNITY_EDITOR
|
||||
if(value==null) Debug.LogWarning($"[EX] SetByCallerModCalculation: GE's '{valueName}' value(name map) is not set");
|
||||
#endif
|
||||
return value ?? 0;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 46c94907308d49a9965a836e3447b1a4
|
||||
timeCreated: 1706243411
|
@@ -0,0 +1,23 @@
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
[CreateAssetMenu(fileName = "SetByCallerFromTag", menuName = "GAS/MMC/SetByCallerFromTagModCalculation")]
|
||||
public class SetByCallerFromTagModCalculation : ModifierMagnitudeCalculation
|
||||
{
|
||||
[SerializeField]
|
||||
[ValueDropdown("@ValueDropdownHelper.GameplayTagChoices", HideChildProperties = true)]
|
||||
private GameplayTag _tag;
|
||||
|
||||
public override float CalculateMagnitude(GameplayEffectSpec spec, float input)
|
||||
{
|
||||
var value = spec.GetMapValue(_tag);
|
||||
#if UNITY_EDITOR
|
||||
if (value == null)
|
||||
Debug.LogWarning($"[EX] SetByCallerModCalculation: GE's '{_tag.Name}' value(tag map) is not set");
|
||||
#endif
|
||||
return value ?? 0;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 235035fa9abf451594198fe2ed2b2e28
|
||||
timeCreated: 1706240763
|
@@ -0,0 +1,26 @@
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
[CreateAssetMenu( fileName = "StackModCalculation", menuName = "GAS/MMC/StackModCalculation" )]
|
||||
public class StackModCalculation:ModifierMagnitudeCalculation
|
||||
{
|
||||
[InfoBox("计算逻辑与ScalableFloatModCalculation一致, 公式:(StackCount) * k + b")]
|
||||
[TabGroup("Default", "StackModCalculation")]
|
||||
[LabelText("系数(k)")]
|
||||
public float k = 1;
|
||||
|
||||
[TabGroup("Default", "StackModCalculation")]
|
||||
[LabelText("常量(b)")]
|
||||
public float b = 0;
|
||||
|
||||
public override float CalculateMagnitude(GameplayEffectSpec spec, float modifierMagnitude)
|
||||
{
|
||||
if (spec.Stacking.stackingType == StackingType.None) return 0;
|
||||
|
||||
var stackCount = spec.StackCount;
|
||||
return stackCount * k + b;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 21d2ef437f1e4ec9900650b169b66e77
|
||||
timeCreated: 1717073260
|
Reference in New Issue
Block a user