mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-09-27 02:36:14 +00:00
提交GAS 打算做一个帧同步的GAS
This commit is contained in:
3
JEX_GAS/Assets/GAS/Runtime/Cue/Base.meta
Normal file
3
JEX_GAS/Assets/GAS/Runtime/Cue/Base.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35878043833f4ae3bb6976f748a85a8b
|
||||
timeCreated: 1705029950
|
79
JEX_GAS/Assets/GAS/Runtime/Cue/Base/GameplayCue.cs
Normal file
79
JEX_GAS/Assets/GAS/Runtime/Cue/Base/GameplayCue.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using System.Linq;
|
||||
using GAS.General;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public abstract class GameplayCue : ScriptableObject
|
||||
{
|
||||
protected const int WIDTH_LABEL = 70;
|
||||
|
||||
[TitleGroup("Base")]
|
||||
[HorizontalGroup("Base/H1")]
|
||||
[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
|
||||
// Tags
|
||||
[TabGroup("Base/H1/V3", "Tags", SdfIconType.TagsFill, TextColor = "#45B1FF", Order = 3)]
|
||||
[ValueDropdown("@ValueDropdownHelper.GameplayTagChoices", IsUniqueList = true, HideChildProperties = true)]
|
||||
[ListDrawerSettings(ShowFoldout = true, ShowItemCount = false, DraggableItems = false)]
|
||||
[DisableContextMenu(disableForMember: false, disableCollectionElements: true)]
|
||||
[CustomContextMenu("排序", "@RequiredTags = TagHelper.Sort($value)")]
|
||||
[LabelText("RequiredTags - 持有所有标签才可触发")]
|
||||
public GameplayTag[] RequiredTags;
|
||||
|
||||
[TabGroup("Base/H1/V3", "Tags")]
|
||||
[ValueDropdown("@ValueDropdownHelper.GameplayTagChoices", IsUniqueList = true, HideChildProperties = true)]
|
||||
[ListDrawerSettings(ShowFoldout = true, ShowItemCount = false, DraggableItems = false)]
|
||||
[DisableContextMenu(disableForMember: false, disableCollectionElements: true)]
|
||||
[CustomContextMenu("排序", "@ImmunityTags = TagHelper.Sort($value)")]
|
||||
[LabelText("ImmunityTags - 持有任意标签不可触发")]
|
||||
public GameplayTag[] ImmunityTags;
|
||||
|
||||
public virtual bool Triggerable(AbilitySystemComponent owner)
|
||||
{
|
||||
if (owner == null) return false;
|
||||
// 持有【所有】RequiredTags才可触发
|
||||
if (!owner.HasAllTags(new GameplayTagSet(RequiredTags)))
|
||||
return false;
|
||||
|
||||
// 持有【任意】ImmunityTags不可触发
|
||||
if (owner.HasAnyTags(new GameplayTagSet(ImmunityTags)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class GameplayCue<T> : GameplayCue where T : GameplayCueSpec
|
||||
{
|
||||
public abstract T CreateSpec(GameplayCueParameters parameters);
|
||||
}
|
||||
}
|
3
JEX_GAS/Assets/GAS/Runtime/Cue/Base/GameplayCue.cs.meta
Normal file
3
JEX_GAS/Assets/GAS/Runtime/Cue/Base/GameplayCue.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24a60d4a49b842c28e848c52adb587e4
|
||||
timeCreated: 1702536571
|
53
JEX_GAS/Assets/GAS/Runtime/Cue/Base/GameplayCueDurational.cs
Normal file
53
JEX_GAS/Assets/GAS/Runtime/Cue/Base/GameplayCueDurational.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public abstract class GameplayCueDurational : GameplayCue<GameplayCueDurationalSpec>
|
||||
{
|
||||
public GameplayCueDurationalSpec ApplyFrom(GameplayEffectSpec gameplayEffectSpec)
|
||||
{
|
||||
if (!Triggerable(gameplayEffectSpec.Owner)) return null;
|
||||
var durationalCue = CreateSpec(new GameplayCueParameters
|
||||
{ sourceGameplayEffectSpec = gameplayEffectSpec });
|
||||
return durationalCue;
|
||||
}
|
||||
|
||||
public GameplayCueDurationalSpec ApplyFrom(AbilitySpec abilitySpec,params object[] customArguments)
|
||||
{
|
||||
if (!Triggerable(abilitySpec.Owner)) return null;
|
||||
var durationalCue = CreateSpec(new GameplayCueParameters
|
||||
{ sourceAbilitySpec = abilitySpec, customArguments = customArguments});
|
||||
return durationalCue;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public virtual void OnEditorPreview(GameObject previewObject,int frameIndex,int startFrame,int endFrame)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public abstract class GameplayCueDurationalSpec : GameplayCueSpec
|
||||
{
|
||||
protected GameplayCueDurationalSpec(GameplayCueDurational cue, GameplayCueParameters parameters) :
|
||||
base(cue, parameters)
|
||||
{
|
||||
}
|
||||
|
||||
public abstract void OnAdd();
|
||||
public abstract void OnRemove();
|
||||
public abstract void OnGameplayEffectActivate();
|
||||
public abstract void OnGameplayEffectDeactivate();
|
||||
public abstract void OnTick();
|
||||
}
|
||||
|
||||
public abstract class GameplayCueDurationalSpec<T> : GameplayCueDurationalSpec where T : GameplayCueDurational
|
||||
{
|
||||
public readonly T cue;
|
||||
|
||||
protected GameplayCueDurationalSpec(T cue, GameplayCueParameters parameters) : base(cue, parameters)
|
||||
{
|
||||
this.cue = cue;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cfc27df4bdc54282b3e7540eef7f4679
|
||||
timeCreated: 1705027856
|
53
JEX_GAS/Assets/GAS/Runtime/Cue/Base/GameplayCueInstant.cs
Normal file
53
JEX_GAS/Assets/GAS/Runtime/Cue/Base/GameplayCueInstant.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public abstract class GameplayCueInstant : GameplayCue<GameplayCueInstantSpec>
|
||||
{
|
||||
public virtual void ApplyFrom(GameplayEffectSpec gameplayEffectSpec)
|
||||
{
|
||||
if (Triggerable(gameplayEffectSpec.Owner))
|
||||
{
|
||||
var instantCue = CreateSpec(new GameplayCueParameters
|
||||
{ sourceGameplayEffectSpec = gameplayEffectSpec });
|
||||
instantCue?.Trigger();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ApplyFrom(AbilitySpec abilitySpec, params object[] customArguments)
|
||||
{
|
||||
if (Triggerable(abilitySpec.Owner))
|
||||
{
|
||||
var instantCue = CreateSpec(new GameplayCueParameters
|
||||
{ sourceAbilitySpec = abilitySpec, customArguments = customArguments });
|
||||
instantCue?.Trigger();
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public virtual void OnEditorPreview(GameObject previewObject, int frame, int startFrame)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public abstract class GameplayCueInstantSpec : GameplayCueSpec
|
||||
{
|
||||
public GameplayCueInstantSpec(GameplayCueInstant cue, GameplayCueParameters parameters) : base(cue,
|
||||
parameters)
|
||||
{
|
||||
}
|
||||
|
||||
public abstract void Trigger();
|
||||
}
|
||||
|
||||
public abstract class GameplayCueInstantSpec<T>:GameplayCueInstantSpec where T:GameplayCueInstant
|
||||
{
|
||||
public readonly T cue;
|
||||
|
||||
public GameplayCueInstantSpec(T cue, GameplayCueParameters parameters) : base(cue, parameters)
|
||||
{
|
||||
this.cue = cue;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2483d9a3b6064679b6ec7cf5fc2831b6
|
||||
timeCreated: 1705027797
|
15
JEX_GAS/Assets/GAS/Runtime/Cue/Base/GameplayCueParameters.cs
Normal file
15
JEX_GAS/Assets/GAS/Runtime/Cue/Base/GameplayCueParameters.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public struct GameplayCueParameters
|
||||
{
|
||||
public GameplayEffectSpec sourceGameplayEffectSpec;
|
||||
|
||||
public AbilitySpec sourceAbilitySpec;
|
||||
|
||||
public object[] customArguments;
|
||||
// AggregatedSourceTags
|
||||
// AggregatedTargetTags
|
||||
// EffectContext
|
||||
// Magnitude
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71478534541e4560a993cd0ead34edc3
|
||||
timeCreated: 1705915979
|
29
JEX_GAS/Assets/GAS/Runtime/Cue/Base/GameplayCueSpec.cs
Normal file
29
JEX_GAS/Assets/GAS/Runtime/Cue/Base/GameplayCueSpec.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public abstract class GameplayCueSpec
|
||||
{
|
||||
protected readonly GameplayCue _cue;
|
||||
protected readonly GameplayCueParameters _parameters;
|
||||
public AbilitySystemComponent Owner { get; protected set; }
|
||||
|
||||
public virtual bool Triggerable()
|
||||
{
|
||||
return _cue.Triggerable(Owner);
|
||||
}
|
||||
|
||||
public GameplayCueSpec(GameplayCue cue, GameplayCueParameters cueParameters)
|
||||
{
|
||||
_cue = cue;
|
||||
_parameters = cueParameters;
|
||||
if (_parameters.sourceGameplayEffectSpec != null)
|
||||
{
|
||||
Owner = _parameters.sourceGameplayEffectSpec.Owner;
|
||||
}
|
||||
else if (_parameters.sourceAbilitySpec != null)
|
||||
{
|
||||
Owner = _parameters.sourceAbilitySpec.Owner;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2c7719fe70c46e98344f1d9d8ebb9e6
|
||||
timeCreated: 1705042515
|
105
JEX_GAS/Assets/GAS/Runtime/Cue/CueAnimation.cs
Normal file
105
JEX_GAS/Assets/GAS/Runtime/Cue/CueAnimation.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using GAS.General;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public class CueAnimation : GameplayCueDurational
|
||||
{
|
||||
[BoxGroup]
|
||||
[InfoBox(GASTextDefine.CUE_ANIMATION_PATH_TIP)]
|
||||
[LabelText(GASTextDefine.CUE_ANIMATION_PATH)]
|
||||
[SerializeField]
|
||||
private string _animatorRelativePath;
|
||||
|
||||
[BoxGroup]
|
||||
[InfoBox(GASTextDefine.CUE_ANIMATION_INCLUDE_CHILDREN_ANIMATOR_TIP)]
|
||||
[LabelText(GASTextDefine.CUE_ANIMATION_INCLUDE_CHILDREN)]
|
||||
[SerializeField]
|
||||
private bool _includeChildrenAnimator;
|
||||
|
||||
[BoxGroup]
|
||||
[LabelText(GASTextDefine.CUE_ANIMATION_STATE)]
|
||||
[SerializeField]
|
||||
private string _stateName;
|
||||
|
||||
public string AnimatorRelativePath => _animatorRelativePath;
|
||||
public bool IncludeChildrenAnimator => _includeChildrenAnimator;
|
||||
public string StateName => _stateName;
|
||||
|
||||
|
||||
public override GameplayCueDurationalSpec CreateSpec(GameplayCueParameters parameters)
|
||||
{
|
||||
return new CueAnimationSpec(this, parameters);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public override void OnEditorPreview(GameObject previewObject, int frame, int startFrame, int endFrame)
|
||||
{
|
||||
if (startFrame <= frame && frame <= endFrame)
|
||||
{
|
||||
var transform = previewObject.transform.Find(AnimatorRelativePath);
|
||||
var animator = IncludeChildrenAnimator ? transform.GetComponentInChildren<Animator>() : transform.GetComponent<Animator>();
|
||||
if (animator != null)
|
||||
{
|
||||
var stateMap = animator.GetAllAnimationState();
|
||||
if (stateMap.TryGetValue(StateName, out var clip))
|
||||
{
|
||||
float clipFrameCount = (int)(clip.frameRate * clip.length);
|
||||
if (frame <= clipFrameCount + startFrame)
|
||||
{
|
||||
var progress = (frame - startFrame) / clipFrameCount;
|
||||
if (progress > 1 && clip.isLooping) progress -= (int)progress;
|
||||
clip.SampleAnimation(animator.gameObject, progress * clip.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"Animator is null. Please check the cue asset: {name}, AnimatorRelativePath: {AnimatorRelativePath}, IncludeChildrenAnimator: {IncludeChildrenAnimator}");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public class CueAnimationSpec : GameplayCueDurationalSpec<CueAnimation>
|
||||
{
|
||||
private readonly Animator _animator;
|
||||
|
||||
public CueAnimationSpec(CueAnimation cue, GameplayCueParameters parameters) : base(cue,
|
||||
parameters)
|
||||
{
|
||||
var transform = Owner.transform.Find(cue.AnimatorRelativePath);
|
||||
_animator = cue.IncludeChildrenAnimator ? transform.GetComponentInChildren<Animator>() : transform.GetComponent<Animator>();
|
||||
if (_animator == null)
|
||||
{
|
||||
Debug.LogError($"Animator is null. Please check the cue asset: {cue.name}, AnimatorRelativePath: {cue.AnimatorRelativePath}, IncludeChildrenAnimator: {cue.IncludeChildrenAnimator}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnAdd()
|
||||
{
|
||||
if (_animator != null)
|
||||
{
|
||||
_animator.Play(cue.StateName);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnGameplayEffectActivate()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnGameplayEffectDeactivate()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnTick()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
3
JEX_GAS/Assets/GAS/Runtime/Cue/CueAnimation.cs.meta
Normal file
3
JEX_GAS/Assets/GAS/Runtime/Cue/CueAnimation.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b9fc094e7fa46ac85ce5efa6359b74f
|
||||
timeCreated: 1711451948
|
111
JEX_GAS/Assets/GAS/Runtime/Cue/CueAnimationOneShot.cs
Normal file
111
JEX_GAS/Assets/GAS/Runtime/Cue/CueAnimationOneShot.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using GAS.General;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
[CreateAssetMenu(fileName = "CuePlayAnimation", menuName = "GAS/Cue/CuePlayAnimation")]
|
||||
public class CueAnimationOneShot : GameplayCueInstant
|
||||
{
|
||||
[BoxGroup]
|
||||
[InfoBox(GASTextDefine.CUE_ANIMATION_PATH_TIP)]
|
||||
[LabelText(GASTextDefine.CUE_ANIMATION_PATH)]
|
||||
[SerializeField]
|
||||
private string _animatorRelativePath;
|
||||
|
||||
[BoxGroup]
|
||||
[InfoBox(GASTextDefine.CUE_ANIMATION_INCLUDE_CHILDREN_ANIMATOR_TIP)]
|
||||
[LabelText(GASTextDefine.CUE_ANIMATION_INCLUDE_CHILDREN)]
|
||||
[SerializeField]
|
||||
private bool _includeChildrenAnimator;
|
||||
|
||||
[BoxGroup]
|
||||
[LabelText(GASTextDefine.CUE_ANIMATION_STATE)]
|
||||
[SerializeField]
|
||||
private string _stateName;
|
||||
|
||||
public string AnimatorRelativePath => _animatorRelativePath;
|
||||
public bool IncludeChildrenAnimator => _includeChildrenAnimator;
|
||||
public string StateName => _stateName;
|
||||
|
||||
|
||||
public override GameplayCueInstantSpec CreateSpec(GameplayCueParameters parameters)
|
||||
{
|
||||
return new CueAnimationOneShotSpec(this, parameters);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public override void OnEditorPreview(GameObject previewObject, int frame, int startFrame)
|
||||
{
|
||||
if (startFrame <= frame)
|
||||
{
|
||||
var transform = previewObject.transform.Find(AnimatorRelativePath);
|
||||
Animator animator = null;
|
||||
if (transform != null)
|
||||
{
|
||||
animator = IncludeChildrenAnimator
|
||||
? transform.GetComponentInChildren<Animator>()
|
||||
: transform.GetComponent<Animator>();
|
||||
}
|
||||
|
||||
if (animator == null)
|
||||
{
|
||||
Debug.LogError(
|
||||
$"Animator is null. Please check the cue asset: {name}, AnimatorRelativePath: {AnimatorRelativePath}, IncludeChildrenAnimator: {IncludeChildrenAnimator}");
|
||||
return;
|
||||
}
|
||||
|
||||
var stateMap = animator.GetAllAnimationState();
|
||||
if (stateMap.TryGetValue(StateName, out var clip))
|
||||
{
|
||||
if (clip != null)
|
||||
{
|
||||
float clipFrameCount = (int)(clip.frameRate * clip.length);
|
||||
if (frame <= clipFrameCount + startFrame)
|
||||
{
|
||||
var progress = (frame - startFrame) / clipFrameCount;
|
||||
if (progress > 1 && clip.isLooping) progress -= (int)progress;
|
||||
clip.SampleAnimation(animator.gameObject, progress * clip.length);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Clip is null. Please check the cue asset: {name}, StateName: {StateName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public class CueAnimationOneShotSpec : GameplayCueInstantSpec<CueAnimationOneShot>
|
||||
{
|
||||
private readonly Animator _animator;
|
||||
|
||||
public CueAnimationOneShotSpec(CueAnimationOneShot cue, GameplayCueParameters parameters)
|
||||
: base(cue, parameters)
|
||||
{
|
||||
var transform = Owner.transform.Find(cue.AnimatorRelativePath);
|
||||
if (transform != null)
|
||||
{
|
||||
_animator = cue.IncludeChildrenAnimator
|
||||
? transform.GetComponentInChildren<Animator>()
|
||||
: transform.GetComponent<Animator>();
|
||||
}
|
||||
|
||||
if (_animator == null)
|
||||
{
|
||||
Debug.LogError(
|
||||
$"Animator is null. Please check the cue asset: {cue.name}, AnimatorRelativePath: {cue.AnimatorRelativePath}, IncludeChildrenAnimator: {cue.IncludeChildrenAnimator}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void Trigger()
|
||||
{
|
||||
if (_animator != null)
|
||||
{
|
||||
_animator.Play(cue.StateName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0831f70ea054910b7c7a907e5121590
|
||||
timeCreated: 1703670598
|
89
JEX_GAS/Assets/GAS/Runtime/Cue/CueAnimationSpeedModifier.cs
Normal file
89
JEX_GAS/Assets/GAS/Runtime/Cue/CueAnimationSpeedModifier.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using GAS.General;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public sealed class CueAnimationSpeedModifier : GameplayCueDurational
|
||||
{
|
||||
const int LabelWidth = 120;
|
||||
|
||||
[TabGroup("Data", "Data", SdfIconType.Gear, TextColor = "#FF7F00")]
|
||||
[InfoBox(GASTextDefine.CUE_ANIMATION_PATH_TIP, InfoMessageType.None)]
|
||||
[LabelText(GASTextDefine.CUE_ANIMATION_PATH), LabelWidth(LabelWidth)]
|
||||
public string animatorRelativePath;
|
||||
|
||||
[TabGroup("Data", "Data")]
|
||||
[InfoBox(GASTextDefine.CUE_ANIMATION_INCLUDE_CHILDREN_ANIMATOR_TIP, InfoMessageType.None)]
|
||||
[LabelText(GASTextDefine.CUE_ANIMATION_INCLUDE_CHILDREN), LabelWidth(LabelWidth)]
|
||||
public bool includeChildrenAnimator;
|
||||
|
||||
[TabGroup("Data", "Data")]
|
||||
[LabelText("播放速度"), LabelWidth(LabelWidth)]
|
||||
[Range(0, 5f)]
|
||||
public float speed = 1f;
|
||||
|
||||
[TabGroup("Data", "Data")]
|
||||
[InfoBox("结束时会设置的值, 如果有其它需求, 需要另外实现. ^_^", InfoMessageType.None)]
|
||||
[LabelText("默认播放速度"), LabelWidth(LabelWidth)]
|
||||
[Range(0, 5f)]
|
||||
public float defaultSpeed = 1f;
|
||||
|
||||
public override GameplayCueDurationalSpec CreateSpec(GameplayCueParameters parameters)
|
||||
{
|
||||
return new GCS_ChangeAnimationSpeed(this, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public sealed class GCS_ChangeAnimationSpeed : GameplayCueDurationalSpec<CueAnimationSpeedModifier>
|
||||
{
|
||||
private readonly Animator _animator;
|
||||
|
||||
public GCS_ChangeAnimationSpeed(CueAnimationSpeedModifier cue, GameplayCueParameters parameters)
|
||||
: base(cue, parameters)
|
||||
{
|
||||
var transform = Owner.transform.Find(cue.animatorRelativePath);
|
||||
if (transform != null)
|
||||
{
|
||||
_animator = cue.includeChildrenAnimator
|
||||
? transform.GetComponentInChildren<Animator>()
|
||||
: transform.GetComponent<Animator>();
|
||||
}
|
||||
|
||||
if (_animator == null)
|
||||
{
|
||||
Debug.LogError(
|
||||
$"Animator is null. Please check the cue asset: {cue.name}, AnimatorRelativePath: {cue.animatorRelativePath}, IncludeChildrenAnimator: {cue.includeChildrenAnimator}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnAdd()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnGameplayEffectActivate()
|
||||
{
|
||||
if (_animator != null)
|
||||
{
|
||||
_animator.speed = cue.speed;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGameplayEffectDeactivate()
|
||||
{
|
||||
if (_animator != null)
|
||||
{
|
||||
_animator.speed = cue.defaultSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnTick()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05165f697da94e96b844dd2d8c77aea9
|
||||
timeCreated: 1718704588
|
78
JEX_GAS/Assets/GAS/Runtime/Cue/CuePlaySound.cs
Normal file
78
JEX_GAS/Assets/GAS/Runtime/Cue/CuePlaySound.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using GAS.General;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public class CuePlaySound : GameplayCueDurational
|
||||
{
|
||||
[BoxGroup]
|
||||
[LabelText(GASTextDefine.CUE_SOUND_EFFECT)]
|
||||
public AudioClip soundEffect;
|
||||
|
||||
[BoxGroup]
|
||||
[LabelText(GASTextDefine.CUE_ATTACH_TO_OWNER)]
|
||||
public bool isAttachToOwner = true;
|
||||
|
||||
public override GameplayCueDurationalSpec CreateSpec(GameplayCueParameters parameters)
|
||||
{
|
||||
return new CuePlaySoundSpec(this, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
public class CuePlaySoundSpec : GameplayCueDurationalSpec<CuePlaySound>
|
||||
{
|
||||
private AudioSource _audioSource;
|
||||
|
||||
public CuePlaySoundSpec(CuePlaySound cue, GameplayCueParameters parameters) : base(cue,
|
||||
parameters)
|
||||
{
|
||||
if (cue.isAttachToOwner)
|
||||
{
|
||||
_audioSource = Owner.gameObject.GetComponent<AudioSource>();
|
||||
if (_audioSource == null)
|
||||
{
|
||||
_audioSource = Owner.gameObject.AddComponent<AudioSource>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var soundRoot = new GameObject("SoundRoot");
|
||||
soundRoot.transform.position = Owner.transform.position;
|
||||
_audioSource = soundRoot.AddComponent<AudioSource>();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnAdd()
|
||||
{
|
||||
_audioSource.clip = cue.soundEffect;
|
||||
_audioSource.Play();
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
if (!cue.isAttachToOwner)
|
||||
{
|
||||
Object.Destroy(_audioSource.gameObject);
|
||||
}else
|
||||
{
|
||||
_audioSource.Stop();
|
||||
_audioSource.clip = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGameplayEffectActivate()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnGameplayEffectDeactivate()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnTick()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
3
JEX_GAS/Assets/GAS/Runtime/Cue/CuePlaySound.cs.meta
Normal file
3
JEX_GAS/Assets/GAS/Runtime/Cue/CuePlaySound.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c3aca85c2044621903d913d5bd792b1
|
||||
timeCreated: 1703670793
|
146
JEX_GAS/Assets/GAS/Runtime/Cue/CueVFX.cs
Normal file
146
JEX_GAS/Assets/GAS/Runtime/Cue/CueVFX.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
using GAS.General;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public class CueVFX : GameplayCueDurational
|
||||
{
|
||||
[BoxGroup]
|
||||
[LabelText(GASTextDefine.CUE_VFX_PREFAB)]
|
||||
public GameObject VfxPrefab;
|
||||
|
||||
[BoxGroup]
|
||||
[LabelText(GASTextDefine.CUE_ATTACH_TO_OWNER)]
|
||||
public bool IsAttachToTarget = true;
|
||||
|
||||
[BoxGroup]
|
||||
[LabelText(GASTextDefine.CUE_VFX_OFFSET)]
|
||||
public Vector3 Offset;
|
||||
|
||||
[BoxGroup]
|
||||
[LabelText(GASTextDefine.CUE_VFX_ROTATION)]
|
||||
public Vector3 Rotation;
|
||||
|
||||
[BoxGroup]
|
||||
[LabelText(GASTextDefine.CUE_VFX_SCALE)]
|
||||
public Vector3 Scale = Vector3.one;
|
||||
|
||||
[BoxGroup]
|
||||
[LabelText(GASTextDefine.CUE_VFX_ACTIVE_WHEN_ADDED)]
|
||||
public bool ActiveWhenAdded = false;
|
||||
|
||||
public override GameplayCueDurationalSpec CreateSpec(GameplayCueParameters parameters)
|
||||
{
|
||||
return new CueVFXSpec(this, parameters);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private GameObject _effectPreviewInstance;
|
||||
public override void OnEditorPreview(GameObject preview, int frameIndex, int startFrame, int endFrame)
|
||||
{
|
||||
if (VfxPrefab == null) return;
|
||||
if (frameIndex >= startFrame && frameIndex <= endFrame)
|
||||
{
|
||||
if (_effectPreviewInstance != null && _effectPreviewInstance.name != VfxPrefab.name)
|
||||
{
|
||||
DestroyImmediate(_effectPreviewInstance);
|
||||
_effectPreviewInstance = null;
|
||||
}
|
||||
|
||||
if (_effectPreviewInstance == null)
|
||||
{
|
||||
_effectPreviewInstance = Instantiate(VfxPrefab, preview.transform);
|
||||
_effectPreviewInstance.name = VfxPrefab.name;
|
||||
_effectPreviewInstance.transform.localPosition = Offset;
|
||||
_effectPreviewInstance.transform.localEulerAngles = Rotation;
|
||||
_effectPreviewInstance.transform.localScale = Scale;
|
||||
}
|
||||
|
||||
// 模拟例子的播放
|
||||
var particleSystems = _effectPreviewInstance.GetComponentsInChildren<ParticleSystem>();
|
||||
foreach (var ps in particleSystems)
|
||||
{
|
||||
var t = (frameIndex - startFrame) / GASTimer.FrameRate;
|
||||
ps.Simulate(t);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_effectPreviewInstance != null)
|
||||
{
|
||||
DestroyImmediate(_effectPreviewInstance);
|
||||
_effectPreviewInstance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public class CueVFXSpec : GameplayCueDurationalSpec<CueVFX>
|
||||
{
|
||||
private GameObject _vfxInstance;
|
||||
|
||||
public CueVFXSpec(CueVFX cue, GameplayCueParameters parameters) : base(cue,
|
||||
parameters)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnAdd()
|
||||
{
|
||||
if (cue.VfxPrefab != null)
|
||||
{
|
||||
_vfxInstance = cue.IsAttachToTarget
|
||||
? Object.Instantiate(cue.VfxPrefab, Owner.transform)
|
||||
: Object.Instantiate(cue.VfxPrefab, Owner.transform.position, Quaternion.identity);
|
||||
|
||||
_vfxInstance.transform.localPosition = cue.Offset;
|
||||
_vfxInstance.transform.localEulerAngles = cue.Rotation;
|
||||
_vfxInstance.transform.localScale = cue.Scale;
|
||||
_vfxInstance.SetActive(cue.ActiveWhenAdded);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
Debug.LogError("VFX prefab is null!");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
if (_vfxInstance != null)
|
||||
{
|
||||
Object.Destroy(_vfxInstance);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGameplayEffectActivate()
|
||||
{
|
||||
if (_vfxInstance != null)
|
||||
{
|
||||
_vfxInstance.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGameplayEffectDeactivate()
|
||||
{
|
||||
if (_vfxInstance != null)
|
||||
{
|
||||
_vfxInstance.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnTick()
|
||||
{
|
||||
}
|
||||
|
||||
public void SetVisible(bool visible)
|
||||
{
|
||||
if (_vfxInstance != null)
|
||||
{
|
||||
_vfxInstance.SetActive(visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
3
JEX_GAS/Assets/GAS/Runtime/Cue/CueVFX.cs.meta
Normal file
3
JEX_GAS/Assets/GAS/Runtime/Cue/CueVFX.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1261c2b342e03224ebc341132b01bf92
|
||||
timeCreated: 1703670852
|
Reference in New Issue
Block a user