mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-09-26 18:26:23 +00:00
提交
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using JNGame.Game;
|
||||
using JNGame.GAS;
|
||||
using JNGame.Runtime.GAS.Runtime;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace GAS.Editor
|
||||
@@ -179,8 +180,8 @@ namespace GAS.Editor
|
||||
if (IsPlaying)
|
||||
{
|
||||
if (_selected == null || _selected.EntityId == 0)
|
||||
_selected = GameplayAbilitySystem.GAS.AbilitySystemComponents.Count > 0
|
||||
? GameplayAbilitySystem.GAS.AbilitySystemComponents[0] as AbilitySystemComponent
|
||||
_selected = JexGasManager.Editor.AbilitySystemComponents.Count > 0
|
||||
? JexGasManager.Editor.AbilitySystemComponents[0] as AbilitySystemComponent
|
||||
: null;
|
||||
|
||||
RefreshAscInfo();
|
||||
@@ -201,7 +202,7 @@ namespace GAS.Editor
|
||||
if (!IsPlaying) return;
|
||||
|
||||
menuScrollPos = EditorGUILayout.BeginScrollView(menuScrollPos, GUI.skin.box);
|
||||
foreach (var iasc in GameplayAbilitySystem.GAS.AbilitySystemComponents)
|
||||
foreach (var iasc in JexGasManager.Editor.AbilitySystemComponents)
|
||||
{
|
||||
var asc = (AbilitySystemComponent)iasc;
|
||||
var presetName = asc.Preset != null ? asc.Preset.Name : "NoPreset";
|
||||
@@ -211,7 +212,6 @@ namespace GAS.Editor
|
||||
RefreshAscInfo();
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
|
@@ -30,7 +30,7 @@ namespace GAS.Runtime
|
||||
{
|
||||
Debug.Log("error");
|
||||
}
|
||||
m_CueIndex = workingContext.OwnerAbility.Owner.OnCueAdd(workingContext.OwnerAbility, cueAssetLocation);
|
||||
m_CueIndex = workingContext.OwnerAbility.Owner.OnCueAdd(workingContext.OwnerAbility, cueAssetLocation,this.durationalFrame);
|
||||
}
|
||||
|
||||
protected override void OnEnd(TimelineWorkingContext workingContext)
|
||||
|
@@ -0,0 +1,51 @@
|
||||
using System.Collections.Generic;
|
||||
using GAS.General;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Cue 处理
|
||||
/// </summary>
|
||||
public abstract partial class AbilitySystemComponent : IAbilitySystemComponent, IPool
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// AbilitySpec 唯一Id
|
||||
/// </summary>
|
||||
private Dictionary<AbilitySpec, int> AbilitySpecId = new();
|
||||
|
||||
/// <summary>
|
||||
/// Ability的Timeline轨道触发了持续型Cue的添加
|
||||
/// </summary>
|
||||
/// <param name="abilitySpec"></param>
|
||||
/// <param name="cueAssetLocation">Cue资源地址</param>
|
||||
/// <param name="durationTime">持续时间</param>
|
||||
/// <returns></returns>
|
||||
public int OnCueAdd(AbilitySpec abilitySpec, string cueAssetLocation, int durationTime)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ability的Timeline轨道触发了持续型Cue的移除
|
||||
/// </summary>
|
||||
/// <param name="abilitySpec"></param>
|
||||
/// <param name="cueClipIndex"></param>
|
||||
public void OnCueRemove(AbilitySpec abilitySpec, int cueClipIndex)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ability的Timeline轨道触发了瞬时Cue的触发
|
||||
/// </summary>
|
||||
/// <param name="abilitySpec"></param>
|
||||
/// <param name="cueAssetLocations"></param>
|
||||
public void OnCueExecute(AbilitySpec abilitySpec, string[] cueAssetLocations)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd84ebd1383e4e009578ebd2daae3200
|
||||
timeCreated: 1729704061
|
@@ -8,7 +8,7 @@ using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public abstract class AbilitySystemComponent : IAbilitySystemComponent, IPool
|
||||
public abstract partial class AbilitySystemComponent : IAbilitySystemComponent, IPool
|
||||
{
|
||||
public int SelfNumber;
|
||||
|
||||
@@ -41,6 +41,20 @@ namespace GAS.Runtime
|
||||
/// Owner的包围盒半径
|
||||
/// </summary>
|
||||
public LFloat BoundRadius { get; protected set; } = LFloat.One;
|
||||
|
||||
/// <summary>
|
||||
/// 当前唯一Id
|
||||
/// </summary>
|
||||
private int UniqueId = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前类下一个唯一Id
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int GetUniqueId()
|
||||
{
|
||||
return UniqueId++;
|
||||
}
|
||||
|
||||
public void OnAwake()
|
||||
{
|
||||
@@ -327,28 +341,6 @@ namespace GAS.Runtime
|
||||
/// <param name="geSpec"></param>
|
||||
public abstract void OnGERelease(GameplayEffectSpec geSpec);
|
||||
|
||||
/// <summary>
|
||||
/// Ability的Timeline轨道触发了持续型Cue的添加
|
||||
/// </summary>
|
||||
/// <param name="abilitySpec"></param>
|
||||
/// <param name="cueAssetLocation"></param>
|
||||
/// <returns></returns>
|
||||
public abstract int OnCueAdd(AbilitySpec abilitySpec, string cueAssetLocation);
|
||||
|
||||
/// <summary>
|
||||
/// Ability的Timeline轨道触发了持续型Cue的移除
|
||||
/// </summary>
|
||||
/// <param name="abilitySpec"></param>
|
||||
/// <param name="cueClipIndex"></param>
|
||||
public abstract void OnCueRemove(AbilitySpec abilitySpec, int cueClipIndex);
|
||||
|
||||
/// <summary>
|
||||
/// Ability的Timeline轨道触发了瞬时Cue的触发
|
||||
/// </summary>
|
||||
/// <param name="abilitySpec"></param>
|
||||
/// <param name="cueAssetLocations"></param>
|
||||
public abstract void OnCueExecute(AbilitySpec abilitySpec, string[] cueAssetLocations);
|
||||
|
||||
/// <summary>
|
||||
/// Ability结束激活
|
||||
/// </summary>
|
||||
|
@@ -1,94 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using GAS.Runtime;
|
||||
|
||||
namespace GAS
|
||||
{
|
||||
public class GameplayAbilitySystem
|
||||
{
|
||||
private static GameplayAbilitySystem _gas;
|
||||
|
||||
private GameplayAbilitySystem()
|
||||
{
|
||||
const int capacity = 1024;
|
||||
AbilitySystemComponents = new List<AbilitySystemComponent>(capacity);
|
||||
_cachedAbilitySystemComponents = 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 readonly List<AbilitySystemComponent> _cachedAbilitySystemComponents;
|
||||
|
||||
// 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()
|
||||
{
|
||||
AbilitySystemComponents.Clear();
|
||||
}
|
||||
|
||||
// public void Tick()
|
||||
// {
|
||||
// Profiler.BeginSample($"{nameof(GameplayAbilitySystem)}::Tick()");
|
||||
|
||||
// _cachedAbilitySystemComponents.AddRange(AbilitySystemComponents);
|
||||
|
||||
// foreach (var abilitySystemComponent in _cachedAbilitySystemComponents)
|
||||
// {
|
||||
// abilitySystemComponent.Tick();
|
||||
// }
|
||||
|
||||
// _cachedAbilitySystemComponents.Clear();
|
||||
|
||||
// Profiler.EndSample();
|
||||
// }
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 98a325bbe54441739d7e05e89817e9a5
|
||||
timeCreated: 1701861619
|
@@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace JNGame.Sync.System.Data
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 事件型数据系统
|
||||
/// 用于通知客户端
|
||||
/// </summary>
|
||||
public abstract class SEventDataSystem : SDataSystemBase
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 服务器事件
|
||||
/// </summary>
|
||||
private Queue<SEvent> ServerEvents = new();
|
||||
/// <summary>
|
||||
/// 客户端事件
|
||||
/// </summary>
|
||||
private Queue<SEvent> ClientEvents = new();
|
||||
|
||||
public SEventDataEnum Type;
|
||||
public bool isServer => Type is SEventDataEnum.ServerClient or SEventDataEnum.Server;
|
||||
public bool isClient => Type is SEventDataEnum.ServerClient or SEventDataEnum.Client;
|
||||
|
||||
//待插入的数据
|
||||
protected Queue<byte[]> WaitUBytes = new ();
|
||||
|
||||
public SEventDataSystem(SEventDataEnum type)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public override void OnSyncStart()
|
||||
{
|
||||
|
||||
}
|
||||
public override void OnSyncUpdate(int dt)
|
||||
{
|
||||
|
||||
while (WaitUBytes.Count > 0)
|
||||
{
|
||||
OnUByteUpdate(WaitUBytes.Dequeue());
|
||||
}
|
||||
|
||||
if (isServer)
|
||||
{
|
||||
if (ServerEvents.Count <= 0) return;
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
using (BinaryWriter writer = new BinaryWriter(ms))
|
||||
{
|
||||
int count = ServerEvents.Count;
|
||||
//写入数量
|
||||
writer.Write(count);
|
||||
for (int i = count - 1; i >= 0; i--)
|
||||
{
|
||||
var data = ServerEvents.Dequeue().ToByteArray();
|
||||
//写入数据大小
|
||||
writer.Write(data.Length);
|
||||
//写入数据
|
||||
writer.Write(data);
|
||||
}
|
||||
}
|
||||
// 发送完整的字节数组
|
||||
OnSendUBytes(ms.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送字节数据
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <returns>是否清空UBytes</returns>
|
||||
public abstract void OnSendUBytes(byte[] bytes);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 插入字节
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public void OnInsertUBytes(byte[] bytes)
|
||||
{
|
||||
WaitUBytes.Enqueue(bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 提交更新到ClientEvents
|
||||
/// </summary>
|
||||
private void OnUByteUpdate(byte[] dequeue)
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream(dequeue))
|
||||
{
|
||||
using (BinaryReader reader = new BinaryReader(ms))
|
||||
{
|
||||
// 读取 数量
|
||||
int count = reader.ReadInt32();
|
||||
for (int i = count - 1; i >= 0; i--)
|
||||
{
|
||||
// 读取 数据 字段的长度
|
||||
int length = reader.ReadInt32();
|
||||
// 读取 数据
|
||||
ClientEvents.Enqueue(SEvent.FromByteArray(reader.ReadBytes(length)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEvent(int type,byte[] data)
|
||||
{
|
||||
//只有服务器才可以添加事件
|
||||
if (isServer)
|
||||
{
|
||||
ServerEvents.Enqueue(new SEvent()
|
||||
{
|
||||
Type = type,
|
||||
Data = data,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class SEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据类型
|
||||
/// </summary>
|
||||
public int Type;
|
||||
/// <summary>
|
||||
/// 数据
|
||||
/// </summary>
|
||||
public byte[] Data;
|
||||
|
||||
/// <summary>
|
||||
/// 将 SEvent 对象转换为字节数组
|
||||
/// </summary>
|
||||
/// <returns>SEvent 对象的字节表示</returns>
|
||||
public byte[] ToByteArray()
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
using (BinaryWriter writer = new BinaryWriter(ms))
|
||||
{
|
||||
// 写入 Type 字段,使用小端字节序
|
||||
writer.Write(Type);
|
||||
// 写入 Data 字段的长度
|
||||
writer.Write(Data?.Length ?? 0);
|
||||
// 写入 Data 字段的数据
|
||||
if (Data != null)
|
||||
{
|
||||
writer.Write(Data);
|
||||
}
|
||||
}
|
||||
// 返回完整的字节数组
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从字节数组还原 SEvent 对象
|
||||
/// </summary>
|
||||
/// <param name="byteArray">包含 SEvent 数据的字节数组</param>
|
||||
/// <returns>还原后的 SEvent 对象</returns>
|
||||
public static SEvent FromByteArray(byte[] byteArray)
|
||||
{
|
||||
if (byteArray == null || byteArray.Length < 8)
|
||||
{
|
||||
throw new ArgumentException("字节数组长度不足");
|
||||
}
|
||||
using (MemoryStream ms = new MemoryStream(byteArray))
|
||||
{
|
||||
using (BinaryReader reader = new BinaryReader(ms))
|
||||
{
|
||||
// 读取 Type 字段
|
||||
int type = reader.ReadInt32();
|
||||
// 读取 Data 字段的长度
|
||||
int dataLength = reader.ReadInt32();
|
||||
// 读取 Data 字段的数据
|
||||
byte[] data = reader.ReadBytes(dataLength);
|
||||
// 返回还原后的 SEvent 对象
|
||||
return new SEvent { Type = type, Data = data };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum SEventDataEnum
|
||||
{
|
||||
Server,
|
||||
Client,
|
||||
ServerClient,
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b2443b1ebaf4f66b259d21757cc3c7e
|
||||
timeCreated: 1729705001
|
Binary file not shown.
@@ -26,7 +26,7 @@ namespace JNGame.GAS
|
||||
|
||||
if (frame >= startFrame && frame <= endFrame)
|
||||
{
|
||||
preview.transform.position = Vector3.Lerp(start.ToVector3(), end.ToVector3(), (float)(frame - startFrame) / endFrame);
|
||||
preview.transform.position = Vector3.Lerp(start.ToVector3(), end.ToVector3(), (float)(frame - startFrame) / (endFrame - startFrame));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,7 +34,7 @@ namespace JNGame.GAS
|
||||
|
||||
public override void OnStart(int startFrame)
|
||||
{
|
||||
Debug.Log("OnEnd");
|
||||
Debug.Log("OnStart");
|
||||
}
|
||||
|
||||
public override void OnEnd(int endFrame)
|
||||
@@ -45,7 +45,7 @@ namespace JNGame.GAS
|
||||
public override void OnTick(int frameIndex, int startFrame, int endFrame)
|
||||
{
|
||||
Debug.Log($"OnTick {frameIndex} {startFrame} {endFrame}");
|
||||
((GAbilitySystemComponent)m_Spec.Owner).Entity.Transform.Position = LVector3.Lerp(start, end, (LFloat)(frameIndex - startFrame) / endFrame);
|
||||
((GAbilitySystemComponent)m_Spec.Owner).Entity.Transform.Position = LVector3.Lerp(start, end, (LFloat)(frameIndex - startFrame) / (endFrame - startFrame));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
using JNGame.Sync.System.Data;
|
||||
using NotImplementedException = System.NotImplementedException;
|
||||
|
||||
namespace GASSamples.Scripts.Game.Logic.Data
|
||||
{
|
||||
public class GEventDataSystem : SEventDataSystem
|
||||
{
|
||||
public GEventDataSystem(SEventDataEnum type) : base(type)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnSendUBytes(byte[] bytes)
|
||||
{
|
||||
OnInsertUBytes(bytes);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62c8d2be3a26419791fb6456f47f82a2
|
||||
timeCreated: 1729707100
|
@@ -11,7 +11,7 @@ namespace GASSamples.Scripts.Game.GAS
|
||||
|
||||
|
||||
public IJNEntity Entity { get; protected set; }
|
||||
|
||||
|
||||
public GAbilitySystemComponent(IJNEntity entity)
|
||||
{
|
||||
Entity = entity;
|
||||
@@ -48,22 +48,6 @@ namespace GASSamples.Scripts.Game.GAS
|
||||
Debug.Log("OnGERelease");
|
||||
}
|
||||
|
||||
public override int OnCueAdd(AbilitySpec abilitySpec, string cueAssetLocation)
|
||||
{
|
||||
Debug.Log("OnCueAdd");
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void OnCueRemove(AbilitySpec abilitySpec, int cueClipIndex)
|
||||
{
|
||||
Debug.Log("OnCueRemove");
|
||||
}
|
||||
|
||||
public override void OnCueExecute(AbilitySpec abilitySpec, string[] cueAssetLocations)
|
||||
{
|
||||
Debug.Log("OnCueExecute");
|
||||
}
|
||||
|
||||
public override void OnAbilityEnd(AbilitySpec abilitySpec)
|
||||
{
|
||||
Debug.Log("OnAbilityEnd");
|
||||
|
@@ -9,6 +9,7 @@ using GASSamples.Scripts.Game.View;
|
||||
using JNGame.Sync.Entity;
|
||||
using JNGame.Sync.Frame;
|
||||
using JNGame.Sync.System;
|
||||
using JNGame.Sync.System.Data;
|
||||
|
||||
namespace DefaultNamespace
|
||||
{
|
||||
@@ -30,6 +31,7 @@ namespace DefaultNamespace
|
||||
public override SDataSystemBase[] NewDataSystems()
|
||||
{
|
||||
return new SDataSystemBase[] {
|
||||
new GEventDataSystem(SEventDataSystem.SEventDataEnum.ServerClient),
|
||||
new JNGASBoxDataSystem(),
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user