基础案例 准备改帧同步了

This commit is contained in:
DESKTOP-5RP3AKU\Jisol
2024-10-21 02:09:30 +08:00
parent 44e2735899
commit cbacd5a501
117 changed files with 17049 additions and 4808 deletions

View File

@@ -1,4 +1,5 @@
using System;
using GAS.Runtime;
using UnityEngine;
namespace GAS.General
@@ -16,7 +17,7 @@ namespace GAS.General
public static int CurrentFrameCount => _currentFrameCount;
public static void UpdateCurrentFrameCount()
{
_currentFrameCount = Mathf.FloorToInt((Timestamp() - _startTimestamp) / 1000f * FrameRate);
_currentFrameCount = Mathf.FloorToInt((Timestamp() - _startTimestamp) / 1000f * JexGasManager.FrameRate);
}
private static long _startTimestamp;
@@ -37,7 +38,5 @@ namespace GAS.General
_deltaTime -= (int)(Timestamp() - _pauseTimestamp);
}
private static int _frameRate = 60;
public static int FrameRate => _frameRate;
}
}

View File

@@ -78,8 +78,8 @@ namespace GAS.Runtime
[TabGroup("Base/H1/V2", "General")]
[LabelWidth(WIDTH_LABEL)]
[LabelText(SdfIconType.ClockFill, Text = GASTextDefine.ABILITY_CD_TIME)]
[Unit(Units.Second)]
public float CooldownTime;
[Unit(Units.Millisecond)]
public int CooldownTime;
// Tags
[TabGroup("Base/H1/V3", "Tags", SdfIconType.TagsFill, TextColor = "#45B1FF", Order = 3)]

View File

@@ -14,14 +14,14 @@ namespace GAS.Runtime
_owner = owner;
}
public void Tick()
public void Tick(int dt)
{
var abilitySpecs = JexGasObjectPool.Instance.Fetch<List<AbilitySpec>>();
abilitySpecs.AddRange(_abilities.Values);
foreach (var abilitySpec in abilitySpecs)
{
abilitySpec.Tick();
abilitySpec.Tick(dt);
}
abilitySpecs.Clear();

View File

@@ -212,15 +212,15 @@ namespace GAS.Runtime
_onCancelAbility?.Invoke();
}
public void Tick()
public void Tick(int dt)
{
if (IsActive)
{
AbilityTick();
AbilityTick(dt);
}
}
protected virtual void AbilityTick()
protected virtual void AbilityTick(int dt)
{
}

View File

@@ -16,7 +16,7 @@ namespace GAS.Runtime
public GameplayEffect Cooldown { get; protected set; }
public float CooldownTime { get; protected set; }
public int CooldownTime { get; protected set; }
public GameplayEffect Cost { get; protected set; }

View File

@@ -56,10 +56,10 @@ namespace GAS.Runtime
_player.Stop();
}
protected override void AbilityTick()
protected override void AbilityTick(int dt)
{
Profiler.BeginSample("TimelineAbilitySpecT<T>::AbilityTick()");
_player.Tick();
_player.Tick(dt);
Profiler.EndSample();
}
}

View File

@@ -66,7 +66,7 @@ namespace GAS.Runtime
public AssetT AbilityAsset => _abilitySpec.Data.AbilityAsset;
public int FrameCount => AbilityAsset.FrameCount;
public int FrameRate => GASTimer.FrameRate;
public int FrameRate => JexGasManager.FrameRate;
/// <summary>
/// 不受播放速率影响的总时间
@@ -241,14 +241,14 @@ namespace GAS.Runtime
IsPlaying = false;
}
public void Tick()
public void Tick(int dt)
{
if (!IsPlaying) return;
var speed = _abilitySpec.GetPlaySpeed();
speed = Math.Max(0, speed);
_playTotalTime += Time.deltaTime * speed;
var targetFrame = (int)(_playTotalTime * FrameRate);
_playTotalTime += dt * speed;
var targetFrame = ((int)(_playTotalTime * FrameRate)) / 1000;
// 追帧
while (_currentFrame < targetFrame)

View File

@@ -282,10 +282,10 @@ namespace GAS.Runtime
return value;
}
public void Tick()
public void Tick(int dt)
{
AbilityContainer.Tick();
GameplayEffectContainer.Tick();
AbilityContainer.Tick(dt);
GameplayEffectContainer.Tick(dt);
}
public Dictionary<string, float> DataSnapshot()

View File

@@ -31,7 +31,7 @@ namespace GAS.Runtime
void RemoveGameplayEffect(GameplayEffectSpec spec);
void Tick();
void Tick(int dt);
Dictionary<string, float> DataSnapshot();

View File

@@ -1,99 +0,0 @@
using System.Collections.Generic;
using GAS.General;
using GAS.Runtime;
using UnityEngine;
using UnityEngine.Profiling;
namespace GAS
{
public class GameplayAbilitySystem
{
private static GameplayAbilitySystem _gas;
private GameplayAbilitySystem()
{
const int capacity = 1024;
AbilitySystemComponents = new List<AbilitySystemComponent>(capacity);
GASTimer.InitStartTimestamp();
GasHost = new GameObject("GAS Host").AddComponent<GasHost>();
GasHost.hideFlags = HideFlags.HideAndDontSave;
Object.DontDestroyOnLoad(GasHost.gameObject);
GasHost.gameObject.SetActive(true);
}
public List<AbilitySystemComponent> AbilitySystemComponents { get; }
private GasHost GasHost { get; }
public static GameplayAbilitySystem GAS
{
get
{
_gas ??= new GameplayAbilitySystem();
return _gas;
}
}
public bool IsPaused => !GasHost.enabled;
public void Register(AbilitySystemComponent abilitySystemComponent)
{
// if (!GasHost.enabled)
// {
// Debug.LogWarning("[EX] GAS is paused, can't register new ASC!");
// return;
// }
if (AbilitySystemComponents.Contains(abilitySystemComponent)) return;
AbilitySystemComponents.Add(abilitySystemComponent);
}
public bool Unregister(AbilitySystemComponent abilitySystemComponent)
{
// if (!GasHost.enabled)
// {
// Debug.LogWarning("[EX] GAS is paused, can't unregister ASC!");
// return false;
// }
return AbilitySystemComponents.Remove(abilitySystemComponent);
}
public void Pause()
{
GasHost.enabled = false;
}
public void Unpause()
{
GasHost.enabled = true;
}
public void ClearComponents()
{
foreach (var t in AbilitySystemComponents)
t.Disable();
AbilitySystemComponents.Clear();
}
public void Tick()
{
Profiler.BeginSample($"{nameof(GameplayAbilitySystem)}::Tick()");
var abilitySystemComponents = JexGasObjectPool.Instance.Fetch<List<AbilitySystemComponent>>();
abilitySystemComponents.AddRange(AbilitySystemComponents);
foreach (var abilitySystemComponent in abilitySystemComponents)
{
abilitySystemComponent.Tick();
}
abilitySystemComponents.Clear();
JexGasObjectPool.Instance.Recycle(abilitySystemComponents);
Profiler.EndSample();
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 98a325bbe54441739d7e05e89817e9a5
timeCreated: 1701861619

View File

@@ -1,21 +0,0 @@
using GAS.General;
using UnityEngine;
namespace GAS
{
public class GasHost : MonoBehaviour
{
private GameplayAbilitySystem _gas => GameplayAbilitySystem.GAS;
private void Update()
{
GASTimer.UpdateCurrentFrameCount();
_gas.Tick();
}
private void OnDestroy()
{
_gas.ClearComponents();
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: c17e2cf434ca2f549b2fbd2dc0ecc4c8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -37,7 +37,7 @@ namespace GAS.Runtime
{
public readonly string GameplayEffectName;
public readonly EffectsDurationPolicy DurationPolicy;
public readonly float Duration; // -1 represents infinite duration
public readonly int Duration; // -1 represents infinite duration
public readonly float Period;
public readonly GameplayEffect PeriodExecution;
public readonly GameplayEffectTagContainer TagContainer;

View File

@@ -55,9 +55,9 @@ namespace GAS.Runtime
[LabelWidth(WIDTH_LABEL)]
[LabelText(GASTextDefine.LABLE_GE_DURATION, SdfIconType.HourglassSplit)]
[EnableIf("@DurationPolicy == EffectsDurationPolicy.Duration")]
[Unit(Units.Second)]
[Unit(Units.Millisecond)]
[ValidateInput("@DurationPolicy != EffectsDurationPolicy.Duration || Duration > 0", ERROR_DURATION)]
public float Duration;
public int Duration;
[ShowIf("@DurationPolicy != EffectsDurationPolicy.Duration")]
[TabGroup(GRP_BASE_H_RIGHT, "Policy")]
@@ -65,9 +65,9 @@ namespace GAS.Runtime
[LabelWidth(WIDTH_LABEL)]
[LabelText(GASTextDefine.LABLE_GE_INTERVAL, SdfIconType.AlarmFill)]
[EnableIf("IsDurationalPolicy")]
[Unit(Units.Second)]
[Unit(Units.Millisecond)]
[ValidateInput("@DurationPolicy != EffectsDurationPolicy.Infinite || Period <= 0 || Period >= 0.01f", "Period < 0.01", InfoMessageType.Warning)]
public float Period;
public int Period;
[ShowIf("@DurationPolicy == EffectsDurationPolicy.Duration"),]
[TabGroup(GRP_BASE_H_RIGHT, "Policy")]
@@ -80,7 +80,7 @@ namespace GAS.Runtime
[PropertyRange(0, "@Duration")]
[ValidateInput("@DurationPolicy != EffectsDurationPolicy.Duration || Period <= 0 || Period >= 0.01f", "Period < 0.01", InfoMessageType.Warning)]
// 这个Property是为了给"限时型"效果绘制一个范围滑动条
public float PeriodForDurational
public int PeriodForDurational
{
get => Period;
set => Period = value;
@@ -325,9 +325,9 @@ namespace GAS.Runtime
public EffectsDurationPolicy GetDurationPolicy() => DurationPolicy;
public float GetDuration() => Duration;
public int GetDuration() => Duration;
public float GetPeriod() => Period;
public int GetPeriod() => Period;
public IGameplayEffectData GetPeriodExecution() => PeriodExecution;

View File

@@ -22,7 +22,7 @@ namespace GAS.Runtime
return _gameplayEffectSpecs;
}
public void Tick()
public void Tick(int dt)
{
var gameplayEffectSpecs = JexGasObjectPool.Instance.Fetch<List<GameplayEffectSpec>>();
gameplayEffectSpecs.AddRange(_gameplayEffectSpecs);
@@ -31,7 +31,7 @@ namespace GAS.Runtime
{
if (gameplayEffectSpec.IsActive)
{
gameplayEffectSpec.Tick();
gameplayEffectSpec.Tick(dt);
}
}

View File

@@ -21,9 +21,9 @@ namespace GAS.Runtime
public virtual EffectsDurationPolicy GetDurationPolicy() => EffectsDurationPolicy.Instant;
public virtual float GetDuration() => -1;
public virtual int GetDuration() => -1;
public virtual float GetPeriod() => 0;
public virtual int GetPeriod() => 0;
public virtual IGameplayEffectData GetPeriodExecution() => null;
@@ -66,7 +66,7 @@ namespace GAS.Runtime
public class InfiniteGameplayEffectData : InstantGameplayEffectData
{
public float Period { get; }
public int Period { get; }
public IGameplayEffectData PeriodExecution { get; set; } = null;
@@ -83,11 +83,11 @@ namespace GAS.Runtime
public GrantedAbilityConfig[] GrantedAbilities { get; set; } = Array.Empty<GrantedAbilityConfig>();
public GameplayEffectStacking Stacking { get; set; } = GameplayEffectStacking.None;
public InfiniteGameplayEffectData(string name, float period) : base(name) => Period = period;
public InfiniteGameplayEffectData(string name, int period) : base(name) => Period = period;
public override EffectsDurationPolicy GetDurationPolicy() => EffectsDurationPolicy.Infinite;
public override float GetPeriod() => Period;
public override int GetPeriod() => Period;
public override IGameplayEffectData GetPeriodExecution() => PeriodExecution;
@@ -114,14 +114,15 @@ namespace GAS.Runtime
public override GameplayEffectStacking GetStacking() => Stacking;
}
public class DurationalGameplayEffectData : InfiniteGameplayEffectData
{
public float Duration { get; }
public int Duration { get; }
public DurationalGameplayEffectData(string name, float period, float duration) : base(name, period) => Duration = duration;
public DurationalGameplayEffectData(string name, int period, int duration) : base(name, period) => Duration = duration;
public override EffectsDurationPolicy GetDurationPolicy() => EffectsDurationPolicy.Duration;
public override float GetDuration() => Duration;
public override int GetDuration() => Duration;
}
}

View File

@@ -25,11 +25,11 @@ namespace GAS.Runtime
private float Period => _spec.GameplayEffect.Period;
public void Tick()
public void Tick(int dt)
{
_spec.TriggerOnTick();
UpdatePeriod();
UpdatePeriod(dt);
if (_spec.DurationPolicy == EffectsDurationPolicy.Duration && _spec.DurationRemaining() <= 0)
{
@@ -69,29 +69,26 @@ namespace GAS.Runtime
/// <summary>
/// 注意: Period 小于 0.01f 可能出现误差, 基本够用了
/// </summary>
private void UpdatePeriod()
private void UpdatePeriod(int dt)
{
// 前提: Period不会动态修改
if (Period <= 0) return;
var actualDuration = Time.time - _spec.ActivationTime;
if (actualDuration < Mathf.Epsilon)
if ( _spec.ActivationTime == 0)
{
// 第一次执行
return;
}
var dt = Time.deltaTime;
if (_spec.DurationPolicy == EffectsDurationPolicy.Duration)
{
var excessDuration = actualDuration - _spec.Duration;
int excessDuration = _spec.ActivationTime - _spec.Duration;
if (excessDuration >= 0)
{
// 如果超出了持续时间,就减去超出的时间, 此时应该是最后一次执行
dt -= excessDuration;
// 为了避免误差, 保证最后一次边界得到执行机会
dt += 0.0001f;
dt += 1;
}
}

View File

@@ -150,14 +150,14 @@ namespace GAS.Runtime
}
public GameplayEffect GameplayEffect { get; private set; }
public float ActivationTime { get; private set; }
public int ActivationTime { get; private set; }
public float Level { get; private set; }
public AbilitySystemComponent Source { get; private set; }
public AbilitySystemComponent Owner { get; private set; }
public bool IsApplied { get; private set; }
public bool IsActive { get; private set; }
internal EntityRef<GameplayEffectPeriodTicker> PeriodTicker { get; private set; }
public float Duration { get; private set; }
public int Duration { get; private set; }
public EffectsDurationPolicy DurationPolicy { get; private set; }
public EntityRef<GameplayEffectSpec> PeriodExecution { get; private set; }
public GameplayEffectModifier[] Modifiers { get; private set; }
@@ -173,13 +173,12 @@ namespace GAS.Runtime
/// </summary>
public int StackCount { get; private set; } = 1;
public float DurationRemaining()
{
if (DurationPolicy == EffectsDurationPolicy.Infinite)
return -1;
return Mathf.Max(0, Duration - (Time.time - ActivationTime));
return Mathf.Max(0, Duration - ActivationTime);
}
public void SetLevel(float level)
@@ -187,12 +186,12 @@ namespace GAS.Runtime
Level = level;
}
public void SetActivationTime(float activationTime)
public void SetActivationTime(int activationTime)
{
ActivationTime = activationTime;
}
public void SetDuration(float duration)
public void SetDuration(int duration)
{
Duration = duration;
}
@@ -271,7 +270,7 @@ namespace GAS.Runtime
{
if (IsActive) return;
IsActive = true;
ActivationTime = Time.time;
ActivationTime = 0;
TriggerOnActivation();
}
@@ -282,9 +281,10 @@ namespace GAS.Runtime
TriggerOnDeactivation();
}
public void Tick()
public void Tick(int dt)
{
PeriodTicker.Value?.Tick();
ActivationTime += dt;
PeriodTicker.Value?.Tick(dt);
}
void TriggerInstantCues(GameplayCueInstant[] cues)
@@ -679,7 +679,7 @@ namespace GAS.Runtime
public void RefreshDuration()
{
ActivationTime = Time.time;
ActivationTime = 0;
}
private void OnStackCountChange(int oldStackCount, int newStackCount)

View File

@@ -4,8 +4,8 @@
{
string GetDisplayName();
EffectsDurationPolicy GetDurationPolicy();
float GetDuration();
float GetPeriod();
int GetDuration();
int GetPeriod();
GameplayEffectSnapshotPolicy GetSnapshotPolicy();
GameplayEffectSpecifiedSnapshotConfig[] GetSpecifiedSnapshotConfigs();

View File

@@ -10,6 +10,22 @@ namespace GAS.Runtime
public class JexGasManager
{
#if UNITY_EDITOR
//编辑器专用的单例 用于预览GAS
public static JexGasManager Editor = new JexGasManager();
#endif
public JexGasManager()
{
#if UNITY_EDITOR
//预览GAS
Editor = this;
#endif
}
//---------------- 全局信息 ------------------------------------------------------------------------------------------
public static int FrameRate = 10; //每秒帧
public List<AbilitySystemComponent> AbilitySystemComponents = new();
/// <summary>
@@ -18,7 +34,7 @@ namespace GAS.Runtime
private JexGasObjectPool ObjectPool = new JexGasObjectPool();
//GAS 更新
public void Update()
public void Update(int dt)
{
Profiler.BeginSample($"{nameof(JexGasManager)}::Tick()");
@@ -28,7 +44,7 @@ namespace GAS.Runtime
foreach (var abilitySystemComponent in abilitySystemComponents)
{
abilitySystemComponent.Tick();
abilitySystemComponent.Tick(dt);
}
abilitySystemComponents.Clear();