mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-06-26 03:14:47 +00:00
临时提交
This commit is contained in:
parent
930911e7df
commit
e9c01842f0
File diff suppressed because it is too large
Load Diff
@ -43,13 +43,13 @@
|
||||
<ItemGroup>
|
||||
<None Include="Assets\Plugins\Sirenix\Odin Inspector\Assets\Editor\Bootstrap License.txt" />
|
||||
<Reference Include="UnityEngine">
|
||||
<HintPath>C:\APP\UnityEdit\2022.3.16f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.dll</HintPath>
|
||||
<HintPath>D:\Unity\2022.3.1f1\Editor\Data\Managed\UnityEngine\UnityEngine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.CoreModule">
|
||||
<HintPath>C:\APP\UnityEdit\2022.3.16f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll</HintPath>
|
||||
<HintPath>D:\Unity\2022.3.1f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEditor">
|
||||
<HintPath>C:\APP\UnityEdit\2022.3.16f1c1\Editor\Data\Managed\UnityEngine\UnityEditor.dll</HintPath>
|
||||
<HintPath>D:\Unity\2022.3.1f1\Editor\Data\Managed\UnityEngine\UnityEditor.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
3
JNFrame2/Assets/HotScripts/JNGame/Editor/CodeGen.meta
Normal file
3
JNFrame2/Assets/HotScripts/JNGame/Editor/CodeGen.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2131d730bd5441b894b4aa82cf8ec03c
|
||||
timeCreated: 1729496838
|
@ -0,0 +1,134 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace JNGame.Tools.CodeGen
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码生成信息
|
||||
/// </summary>
|
||||
public class CodeGenInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码文件输出路径
|
||||
/// </summary>
|
||||
public string outputPath;
|
||||
/// <summary>
|
||||
/// 代码生成using的命名空间
|
||||
/// </summary>
|
||||
public string codeGenNameSpace;
|
||||
/// <summary>
|
||||
/// 需要代码生成的所有Type
|
||||
/// </summary>
|
||||
public List<System.Type> allTypes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CodeGenFieldInfo
|
||||
{
|
||||
public System.Type type;
|
||||
public string name;
|
||||
|
||||
public string TypeName => type.Name;
|
||||
public string FullTypeName => type.FullName;
|
||||
public bool IsEnum => type.IsEnum;
|
||||
public bool IsStruct => !type.IsClass && !type.IsInterface;
|
||||
public bool IsClass => type.IsClass;
|
||||
public bool IsString => type == typeof(string);
|
||||
public bool IsArray => type.IsArray;
|
||||
public bool IsList => type.IsSubclassOf(typeof(IList));
|
||||
public bool IsDict => type.IsSubclassOf(typeof(IDictionary));
|
||||
}
|
||||
|
||||
public class CodeGenTemplateInfo
|
||||
{
|
||||
public string Default = "";
|
||||
public string Enum = "";
|
||||
public string Struct = "";
|
||||
public string Array = "";
|
||||
public string List = "";
|
||||
public string Dict = "";
|
||||
|
||||
public string GetTemplateStr(CodeGenFieldInfo info)
|
||||
{
|
||||
if (info.IsEnum && !string.IsNullOrEmpty(Enum)) return Enum;
|
||||
if (info.IsList && !string.IsNullOrEmpty(List)) return List;
|
||||
if (info.IsDict && !string.IsNullOrEmpty(Dict)) return Dict;
|
||||
if (info.IsStruct && !string.IsNullOrEmpty(Struct)) return Struct;
|
||||
if (info.IsArray && !string.IsNullOrEmpty(Array)) return Array;
|
||||
return Default;
|
||||
}
|
||||
}
|
||||
|
||||
public class FileUtil
|
||||
{
|
||||
public static void SaveFile(string path, byte[] finalStr, bool isNeedLog = true)
|
||||
{
|
||||
var dir = Path.GetDirectoryName(path);
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var rawContent = File.ReadAllBytes(path);
|
||||
if (finalStr.Length == rawContent.Length)
|
||||
{
|
||||
bool isSame = true;
|
||||
for (int i = 0; i < finalStr.Length; i++)
|
||||
{
|
||||
if (finalStr[i] != rawContent[i])
|
||||
{
|
||||
isSame = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isSame)
|
||||
{
|
||||
// 相同的内容跳过,避免重新的导入
|
||||
#if UNITY_EDITOR
|
||||
if (isNeedLog) UnityEngine.Debug.Log("Output Skip " + path);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File.WriteAllBytes(path, finalStr);
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.AssetDatabase.ImportAsset(path);
|
||||
if (isNeedLog) UnityEngine.Debug.Log("Output " + path);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void SaveFile(string path, string finalStr, bool isNeedLog = true)
|
||||
{
|
||||
var dir = Path.GetDirectoryName(path);
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var rawContent = File.ReadAllText(path);
|
||||
if (finalStr == rawContent)
|
||||
{
|
||||
// 相同的内容跳过,避免重新的导入
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
File.WriteAllText(path, finalStr);
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.AssetDatabase.ImportAsset(path);
|
||||
if (isNeedLog) UnityEngine.Debug.Log("Output " + path);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6427711364f941d58000a7c3df90315e
|
||||
timeCreated: 1729496613
|
@ -0,0 +1,70 @@
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using System.Collections.Generic;
|
||||
using GAS.Runtime;
|
||||
using JNGame.Serialization;
|
||||
|
||||
namespace GAS.Editor
|
||||
{
|
||||
public static class GameplayAbilityAssetConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// 序列化TimelineAbilityAsset
|
||||
/// </summary>
|
||||
/// <param name="timelineAbilityAsset"></param>
|
||||
/// <returns></returns>
|
||||
public static byte[] ToBytes(this TimelineAbilityAsset timelineAbilityAsset)
|
||||
{
|
||||
Serializer serializer = new Serializer();
|
||||
// 序列化TimlineAbilityAsset的Ability属性配置
|
||||
serializer.Write(timelineAbilityAsset.Name);
|
||||
serializer.Write(timelineAbilityAsset.UniqueName);
|
||||
serializer.Write(timelineAbilityAsset.Cost == null ? "" : timelineAbilityAsset.Cost.Name);
|
||||
serializer.Write(timelineAbilityAsset.CooldownTime);
|
||||
// serializer.WriteArray(timelineAbilityAsset.AssetTags);
|
||||
// serializer.WriteArray(timelineAbilityAsset.CancelAbilityTags);
|
||||
// serializer.WriteArray(timelineAbilityAsset.BlockAbilityTags);
|
||||
// serializer.WriteArray(timelineAbilityAsset.ActivationOwnedTags);
|
||||
// serializer.WriteArray(timelineAbilityAsset.ActivationRequiredTags);
|
||||
// serializer.WriteArray(timelineAbilityAsset.ActivationBlockedTags);
|
||||
|
||||
// Ability的Timeline执行规则部分转化为TimelineInfo
|
||||
// TimelineInfo timelineInfo = Convert2TimelineInfo(timelineAbilityAsset);
|
||||
// timelineInfo.SerializeForEditor(serializer);
|
||||
|
||||
return serializer.CopyData();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class AbilityAssetTool
|
||||
{
|
||||
// /// <summary>
|
||||
// /// PureTimelineAbilityAsset数据序列化为字节数据的工具函数
|
||||
// /// </summary>
|
||||
// /// <param name="info"></param>
|
||||
// /// <returns></returns>
|
||||
// public static byte[] Serialize(PureTimelineAbilityAsset abilityAsset)
|
||||
// {
|
||||
// var writer = new Serializer();
|
||||
// abilityAsset.SerializeForEditor(writer);
|
||||
// return writer.CopyData();
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 字节数据反序列化为PureTimelineAbilityAsset的工具函数
|
||||
// /// </summary>
|
||||
// /// <param name="bytes"></param>
|
||||
// /// <returns></returns>
|
||||
// public static PureTimelineAbilityAsset Deserialize(byte[] bytes)
|
||||
// {
|
||||
// var reader = new Deserializer(bytes);
|
||||
// var abilityAsset = new PureTimelineAbilityAsset();
|
||||
// abilityAsset.DeserializeForEditor(reader);
|
||||
// return abilityAsset;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b8ce146f8ec841b49c7015f978fe03d9
|
||||
timeCreated: 1729501121
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using GAS.General;
|
||||
using Sirenix.OdinInspector;
|
||||
@ -30,6 +31,25 @@ namespace GAS.Editor
|
||||
[OnValueChanged("SaveAsset")]
|
||||
public string GASConfigAssetPath = "Assets/GAS/Config";
|
||||
|
||||
[BoxGroup("A")]
|
||||
[LabelText("二进制配置文件生成路径")]
|
||||
[LabelWidth(LABEL_WIDTH)]
|
||||
[FolderPath]
|
||||
[OnValueChanged("SaveAsset")]
|
||||
public string GASBinaryAssetPath = "Assets/GAS/Binary";
|
||||
|
||||
[BoxGroup("A")]
|
||||
[LabelText("业务脚本生成路径")]
|
||||
[LabelWidth(LABEL_WIDTH)]
|
||||
[FolderPath]
|
||||
[OnValueChanged("SaveAsset")]
|
||||
public string LogicCodeGeneratePath = "Assets/Scripts/Gen";
|
||||
|
||||
[BoxGroup("A")]
|
||||
[LabelText("业务脚本Assembly")]
|
||||
[LabelWidth(LABEL_WIDTH)]
|
||||
public List<string> LogicCodeGenerateAssemblies = new List<string>();
|
||||
|
||||
public static GASSettingAsset Setting
|
||||
{
|
||||
get
|
||||
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c8eb15d90924617af4759059f71843b
|
||||
timeCreated: 1729496573
|
@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using GAS.Runtime;
|
||||
using JNGame.Tools.CodeGen;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// AbilityTask枚举和构造工厂方法注册代码生成
|
||||
/// </summary>
|
||||
public class CodeGenAbilityTaskInjecter
|
||||
{
|
||||
private static readonly string s_CodeTemplate = @"
|
||||
// auto generate by tools, DO NOT Modify it!!!
|
||||
|
||||
using GAS.Runtime;
|
||||
|
||||
namespace ##NAMESPACE
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏业务逻辑扩展的AbilityTask枚举
|
||||
/// </summary>
|
||||
public enum EnumGameAbilityTaskType
|
||||
{
|
||||
##CODEREPLACE_0
|
||||
}
|
||||
|
||||
#region AbilityTask构造工厂方法注册
|
||||
|
||||
public partial class GASInjector
|
||||
{
|
||||
private partial void InternalAbilityTaskInject()
|
||||
{
|
||||
##CODEREPLACE_1
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AbilityTask枚举ID自动生成
|
||||
|
||||
##CODEREPLACE_2
|
||||
|
||||
#endregion
|
||||
|
||||
}";
|
||||
|
||||
public static void GenCode(CodeGenInfo info)
|
||||
{
|
||||
string prefix = "\t";
|
||||
var contextTemplates = new List<string>()
|
||||
{
|
||||
prefix + prefix + "##TYPE_NAME = ##INDEX,",
|
||||
prefix + prefix + prefix + "AbilityTaskFactory.Register((ushort)EnumGameAbilityTaskType.##TYPE_NAME, () => new ##FULL_TYPE_NAME());",
|
||||
prefix + "public partial class ##TYPE_NAME { public override ushort TypeId => (ushort)EnumGameAbilityTaskType.##TYPE_NAME; }"
|
||||
};
|
||||
|
||||
var types = info.allTypes.ToArray().ToList();
|
||||
types.Sort((a, b) => a.Name.CompareTo(b.Name));
|
||||
var finalStr = s_CodeTemplate.Replace("##NAMESPACE", info.codeGenNameSpace);
|
||||
for (int i = 0; i < contextTemplates.Count; i++)
|
||||
{
|
||||
finalStr = finalStr.Replace("##CODEREPLACE_" + i, GenCodeByTemplate(types, contextTemplates[i]));
|
||||
}
|
||||
|
||||
var path = info.outputPath;
|
||||
FileUtil.SaveFile(path, finalStr);
|
||||
}
|
||||
|
||||
private static string GenCodeByTemplate(List<Type> types, string template)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int counterInstantTask = 0;
|
||||
int counterOngoingTask = 0;
|
||||
int counterPassiveTask = 0;
|
||||
for (int i = 0; i < types.Count; i++)
|
||||
{
|
||||
var type = types[i];
|
||||
string index;
|
||||
if (type.IsSubclassOf(typeof(InstantAbilityTask)))
|
||||
{
|
||||
index = ((int)EnumAbilityTaskType.InstantTaskStart + (++counterInstantTask)).ToString();
|
||||
}
|
||||
else if (type.IsSubclassOf(typeof(OngoingAbilityTask)))
|
||||
{
|
||||
index = ((int)EnumAbilityTaskType.OngoingTaskStart + (++counterOngoingTask)).ToString();
|
||||
}
|
||||
else if(type.IsSubclassOf(typeof(PassiveAbilityTask)))
|
||||
{
|
||||
index = ((int)EnumAbilityTaskType.PassiveTaskStart + (++counterPassiveTask)).ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"AbilityTask的类型不是 InstantAbilityTask /OngoingAbilityTask / PassiveAbilityTask 任意一种,{type.FullName}");
|
||||
continue;
|
||||
}
|
||||
var typeName = type.Name.ToString();
|
||||
var fullTypeName = type.FullName.ToString();
|
||||
var str = template.Replace("##INDEX", index).Replace("##TYPE_NAME", typeName).Replace("##FULL_TYPE_NAME", fullTypeName);
|
||||
sb.AppendLine(str);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdc093094756c434781a2996f811416d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,127 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using JNGame.Tools.CodeGen;
|
||||
|
||||
namespace GAS.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 行为树节点序列化相关代码生成
|
||||
/// </summary>
|
||||
public class CodeGenAbilityTaskSerialization
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码文件头部模板代码
|
||||
/// </summary>
|
||||
private static readonly string s_CodeHeaderTemplate = @"
|
||||
// auto generate by tools, DO NOT Modify it!!!
|
||||
|
||||
using GAS.Runtime;
|
||||
using JNGame.Serialization;
|
||||
";
|
||||
|
||||
/// <summary>
|
||||
/// 类模板代码
|
||||
/// </summary>
|
||||
private static readonly string s_ClsTemplate = @"
|
||||
namespace ##NAMESPACE
|
||||
{
|
||||
public partial class ##TYPE_NAME
|
||||
{
|
||||
public override void Serialize(Serializer writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
##CODEREPLACE_0
|
||||
}
|
||||
|
||||
public override void Deserialize(Deserializer reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
##CODEREPLACE_1
|
||||
}
|
||||
}
|
||||
}
|
||||
";
|
||||
|
||||
private static readonly BindingFlags s_BindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly;
|
||||
|
||||
public static void GenCode(CodeGenInfo info)
|
||||
{
|
||||
string prefix = "\t\t\t";
|
||||
var types = info.allTypes.ToArray().ToList();
|
||||
types.Sort((a, b) => a.Name.CompareTo(b.Name));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (var type in types)
|
||||
{
|
||||
var clsStr = GenCodeByTemplate(type, s_ClsTemplate);
|
||||
var contextTemplates = new List<CodeGenTemplateInfo>()
|
||||
{
|
||||
new CodeGenTemplateInfo()
|
||||
{
|
||||
Default = prefix + "writer.Write(##NAME);",
|
||||
Enum = prefix + "writer.Write((int)##NAME);", // TODO deal with array list &dict
|
||||
Array = prefix + "writer.WriteArray(##NAME);",
|
||||
},
|
||||
new CodeGenTemplateInfo()
|
||||
{
|
||||
Default = prefix + "##NAME = reader.Read##TYPE_NAME();",
|
||||
Enum = prefix + "##NAME = (##TYPE_NAME)reader.ReadInt32();",
|
||||
Array = prefix + "##NAME = reader.ReadArray(new ##ELEMENT_TYPE_NAME());",
|
||||
},
|
||||
};
|
||||
var fields = type.GetFields(s_BindingFlags)
|
||||
.Select(a => new CodeGenFieldInfo() { name = a.Name, type = a.FieldType }).ToList();
|
||||
// var properties = type.GetProperties(s_BindingFlags).Where(a => a.CanRead && a.CanWrite)
|
||||
// .Select(a => new CodeGenFieldInfo() { name = a.Name, type = a.PropertyType }).ToList();
|
||||
// fields.AddRange(properties);
|
||||
for (int i = 0; i < contextTemplates.Count; i++)
|
||||
{
|
||||
clsStr = clsStr.Replace("##CODEREPLACE_" + i, GetFieldsCode(fields, contextTemplates[i]));
|
||||
}
|
||||
|
||||
if (fields.Count > 0)
|
||||
{
|
||||
sb.AppendLine(clsStr);
|
||||
}
|
||||
}
|
||||
|
||||
var finalStr = s_CodeHeaderTemplate;
|
||||
finalStr += sb.ToString();
|
||||
var path = info.outputPath;
|
||||
FileUtil.SaveFile(path, finalStr);
|
||||
}
|
||||
|
||||
private static string GetFieldsCode(List<CodeGenFieldInfo> fields, CodeGenTemplateInfo template)
|
||||
{
|
||||
StringBuilder sbField = new StringBuilder();
|
||||
foreach (var field in fields)
|
||||
{
|
||||
var templateStr = template.GetTemplateStr(field);
|
||||
string elementTypeName = "";
|
||||
if(field.IsArray || field.IsList)
|
||||
{
|
||||
elementTypeName = field.type.GetElementType().Name;
|
||||
}
|
||||
var str = templateStr.Replace("##NAME", field.name).Replace("##TYPE_NAME", field.TypeName).Replace("##FULL_TYPE_NAME", field.FullTypeName)
|
||||
.Replace("##ELEMENT_TYPE_NAME", elementTypeName);
|
||||
sbField.AppendLine(str);
|
||||
}
|
||||
|
||||
return sbField.ToString();
|
||||
}
|
||||
|
||||
private static string GenCodeByTemplate(Type type, string template)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var nameSpace = type.Namespace.ToString();
|
||||
var typeName = type.Name.ToString();
|
||||
var fullTypeName = type.FullName.ToString();
|
||||
var str = template.Replace("##NAMESPACE", nameSpace).Replace("##TYPE_NAME", typeName).Replace("##FULL_TYPE_NAME", fullTypeName);
|
||||
sb.AppendLine(str);
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d06f987f50f2b6947beba00d4c7be0b3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,59 @@
|
||||
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using JNGame.Tools.CodeGen;
|
||||
|
||||
namespace GAS.Editor
|
||||
{
|
||||
public class CodeGenGELib
|
||||
{
|
||||
private static readonly string s_CodeTemplate = @"
|
||||
// auto generate by tools, DO NOT Modify it!!!
|
||||
|
||||
using GAS.Runtime;
|
||||
|
||||
namespace ##NAMESPACE
|
||||
{
|
||||
#region GE索引自动导出
|
||||
|
||||
public static class GELib
|
||||
{
|
||||
##CODEREPLACE_0
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}";
|
||||
|
||||
public static void GenCode(List<string> allGEAssetNames, string codeGenNameSpace, string outputPath)
|
||||
{
|
||||
string prefix = "\t\t";
|
||||
var contextTemplates = new List<string>()
|
||||
{
|
||||
prefix + "public static readonly string ##FILE_NAME = \"##UNIQUE_KEY\";"
|
||||
};
|
||||
|
||||
var finalStr = s_CodeTemplate.Replace("##NAMESPACE", codeGenNameSpace);
|
||||
for (int i = 0; i < contextTemplates.Count; i++)
|
||||
{
|
||||
finalStr = finalStr.Replace("##CODEREPLACE_" + i, GenCodeByTemplate(allGEAssetNames, contextTemplates[i]));
|
||||
}
|
||||
|
||||
var path = outputPath;
|
||||
FileUtil.SaveFile(path, finalStr);
|
||||
}
|
||||
|
||||
private static string GenCodeByTemplate(List<string> allGEAssetNames, string template)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < allGEAssetNames.Count; ++i)
|
||||
{
|
||||
var str = template.Replace("##FILE_NAME", allGEAssetNames[i]).Replace("##UNIQUE_KEY", allGEAssetNames[i]);
|
||||
sb.AppendLine(str);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43f0c08a89a7fef4da5be7b154a90b57
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using GAS.Runtime;
|
||||
using JNGame.Tools.CodeGen;
|
||||
|
||||
namespace GAS.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// MMC枚举和构造工厂方法注册代码生成
|
||||
/// </summary>
|
||||
public class CodeGenPureMMCInjecter
|
||||
{
|
||||
private static readonly string s_CodeTemplate = @"
|
||||
// auto generate by tools, DO NOT Modify it!!!
|
||||
|
||||
using GAS.Runtime;
|
||||
|
||||
namespace ##NAMESPACE
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏业务逻辑扩展的MMC枚举
|
||||
/// </summary>
|
||||
public enum EnumGameMMCType
|
||||
{
|
||||
##CODEREPLACE_0
|
||||
}
|
||||
|
||||
#region MMC构造工厂方法注册
|
||||
|
||||
public partial class GASInjector
|
||||
{
|
||||
private partial void InternalMMCInject()
|
||||
{
|
||||
##CODEREPLACE_1
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MMC枚举ID自动生成
|
||||
|
||||
##CODEREPLACE_2
|
||||
|
||||
#endregion
|
||||
|
||||
}";
|
||||
|
||||
public static void GenCode(CodeGenInfo info)
|
||||
{
|
||||
string prefix = "\t";
|
||||
var contextTemplates = new List<string>()
|
||||
{
|
||||
prefix + prefix + "##TYPE_NAME = ##INDEX,",
|
||||
prefix + prefix + prefix + "MMCFactory.Register((ushort)EnumGameMMCType.##TYPE_NAME, () => new ##FULL_TYPE_NAME());",
|
||||
prefix + "public partial class ##TYPE_NAME { public override ushort TypeId => (ushort)EnumGameMMCType.##TYPE_NAME; }"
|
||||
};
|
||||
|
||||
var types = info.allTypes.ToArray().ToList();
|
||||
types.Sort((a, b) => a.Name.CompareTo(b.Name));
|
||||
var finalStr = s_CodeTemplate.Replace("##NAMESPACE", info.codeGenNameSpace);
|
||||
for (int i = 0; i < contextTemplates.Count; i++)
|
||||
{
|
||||
finalStr = finalStr.Replace("##CODEREPLACE_" + i, GenCodeByTemplate(types, contextTemplates[i]));
|
||||
}
|
||||
|
||||
var path = info.outputPath;
|
||||
FileUtil.SaveFile(path, finalStr);
|
||||
}
|
||||
|
||||
private static string GenCodeByTemplate(List<Type> types, string template)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < types.Count; i++)
|
||||
{
|
||||
var type = types[i];
|
||||
string index = ((int)EnumMMCType.EnumBuiltinCount + i + 1).ToString();
|
||||
var typeName = type.Name.ToString();
|
||||
var fullTypeName = type.FullName.ToString();
|
||||
var str = template.Replace("##INDEX", index).Replace("##TYPE_NAME", typeName).Replace("##FULL_TYPE_NAME", fullTypeName);
|
||||
sb.AppendLine(str);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f93cd40e5f55ae4bad291b74a82898b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,122 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using JNGame.Tools.CodeGen;
|
||||
|
||||
namespace GAS.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 行为树节点序列化相关代码生成
|
||||
/// </summary>
|
||||
public class CodeGenPureMMCSerialization
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码文件头部模板代码
|
||||
/// </summary>
|
||||
private static readonly string s_CodeHeaderTemplate = @"
|
||||
// auto generate by tools, DO NOT Modify it!!!
|
||||
|
||||
using GAS.Runtime;
|
||||
using JNGame.Serialization;
|
||||
";
|
||||
|
||||
/// <summary>
|
||||
/// 类模板代码
|
||||
/// </summary>
|
||||
private static readonly string s_ClsTemplate = @"
|
||||
namespace ##NAMESPACE
|
||||
{
|
||||
public partial class ##TYPE_NAME
|
||||
{
|
||||
public override void Serialize(Serializer writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
##CODEREPLACE_0
|
||||
}
|
||||
|
||||
public override void Deserialize(Deserializer reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
##CODEREPLACE_1
|
||||
}
|
||||
}
|
||||
}
|
||||
";
|
||||
|
||||
private static readonly BindingFlags s_BindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly;
|
||||
|
||||
public static void GenCode(CodeGenInfo info)
|
||||
{
|
||||
string prefix = "\t\t\t";
|
||||
var types = info.allTypes.ToArray().ToList();
|
||||
types.Sort((a, b) => a.Name.CompareTo(b.Name));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (var type in types)
|
||||
{
|
||||
var clsStr = GenCodeByTemplate(type, s_ClsTemplate);
|
||||
var contextTemplates = new List<CodeGenTemplateInfo>()
|
||||
{
|
||||
new CodeGenTemplateInfo()
|
||||
{
|
||||
Default = prefix + "writer.Write(##NAME);",
|
||||
Enum = prefix + "writer.Write((byte)##NAME);", // TODO deal with array list &dict
|
||||
},
|
||||
new CodeGenTemplateInfo()
|
||||
{
|
||||
Default = prefix + "##NAME = reader.Read##TYPE_NAME();",
|
||||
Enum = prefix + "##NAME = (##TYPE_NAME)reader.ReadByte();",
|
||||
},
|
||||
};
|
||||
var fields = type.GetFields(s_BindingFlags)
|
||||
.Select(a => new CodeGenFieldInfo() { name = a.Name, type = a.FieldType }).ToList();
|
||||
for (int i = 0; i < contextTemplates.Count; i++)
|
||||
{
|
||||
clsStr = clsStr.Replace("##CODEREPLACE_" + i, GetFieldsCode(fields, contextTemplates[i]));
|
||||
}
|
||||
|
||||
if (fields.Count > 0)
|
||||
{
|
||||
sb.AppendLine(clsStr);
|
||||
}
|
||||
}
|
||||
|
||||
var finalStr = s_CodeHeaderTemplate;
|
||||
finalStr += sb.ToString();
|
||||
var path = info.outputPath;
|
||||
FileUtil.SaveFile(path, finalStr);
|
||||
}
|
||||
|
||||
private static string GetFieldsCode(List<CodeGenFieldInfo> fields, CodeGenTemplateInfo template)
|
||||
{
|
||||
StringBuilder sbField = new StringBuilder();
|
||||
foreach (var field in fields)
|
||||
{
|
||||
var templateStr = template.GetTemplateStr(field);
|
||||
string elementTypeName = "";
|
||||
if(field.IsArray || field.IsList)
|
||||
{
|
||||
elementTypeName = field.type.GetElementType().Name;
|
||||
}
|
||||
var str = templateStr.Replace("##NAME", field.name).Replace("##TYPE_NAME", field.TypeName).Replace("##FULL_TYPE_NAME", field.FullTypeName)
|
||||
.Replace("##ELEMENT_TYPE_NAME", elementTypeName);
|
||||
sbField.AppendLine(str);
|
||||
}
|
||||
|
||||
return sbField.ToString();
|
||||
}
|
||||
|
||||
private static string GenCodeByTemplate(Type type, string template)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var nameSpace = type.Namespace.ToString();
|
||||
var typeName = type.Name.ToString();
|
||||
var fullTypeName = type.FullName.ToString();
|
||||
var str = template.Replace("##NAMESPACE", nameSpace).Replace("##TYPE_NAME", typeName).Replace("##FULL_TYPE_NAME", fullTypeName);
|
||||
sb.AppendLine(str);
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44b19adf34116394c99dd66de03bebde
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using GAS.Runtime;
|
||||
using JNGame.Tools.CodeGen;
|
||||
|
||||
namespace GAS.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// MMC枚举和构造工厂方法注册代码生成
|
||||
/// </summary>
|
||||
public class CodeGenScriptableMMCInjecter
|
||||
{
|
||||
private static readonly string s_CodeTemplate = @"
|
||||
// auto generate by tools, DO NOT Modify it!!!
|
||||
|
||||
using GAS.Runtime;
|
||||
|
||||
namespace ##NAMESPACE
|
||||
{
|
||||
#region MMC枚举ID自动生成
|
||||
|
||||
##CODEREPLACE_0
|
||||
|
||||
#endregion
|
||||
|
||||
}";
|
||||
|
||||
public static void GenCode(CodeGenInfo info)
|
||||
{
|
||||
string prefix = "\t";
|
||||
var contextTemplates = new List<string>()
|
||||
{
|
||||
prefix + "public partial class ##TYPE_NAME { public override ushort TypeId => (ushort)EnumGameMMCType.Pure##TYPE_NAME; }"
|
||||
};
|
||||
|
||||
var types = info.allTypes.ToArray().ToList();
|
||||
types.Sort((a, b) => a.Name.CompareTo(b.Name));
|
||||
var finalStr = s_CodeTemplate.Replace("##NAMESPACE", info.codeGenNameSpace);
|
||||
for (int i = 0; i < contextTemplates.Count; i++)
|
||||
{
|
||||
finalStr = finalStr.Replace("##CODEREPLACE_" + i, GenCodeByTemplate(types, contextTemplates[i]));
|
||||
}
|
||||
|
||||
var path = info.outputPath;
|
||||
FileUtil.SaveFile(path, finalStr);
|
||||
}
|
||||
|
||||
private static string GenCodeByTemplate(List<Type> types, string template)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < types.Count; i++)
|
||||
{
|
||||
var type = types[i];
|
||||
string index = ((int)EnumMMCType.EnumBuiltinCount + i + 1).ToString();
|
||||
var typeName = type.Name.ToString();
|
||||
var fullTypeName = type.FullName.ToString();
|
||||
var str = template.Replace("##INDEX", index).Replace("##TYPE_NAME", typeName).Replace("##FULL_TYPE_NAME", fullTypeName);
|
||||
sb.AppendLine(str);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be3b8b5fbf6288d489d2505ffb6c937b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,122 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using JNGame.Tools.CodeGen;
|
||||
|
||||
namespace GAS.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 行为树节点序列化相关代码生成
|
||||
/// </summary>
|
||||
public class CodeGenScriptableMMCSerialization
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码文件头部模板代码
|
||||
/// </summary>
|
||||
private static readonly string s_CodeHeaderTemplate = @"
|
||||
// auto generate by tools, DO NOT Modify it!!!
|
||||
|
||||
using GAS.Runtime;
|
||||
using JNGame.Serialization;
|
||||
";
|
||||
|
||||
/// <summary>
|
||||
/// 类模板代码
|
||||
/// </summary>
|
||||
private static readonly string s_ClsTemplate = @"
|
||||
namespace ##NAMESPACE
|
||||
{
|
||||
public partial class ##TYPE_NAME
|
||||
{
|
||||
public override void Serialize(Serializer writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
##CODEREPLACE_0
|
||||
}
|
||||
|
||||
public override void Deserialize(Deserializer reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
##CODEREPLACE_1
|
||||
}
|
||||
}
|
||||
}
|
||||
";
|
||||
|
||||
private static readonly BindingFlags s_BindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly;
|
||||
|
||||
public static void GenCode(CodeGenInfo info)
|
||||
{
|
||||
string prefix = "\t\t\t";
|
||||
var types = info.allTypes.ToArray().ToList();
|
||||
types.Sort((a, b) => a.Name.CompareTo(b.Name));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (var type in types)
|
||||
{
|
||||
var clsStr = GenCodeByTemplate(type, s_ClsTemplate);
|
||||
var contextTemplates = new List<CodeGenTemplateInfo>()
|
||||
{
|
||||
new CodeGenTemplateInfo()
|
||||
{
|
||||
Default = prefix + "writer.Write(##NAME);",
|
||||
Enum = prefix + "writer.Write((byte)##NAME);", // TODO deal with array list &dict
|
||||
},
|
||||
new CodeGenTemplateInfo()
|
||||
{
|
||||
Default = prefix + "##NAME = reader.Read##TYPE_NAME();",
|
||||
Enum = prefix + "##NAME = (##TYPE_NAME)reader.ReadByte();",
|
||||
},
|
||||
};
|
||||
var fields = type.GetFields(s_BindingFlags)
|
||||
.Select(a => new CodeGenFieldInfo() { name = a.Name, type = a.FieldType }).ToList();
|
||||
for (int i = 0; i < contextTemplates.Count; i++)
|
||||
{
|
||||
clsStr = clsStr.Replace("##CODEREPLACE_" + i, GetFieldsCode(fields, contextTemplates[i]));
|
||||
}
|
||||
|
||||
if (fields.Count > 0)
|
||||
{
|
||||
sb.AppendLine(clsStr);
|
||||
}
|
||||
}
|
||||
|
||||
var finalStr = s_CodeHeaderTemplate;
|
||||
finalStr += sb.ToString();
|
||||
var path = info.outputPath;
|
||||
FileUtil.SaveFile(path, finalStr);
|
||||
}
|
||||
|
||||
private static string GetFieldsCode(List<CodeGenFieldInfo> fields, CodeGenTemplateInfo template)
|
||||
{
|
||||
StringBuilder sbField = new StringBuilder();
|
||||
foreach (var field in fields)
|
||||
{
|
||||
var templateStr = template.GetTemplateStr(field);
|
||||
string elementTypeName = "";
|
||||
if(field.IsArray || field.IsList)
|
||||
{
|
||||
elementTypeName = field.type.GetElementType().Name;
|
||||
}
|
||||
var str = templateStr.Replace("##NAME", field.name).Replace("##TYPE_NAME", field.TypeName).Replace("##FULL_TYPE_NAME", field.FullTypeName)
|
||||
.Replace("##ELEMENT_TYPE_NAME", elementTypeName);
|
||||
sbField.AppendLine(str);
|
||||
}
|
||||
|
||||
return sbField.ToString();
|
||||
}
|
||||
|
||||
private static string GenCodeByTemplate(Type type, string template)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var nameSpace = type.Namespace.ToString();
|
||||
var typeName = type.Name.ToString();
|
||||
var fullTypeName = type.FullName.ToString();
|
||||
var str = template.Replace("##NAMESPACE", nameSpace).Replace("##TYPE_NAME", typeName).Replace("##FULL_TYPE_NAME", fullTypeName);
|
||||
sb.AppendLine(str);
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7b15c5efee61074f997ba552d608101
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,90 @@
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using GAS.Runtime;
|
||||
using JNGame.Tools.CodeGen;
|
||||
|
||||
namespace GAS.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 目标捕获器枚举和构造工厂方法注册代码生成
|
||||
/// </summary>
|
||||
public class CodeGenTargetCatcherInjecter
|
||||
{
|
||||
private static readonly string s_CodeTemplate = @"
|
||||
// auto generate by tools, DO NOT Modify it!!!
|
||||
|
||||
using GAS.Runtime;
|
||||
|
||||
namespace ##NAMESPACE
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏业务逻辑扩展的TargetCatcher枚举
|
||||
/// </summary>
|
||||
public enum EnumGameTargetCatcherType
|
||||
{
|
||||
##CODEREPLACE_0
|
||||
}
|
||||
|
||||
#region TargetCatcher构造工厂方法注册
|
||||
|
||||
public partial class GASInjector
|
||||
{
|
||||
private partial void InternalTargetCatcherInject()
|
||||
{
|
||||
##CODEREPLACE_1
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TargetCatcher枚举ID自动生成
|
||||
|
||||
##CODEREPLACE_2
|
||||
|
||||
#endregion
|
||||
|
||||
}";
|
||||
|
||||
public static void GenCode(CodeGenInfo info)
|
||||
{
|
||||
string prefix = "\t";
|
||||
var contextTemplates = new List<string>()
|
||||
{
|
||||
prefix + prefix + "##TYPE_NAME = ##INDEX,",
|
||||
prefix + prefix + prefix + "TargetCatcherFactory.Register((ushort)EnumGameTargetCatcherType.##TYPE_NAME, () => new ##FULL_TYPE_NAME());",
|
||||
prefix + "public partial class ##TYPE_NAME { public override ushort TypeId => (ushort)EnumGameTargetCatcherType.##TYPE_NAME; }"
|
||||
};
|
||||
|
||||
var types = info.allTypes.ToArray().ToList();
|
||||
types.Sort((a, b) => a.Name.CompareTo(b.Name));
|
||||
var finalStr = s_CodeTemplate.Replace("##NAMESPACE", info.codeGenNameSpace);
|
||||
for (int i = 0; i < contextTemplates.Count; i++)
|
||||
{
|
||||
finalStr = finalStr.Replace("##CODEREPLACE_" + i, GenCodeByTemplate(types, contextTemplates[i]));
|
||||
}
|
||||
|
||||
var path = info.outputPath;
|
||||
FileUtil.SaveFile(path, finalStr);
|
||||
}
|
||||
|
||||
private static string GenCodeByTemplate(List<Type> types, string template)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < types.Count; i++)
|
||||
{
|
||||
var type = types[i];
|
||||
string index = ((int)EnumTargetCatcherType.EnumBuiltinCount + i + 1).ToString();
|
||||
var typeName = type.Name.ToString();
|
||||
var fullTypeName = type.FullName.ToString();
|
||||
var str = template.Replace("##INDEX", index).Replace("##TYPE_NAME", typeName).Replace("##FULL_TYPE_NAME", fullTypeName);
|
||||
sb.AppendLine(str);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9417a4dacd34d1f438b3a1583dea58de
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f879d96e563108c45ab0cfa0ffc025f8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,338 @@
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using GAS.Runtime;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using JNGame.Tools.CodeGen;
|
||||
using JNGame.Serialization;
|
||||
using FileUtil = JNGame.Tools.CodeGen.FileUtil;
|
||||
|
||||
namespace GAS.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 纯净模式GAS的编辑器工具
|
||||
/// </summary>
|
||||
public static class PureGASEditorTools
|
||||
{
|
||||
/// <summary>
|
||||
/// GAS纯净模式代码生成入口
|
||||
/// </summary>
|
||||
[MenuItem("EX-GAS/PureMode/GenCode/All")]
|
||||
public static void GenCode()
|
||||
{
|
||||
GenCode_AbilityTaskBase();
|
||||
GenCode_TargetCatcherBase();
|
||||
GenCode_MMC();
|
||||
GenCode_GELib();
|
||||
}
|
||||
|
||||
[MenuItem("EX-GAS/PureMode/GenCode/AbilityTask")]
|
||||
public static void GenCode_AbilityTaskBase()
|
||||
{
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
GASSettingAsset gasSetting = GASSettingAsset.Setting;
|
||||
List<Type> subTypeFromAbilityTaskBase = new List<Type>();
|
||||
for (var i = 0; i < assemblies.Length; ++i)
|
||||
{
|
||||
var assembly = assemblies[i];
|
||||
if (assembly == null) { continue; }
|
||||
var assName = assembly.GetName().Name;
|
||||
if (!gasSetting.LogicCodeGenerateAssemblies.Contains(assName)) { continue; }
|
||||
// 筛选非抽象的AbilityTaskBase派生类
|
||||
var lst = assembly.GetTypes().Where(
|
||||
clsType => !clsType.IsAbstract && clsType.IsSubclassOf(typeof(AbilityTaskBase))
|
||||
);
|
||||
subTypeFromAbilityTaskBase.AddRange(lst);
|
||||
}
|
||||
|
||||
var dir = gasSetting.LogicCodeGeneratePath;
|
||||
// 自动生成AbilityTask枚举和工厂注入方法
|
||||
CodeGenAbilityTaskInjecter.GenCode(new CodeGenInfo()
|
||||
{
|
||||
codeGenNameSpace = "JNGame.GAS",
|
||||
outputPath = Path.Combine(dir, "CodeGen_AbilityTaskExt.cs"),
|
||||
allTypes = subTypeFromAbilityTaskBase
|
||||
});
|
||||
// 自动生成AbilityTask序列化相关代码
|
||||
CodeGenAbilityTaskSerialization.GenCode(new CodeGenInfo()
|
||||
{
|
||||
codeGenNameSpace = "JNGame.GAS",
|
||||
outputPath = Path.Combine(dir, "CodeGen_AbilityTaskExtSerialization.cs"),
|
||||
allTypes = subTypeFromAbilityTaskBase
|
||||
});
|
||||
}
|
||||
|
||||
[MenuItem("EX-GAS/PureMode/GenCode/TargetCatcher")]
|
||||
public static void GenCode_TargetCatcherBase()
|
||||
{
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
GASSettingAsset gasSetting = GASSettingAsset.Setting;
|
||||
List<Type> subTypeFromTargetCatcherBase = new List<Type>();
|
||||
for (var i = 0; i < assemblies.Length; ++i)
|
||||
{
|
||||
var assembly = assemblies[i];
|
||||
if (assembly == null) { continue; }
|
||||
var assName = assembly.GetName().Name;
|
||||
if (!gasSetting.LogicCodeGenerateAssemblies.Contains(assName)) { continue; }
|
||||
// 筛选非抽象的TargetCatcherBase派生类
|
||||
var lst = assembly.GetTypes().Where(
|
||||
clsType => !clsType.IsAbstract && clsType.IsSubclassOf(typeof(TargetCatcherBase))
|
||||
);
|
||||
subTypeFromTargetCatcherBase.AddRange(lst);
|
||||
}
|
||||
// 自动生成TargetCatcher枚举和工厂注入方法
|
||||
var dir = gasSetting.LogicCodeGeneratePath;
|
||||
CodeGenTargetCatcherInjecter.GenCode(new CodeGenInfo()
|
||||
{
|
||||
codeGenNameSpace = "JNGame.GAS",
|
||||
outputPath = Path.Combine(dir, "CodeGen_TaregetCatcherExt.cs"),
|
||||
allTypes = subTypeFromTargetCatcherBase
|
||||
});
|
||||
}
|
||||
|
||||
[MenuItem("EX-GAS/PureMode/GenCode/GELib")]
|
||||
public static void GenCode_GELib()
|
||||
{
|
||||
var dir = GASSettingAsset.Setting.LogicCodeGeneratePath;
|
||||
var guids = AssetDatabase.FindAssets($"t:{nameof(GameplayEffectAsset)}");
|
||||
List<string> allGENames = new List<string>(guids.Length);
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
// 加载Scriptable配置,并且序列化为bytes
|
||||
var geAsset = AssetDatabase.LoadAssetAtPath<GameplayEffectAsset>(path);
|
||||
allGENames.Add(geAsset.name);
|
||||
}
|
||||
CodeGenGELib.GenCode(allGENames, "JNGame.GAS", Path.Combine(dir, "CodeGen_GELib.cs"));
|
||||
}
|
||||
|
||||
[MenuItem("EX-GAS/PureMode/GenCode/MMC")]
|
||||
public static void GenCode_MMC()
|
||||
{
|
||||
GenCode_PureMMC();
|
||||
GenCode_ScriptableMMC();
|
||||
}
|
||||
|
||||
public static void GenCode_PureMMC()
|
||||
{
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
GASSettingAsset gasSetting = GASSettingAsset.Setting;
|
||||
List<Type> subTypeFromPureMMC = new List<Type>();
|
||||
List<Type> subTypeFromScriptableMMC = new List<Type>();
|
||||
List<string> outFilter = new List<string>() {
|
||||
"AttrBasedWithStackModCalculation",
|
||||
"AttributeBasedModCalculation",
|
||||
"ScalableFloatModCalculation",
|
||||
"StackModCalculation",
|
||||
};
|
||||
for (var i = 0; i < assemblies.Length; ++i)
|
||||
{
|
||||
var assembly = assemblies[i];
|
||||
if (assembly == null) { continue; }
|
||||
var assName = assembly.GetName().Name;
|
||||
if (!gasSetting.LogicCodeGenerateAssemblies.Contains(assName)) { continue; }
|
||||
// 筛选非抽象的PureModifierMagnitudeCalculation派生类
|
||||
var lst = assembly.GetTypes().Where(
|
||||
clsType => !clsType.IsAbstract && clsType.IsSubclassOf(typeof(PureModifierMagnitudeCalculation)) && outFilter.IndexOf(clsType.Name) < 0
|
||||
);
|
||||
subTypeFromPureMMC.AddRange(lst);
|
||||
}
|
||||
var dir = gasSetting.LogicCodeGeneratePath;
|
||||
CodeGenPureMMCInjecter.GenCode(new CodeGenInfo()
|
||||
{
|
||||
codeGenNameSpace = "JNGame.GAS",
|
||||
outputPath = Path.Combine(dir, "CodeGen_PureMMCExt.cs"),
|
||||
allTypes = subTypeFromPureMMC
|
||||
});
|
||||
CodeGenPureMMCSerialization.GenCode(new CodeGenInfo()
|
||||
{
|
||||
codeGenNameSpace = "JNGame.GAS",
|
||||
outputPath = Path.Combine(dir, "CodeGen_PureMMCExtSerialization.cs"),
|
||||
allTypes = subTypeFromPureMMC
|
||||
});
|
||||
}
|
||||
|
||||
public static void GenCode_ScriptableMMC()
|
||||
{
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
GASSettingAsset gasSetting = GASSettingAsset.Setting;
|
||||
List<Type> subTypeFromScriptableMMC = new List<Type>();
|
||||
|
||||
List<string> outFilter = new List<string>() {
|
||||
"AttrBasedWithStackModCalculation",
|
||||
"AttributeBasedModCalculation",
|
||||
"ScalableFloatModCalculation",
|
||||
"StackModCalculation",
|
||||
};
|
||||
for (var i = 0; i < assemblies.Length; ++i)
|
||||
{
|
||||
var assembly = assemblies[i];
|
||||
if (assembly == null) { continue; }
|
||||
var assName = assembly.GetName().Name;
|
||||
if (!"GAS.UnityExt.Runtime".Equals(assName)) { continue; }
|
||||
// 筛选非抽象的ModifierMagnitudeCalculation派生类
|
||||
var lst = assembly.GetTypes().Where(
|
||||
clsType => !clsType.IsAbstract && clsType.IsSubclassOf(typeof(ModifierMagnitudeCalculation)) && outFilter.IndexOf(clsType.Name) < 0
|
||||
);
|
||||
subTypeFromScriptableMMC.AddRange(lst);
|
||||
}
|
||||
var dir = "Assets/GameScript/HotFix/GAS.UnityExt/Runtime/CodeGen";// gasSetting.LogicCodeGeneratePath;
|
||||
CodeGenScriptableMMCInjecter.GenCode(new CodeGenInfo()
|
||||
{
|
||||
codeGenNameSpace = "JNGame.GAS",
|
||||
outputPath = Path.Combine(dir, "CodeGen_ScriptableMMCExt.cs"),
|
||||
allTypes = subTypeFromScriptableMMC
|
||||
});
|
||||
CodeGenScriptableMMCSerialization.GenCode(new CodeGenInfo()
|
||||
{
|
||||
codeGenNameSpace = "JNGame.GAS",
|
||||
outputPath = Path.Combine(dir, "CodeGen_ScriptableMMCExtSerialization.cs"),
|
||||
allTypes = subTypeFromScriptableMMC
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GAS纯净模式二进制配置生成入口
|
||||
/// </summary>
|
||||
[MenuItem("EX-GAS/PureMode/GenData/All")]
|
||||
public static void GenData()
|
||||
{
|
||||
GenGAData();
|
||||
GenGEData();
|
||||
GenASCPresetData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GAS纯净模式 - 二进制Ability配置生成入口
|
||||
/// </summary>
|
||||
/// <param name="genPath"></param>
|
||||
[MenuItem("EX-GAS/PureMode/GenData/AbilityAsset")]
|
||||
public static void GenGAData()
|
||||
{
|
||||
|
||||
string saveDir = GASSettingAsset.Setting.GASBinaryAssetPath;
|
||||
var guids = AssetDatabase.FindAssets($"t:{nameof(TimelineAbilityAsset)}");
|
||||
int exportCount = 0;
|
||||
int failedCount = 0;
|
||||
Dictionary<string, byte[]> allGAAssets = new Dictionary<string, byte[]>();
|
||||
Serializer serializer = new Serializer();
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
exportCount++;
|
||||
// 加载Scriptable配置,并且序列化为bytes
|
||||
var timelineAsset = AssetDatabase.LoadAssetAtPath<TimelineAbilityAsset>(path);
|
||||
// var bytes = timelineAsset.ToBytes();
|
||||
// // 反序列为纯净模式配置,并再次序列化为二进制数据,检查两次序列化数据是否一致
|
||||
// var newInfo = AbilityAssetTool.Deserialize(bytes);
|
||||
// var newBytes = AbilityAssetTool.Serialize(newInfo);
|
||||
// bool isSame = newBytes.EqualsEx(bytes);
|
||||
// if (!isSame)
|
||||
// {
|
||||
// Debug.LogError($"TimelineAsset Serialize Failed {path}");
|
||||
// ++failedCount;
|
||||
// continue;
|
||||
// }
|
||||
// allGAAssets.Add(timelineAsset.name, bytes);
|
||||
}
|
||||
// 整合成一个二进制文件
|
||||
serializer.Write((ushort)allGAAssets.Count);
|
||||
foreach (var iter in allGAAssets)
|
||||
{
|
||||
serializer.Append(iter.Value);
|
||||
}
|
||||
FileUtil.SaveFile(Path.Combine(saveDir, "GA_Database.bytes"), serializer.CopyData());
|
||||
Debug.Log($"Export Done count= {exportCount}, Failed count = {failedCount}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GAS纯净模式 - 二进制GE配置生成入口
|
||||
/// </summary>
|
||||
/// <param name="genPath"></param>
|
||||
[MenuItem("EX-GAS/PureMode/GenData/GEAsset")]
|
||||
public static void GenGEData()
|
||||
{
|
||||
string saveDir = GASSettingAsset.Setting.GASBinaryAssetPath;
|
||||
var guids = AssetDatabase.FindAssets($"t:{nameof(GameplayEffectAsset)}");
|
||||
int exportCount = 0;
|
||||
int failedCount = 0;
|
||||
Dictionary<string, byte[]> allGEAssets = new Dictionary<string, byte[]>();
|
||||
Serializer serializer = new Serializer();
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
exportCount++;
|
||||
// 加载Scriptable配置,并且序列化为bytes
|
||||
var geAsset = AssetDatabase.LoadAssetAtPath<GameplayEffectAsset>(path);
|
||||
// var bytes = geAsset.ToBytes();
|
||||
// // 反序列为纯净模式配置,并再次序列化为二进制数据,检查两次序列化数据是否一致
|
||||
// var newInfo = GameEffectAssetSerializationTool.Deserialize(bytes);
|
||||
// var newBytes = GameEffectAssetSerializationTool.Serialize(newInfo);
|
||||
// bool isSame = newBytes.EqualsEx(bytes);
|
||||
// if (!isSame)
|
||||
// {
|
||||
// Debug.LogError($"TimelineAsset Serialize Failed {path}");
|
||||
// ++failedCount;
|
||||
// continue;
|
||||
// }
|
||||
// allGEAssets.Add(geAsset.name, bytes);
|
||||
}
|
||||
// 整合成一个二进制文件
|
||||
serializer.Write((ushort)allGEAssets.Count);
|
||||
foreach (var iter in allGEAssets)
|
||||
{
|
||||
serializer.Append(iter.Value);
|
||||
}
|
||||
FileUtil.SaveFile(Path.Combine(saveDir, "GE_Database.bytes"), serializer.CopyData());
|
||||
Debug.Log($"Export Done count= {exportCount}, Failed count = {failedCount}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GAS纯净模式 - 二进制GASPreset配置生成入口
|
||||
/// </summary>
|
||||
[MenuItem("EX-GAS/PureMode/GenData/ASCPreset")]
|
||||
public static void GenASCPresetData()
|
||||
{
|
||||
string saveDir = GASSettingAsset.Setting.GASBinaryAssetPath;
|
||||
var guids = AssetDatabase.FindAssets($"t:{nameof(AbilitySystemComponentPreset)}");
|
||||
int exportCount = 0;
|
||||
int failedCount = 0;
|
||||
Dictionary<string, byte[]> allASCPresets = new Dictionary<string, byte[]>();
|
||||
Serializer serializer = new Serializer();
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
exportCount++;
|
||||
// 加载Scriptable配置,并且序列化为bytes
|
||||
var ascPresetAsset = AssetDatabase.LoadAssetAtPath<AbilitySystemComponentPreset>(path);
|
||||
// var bytes = ascPresetAsset.ToBytes();
|
||||
// // 反序列为纯净模式配置,并再次序列化为二进制数据,检查两次序列化数据是否一致
|
||||
// var newInfo = AbilitySystemComponentPresetConverter.Deserialize(bytes);
|
||||
// var newBytes = AbilitySystemComponentPresetConverter.Serialize(newInfo);
|
||||
// bool isSame = newBytes.EqualsEx(bytes);
|
||||
// if (!isSame)
|
||||
// {
|
||||
// Debug.LogError($"TimelineAsset Serialize Failed {path}");
|
||||
// ++failedCount;
|
||||
// continue;
|
||||
// }
|
||||
// allASCPresets.Add(ascPresetAsset.name, bytes);
|
||||
}
|
||||
// 整合成一个二进制文件
|
||||
serializer.Write((ushort)allASCPresets.Count);
|
||||
foreach (var iter in allASCPresets)
|
||||
{
|
||||
serializer.Append(iter.Value);
|
||||
}
|
||||
FileUtil.SaveFile(Path.Combine(saveDir, "ASC_Database.bytes"), serializer.CopyData());
|
||||
Debug.Log($"Export Done count= {exportCount}, Failed count = {failedCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a832c435436925438d1e3859b98902c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -2,6 +2,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using GAS.Runtime;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
@ -14,24 +15,31 @@ namespace GAS.General
|
||||
|
||||
public class JexGasObjectPool
|
||||
{
|
||||
private static JexGasObjectPool _singleton;
|
||||
|
||||
public static JexGasObjectPool Instance => _singleton ??= new JexGasObjectPool();
|
||||
// private static JexGasObjectPool _singleton;
|
||||
//
|
||||
// public static JexGasObjectPool Instance => _singleton ??= new JexGasObjectPool();
|
||||
|
||||
public JexGasManager Manager;
|
||||
|
||||
public JexGasObjectPool(JexGasManager manager)
|
||||
{
|
||||
Manager = manager;
|
||||
}
|
||||
|
||||
private readonly ConcurrentDictionary<Type, Pool> _objPool = new();
|
||||
|
||||
private readonly Func<Type, Pool> _addPoolFunc = type => new Pool(type, 1024);
|
||||
|
||||
public static void Awake()
|
||||
{
|
||||
_singleton = null;
|
||||
_singleton = new JexGasObjectPool();
|
||||
}
|
||||
|
||||
public static void Destroy()
|
||||
{
|
||||
_singleton = null;
|
||||
}
|
||||
// public static void Awake()
|
||||
// {
|
||||
// _singleton = null;
|
||||
// _singleton = new JexGasObjectPool();
|
||||
// }
|
||||
//
|
||||
// public static void Destroy()
|
||||
// {
|
||||
// _singleton = null;
|
||||
// }
|
||||
|
||||
public T Fetch<T>() where T : class
|
||||
{
|
||||
|
@ -16,7 +16,7 @@ namespace GAS.Runtime
|
||||
|
||||
public void Tick(int dt)
|
||||
{
|
||||
var abilitySpecs = JexGasObjectPool.Instance.Fetch<List<AbilitySpec>>();
|
||||
var abilitySpecs = _owner.GetManager().ObjectPool.Fetch<List<AbilitySpec>>();
|
||||
abilitySpecs.AddRange(_abilities.Values);
|
||||
|
||||
foreach (var abilitySpec in abilitySpecs)
|
||||
@ -25,7 +25,7 @@ namespace GAS.Runtime
|
||||
}
|
||||
|
||||
abilitySpecs.Clear();
|
||||
JexGasObjectPool.Instance.Recycle(abilitySpecs);
|
||||
_owner.GetManager().ObjectPool.Recycle(abilitySpecs);
|
||||
}
|
||||
|
||||
public void GrantAbility(AbstractAbility ability)
|
||||
|
@ -1,10 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public struct AbilityInstanceInfo
|
||||
{
|
||||
public AbilityAsset abilityAsset;
|
||||
public Type abilityType;
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99ad85c3caba4604b9950ae1105e85b4
|
||||
timeCreated: 1706090943
|
@ -28,8 +28,8 @@ namespace GAS.Runtime
|
||||
Tag = new AbilityTagContainer(
|
||||
DataReference.AssetTags, DataReference.CancelAbilityTags, DataReference.BlockAbilityTags,
|
||||
DataReference.ActivationOwnedTags, DataReference.ActivationRequiredTags, DataReference.ActivationBlockedTags);
|
||||
Cooldown = DataReference.Cooldown ? DataReference.Cooldown.SharedInstance : default;
|
||||
Cost = DataReference.Cost ? DataReference.Cost.SharedInstance: default;
|
||||
Cooldown = DataReference.Cooldown?.SharedInstance();
|
||||
Cost = DataReference.Cost?.SharedInstance();
|
||||
|
||||
CooldownTime = DataReference.CooldownTime;
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
using System;
|
||||
using GAS.Runtime;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
[Serializable]
|
||||
public abstract class CatchAreaBase : TargetCatcherBase
|
||||
{
|
||||
public LayerMask checkLayer;
|
||||
|
||||
public void Init(AbilitySystemComponent owner, LayerMask checkLayer)
|
||||
{
|
||||
base.Init(owner);
|
||||
this.checkLayer = checkLayer;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58b4935f7a5a43d69506e28666032462
|
||||
timeCreated: 1709451834
|
@ -0,0 +1,14 @@
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// 目标捕获器类型枚举
|
||||
/// </summary>
|
||||
public enum EnumTargetCatcherType
|
||||
{
|
||||
CatchSelf = 1, // 捕获Ability的施法者自身
|
||||
CatchTarget, // 捕获Ability的目标
|
||||
|
||||
EnumBuiltinCount = 10, // 内建捕获器类型枚举的上限控制,上层业务派生由此开始
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 388df5b7ba124ee3b97a2380e1e8800d
|
||||
timeCreated: 1729498857
|
@ -0,0 +1,45 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public partial class TargetCatcherFactory
|
||||
{
|
||||
public delegate TargetCatcherBase NodeCreateFunc();
|
||||
|
||||
private static readonly Dictionary<ushort, NodeCreateFunc> s_TypeId2FactoryFunc;
|
||||
|
||||
static TargetCatcherFactory()
|
||||
{
|
||||
s_TypeId2FactoryFunc = new Dictionary<ushort, NodeCreateFunc>();
|
||||
Register((ushort)EnumTargetCatcherType.CatchSelf, () => new CatchSelf());
|
||||
Register((ushort)EnumTargetCatcherType.CatchTarget, () => new CatchTarget());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册TargetCatcher构造方法
|
||||
/// </summary>
|
||||
/// <param name="typeId"></param>
|
||||
/// <param name="func"></param>
|
||||
public static void Register(ushort typeId, NodeCreateFunc func)
|
||||
{
|
||||
s_TypeId2FactoryFunc[typeId] = func;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过节点类型创建TargetCatcher
|
||||
/// </summary>
|
||||
/// <param name="typeId">Timeline节点类型</param>
|
||||
/// <returns></returns>
|
||||
public static TargetCatcherBase CreateNode(ushort typeId)
|
||||
{
|
||||
if (!s_TypeId2FactoryFunc.ContainsKey(typeId))
|
||||
{
|
||||
Debug.LogError($"Can Not Find TargetCatcher Factory Function Id={typeId}");
|
||||
return null;
|
||||
}
|
||||
return s_TypeId2FactoryFunc[typeId]();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8c940b523ae4eb79010981381e33212
|
||||
timeCreated: 1729505456
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f8f62af330f4460b865fdcf0a2786d1b
|
||||
timeCreated: 1729505957
|
@ -0,0 +1,97 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// AbilityTask构造工厂
|
||||
/// </summary>
|
||||
public static class AbilityTaskFactory
|
||||
{
|
||||
public delegate AbilityTaskBase NodeCreateFunc();
|
||||
|
||||
/// <summary>
|
||||
/// TypeID映射构造方法
|
||||
/// </summary>
|
||||
private static readonly Dictionary<ushort, NodeCreateFunc> s_TypeId2FactoryFunc;
|
||||
|
||||
static AbilityTaskFactory()
|
||||
{
|
||||
s_TypeId2FactoryFunc = new Dictionary<ushort, NodeCreateFunc>();
|
||||
Register((ushort)EnumAbilityTaskType.InstantTaskStart, () => new DefaultInstantAbilityTask());
|
||||
Register((ushort)EnumAbilityTaskType.OngoingTaskStart, () => new DefaultOngoingAbilityTask());
|
||||
Register((ushort)EnumAbilityTaskType.PassiveTaskStart, () => new DefaultPassiveAbilityTask());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册Timeline节点类型构造方法
|
||||
/// </summary>
|
||||
/// <param name="typeId"></param>
|
||||
/// <param name="func"></param>
|
||||
public static void Register(ushort typeId, NodeCreateFunc func)
|
||||
{
|
||||
s_TypeId2FactoryFunc[typeId] = func;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过节点类型创建InstantAbilityTask实例
|
||||
/// </summary>
|
||||
/// <param name="typeId">AbilityTask类型</param>
|
||||
/// <returns></returns>
|
||||
public static InstantAbilityTask CreateInstantTask(ushort typeId)
|
||||
{
|
||||
if (typeId < (ushort)EnumAbilityTaskType.InstantTaskStart && typeId >= (ushort)EnumAbilityTaskType.OngoingTaskStart)
|
||||
{
|
||||
Debug.LogError($"TypeId不是InstantTask派生的,TypeId={typeId}");
|
||||
return null;
|
||||
}
|
||||
return CreateTask(typeId) as InstantAbilityTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过节点类型创建OngoingAbilityTask实例
|
||||
/// </summary>
|
||||
/// <param name="typeId">AbilityTask类型</param>
|
||||
/// <returns></returns>
|
||||
public static OngoingAbilityTask CreateOngoingTask(ushort typeId)
|
||||
{
|
||||
if (typeId < (ushort)EnumAbilityTaskType.OngoingTaskStart && typeId >= (ushort)EnumAbilityTaskType.PassiveTaskStart)
|
||||
{
|
||||
Debug.LogError($"TypeId不是OngoingTask派生的,TypeId={typeId}");
|
||||
return null;
|
||||
}
|
||||
return CreateTask(typeId) as OngoingAbilityTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过节点类型创建PassiveAbilityTask实例
|
||||
/// </summary>
|
||||
/// <param name="typeId">AbilityTask类型</param>
|
||||
/// <returns></returns>
|
||||
public static PassiveAbilityTask CreatePassiveTask(ushort typeId)
|
||||
{
|
||||
if (typeId < (ushort)EnumAbilityTaskType.PassiveTaskStart)
|
||||
{
|
||||
Debug.LogError($"TypeId不是PassiveTask派生的,TypeId={typeId}");
|
||||
return null;
|
||||
}
|
||||
return CreateTask(typeId) as PassiveAbilityTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过节点类型创建AbilityTask实例
|
||||
/// </summary>
|
||||
/// <param name="typeId">AbilityTask类型</param>
|
||||
/// <returns></returns>
|
||||
public static AbilityTaskBase CreateTask(ushort typeId)
|
||||
{
|
||||
if (!s_TypeId2FactoryFunc.ContainsKey(typeId))
|
||||
{
|
||||
Debug.LogError($"没有注册的AbilityTask, TypeId={typeId}");
|
||||
return null;
|
||||
}
|
||||
return s_TypeId2FactoryFunc[typeId]();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57d9e528d18245f386608d8853b6b8ea
|
||||
timeCreated: 1729505585
|
@ -0,0 +1,15 @@
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// AbilityTask的类型枚举
|
||||
/// </summary>
|
||||
public enum EnumAbilityTaskType : ushort
|
||||
{
|
||||
InstantTaskStart = 10000, // InstantTask派生的起始Type索引,上层派生由此递增
|
||||
|
||||
OngoingTaskStart = 20000, // OngoingTask派生的起始Type索引,上层派生由此递增
|
||||
|
||||
PassiveTaskStart = 30000, // PassiveTask派生的起始Type索引,上层派生由此递增
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57d5671cf20243c1b81d2754324ca1eb
|
||||
timeCreated: 1729497043
|
@ -81,7 +81,7 @@ namespace GAS.Runtime
|
||||
{
|
||||
if (modifier.AttributeName == _processedAttribute.Name)
|
||||
{
|
||||
var modifierSpec = JexGasObjectPool.Instance.Fetch<ModifierSpec>();
|
||||
var modifierSpec = _owner.GetManager().ObjectPool.Fetch<ModifierSpec>();
|
||||
modifierSpec.Init(geSpec, modifier);
|
||||
_modifierCache.Add(modifierSpec);
|
||||
TryRegisterAttributeChangedListen(geSpec, modifier);
|
||||
@ -105,7 +105,7 @@ namespace GAS.Runtime
|
||||
foreach (var modifierSpec in _modifierCache)
|
||||
{
|
||||
modifierSpec.Release();
|
||||
JexGasObjectPool.Instance.Recycle(modifierSpec);
|
||||
_owner.GetManager().ObjectPool.Recycle(modifierSpec);
|
||||
}
|
||||
|
||||
_modifierCache.Clear();
|
||||
@ -240,9 +240,9 @@ namespace GAS.Runtime
|
||||
|
||||
private void TryUnregisterAttributeChangedListen(GameplayEffectSpec ge, GameplayEffectModifier modifier)
|
||||
{
|
||||
if (modifier.MMC is AttributeBasedModCalculation { captureType: AttributeBasedModCalculation.GEAttributeCaptureType.Track } mmc)
|
||||
if (modifier.MMC is AttributeBasedModCalculation { captureType: GEAttributeCaptureType.Track } mmc)
|
||||
{
|
||||
if (mmc.attributeFromType == AttributeBasedModCalculation.AttributeFrom.Target)
|
||||
if (mmc.attributeFromType == AttributeFrom.Target)
|
||||
{
|
||||
if (ge.Owner != null)
|
||||
ge.Owner.AttributeSetContainer.Sets[mmc.attributeSetName][mmc.attributeShortName]
|
||||
@ -259,9 +259,9 @@ namespace GAS.Runtime
|
||||
|
||||
private void TryRegisterAttributeChangedListen(GameplayEffectSpec ge, GameplayEffectModifier modifier)
|
||||
{
|
||||
if (modifier.MMC is AttributeBasedModCalculation { captureType: AttributeBasedModCalculation.GEAttributeCaptureType.Track } mmc)
|
||||
if (modifier.MMC is AttributeBasedModCalculation { captureType: GEAttributeCaptureType.Track } mmc)
|
||||
{
|
||||
if (mmc.attributeFromType == AttributeBasedModCalculation.AttributeFrom.Target)
|
||||
if (mmc.attributeFromType == AttributeFrom.Target)
|
||||
{
|
||||
if (ge.Owner != null)
|
||||
ge.Owner.AttributeSetContainer.Sets[mmc.attributeSetName][mmc.attributeShortName]
|
||||
@ -286,12 +286,12 @@ namespace GAS.Runtime
|
||||
{
|
||||
foreach (var modifierSpec in _modifierCache)
|
||||
{
|
||||
if (modifierSpec.Modifier.MMC is not AttributeBasedModCalculation { captureType: AttributeBasedModCalculation.GEAttributeCaptureType.Track } mmc) continue;
|
||||
if (modifierSpec.Modifier.MMC is not AttributeBasedModCalculation { captureType: GEAttributeCaptureType.Track } mmc) continue;
|
||||
if (attribute.Name != mmc.attributeName) continue;
|
||||
var geSpec = modifierSpec.SpecRef.Value;
|
||||
if (geSpec == null) continue;
|
||||
if ((mmc.attributeFromType == AttributeBasedModCalculation.AttributeFrom.Target && attribute.Owner == geSpec.Owner) ||
|
||||
(mmc.attributeFromType == AttributeBasedModCalculation.AttributeFrom.Source && attribute.Owner == geSpec.Source))
|
||||
if ((mmc.attributeFromType == AttributeFrom.Target && attribute.Owner == geSpec.Owner) ||
|
||||
(mmc.attributeFromType == AttributeFrom.Source && attribute.Owner == geSpec.Source))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ namespace GAS.Runtime
|
||||
|
||||
public Dictionary<string, LFloat> Snapshot()
|
||||
{
|
||||
var snapshot = JexGasObjectPool.Instance.Fetch<Dictionary<string, LFloat>>();
|
||||
var snapshot = _owner.GetManager().ObjectPool.Fetch<Dictionary<string, LFloat>>();
|
||||
foreach (var kv in _attributeSets)
|
||||
{
|
||||
var attributeSet = kv.Value;
|
||||
|
@ -2,11 +2,12 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using GAS.General;
|
||||
using JNGame.Math;
|
||||
using JNGame.Runtime.GAS;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public class AbilitySystemComponent : IAbilitySystemComponent
|
||||
public class AbilitySystemComponent : IAbilitySystemComponent,IJexGASObject
|
||||
{
|
||||
|
||||
private AbilitySystemComponentPreset preset;
|
||||
@ -399,5 +400,20 @@ namespace GAS.Runtime
|
||||
{
|
||||
GameplayEffectContainer.ClearGameplayEffect();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private JexGasManager _manager = JexGasManager.Editor;
|
||||
#else
|
||||
private JexGasManager _manager = null;
|
||||
#endif
|
||||
public JexGasManager GetManager()
|
||||
{
|
||||
return _manager;
|
||||
}
|
||||
|
||||
public void SetManager(JexGasManager manager)
|
||||
{
|
||||
_manager = manager;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ namespace GAS.Runtime
|
||||
LFloat level,
|
||||
object userData = null)
|
||||
{
|
||||
var spec = JexGasObjectPool.Instance.Fetch<GameplayEffectSpec>();
|
||||
var spec = new GameplayEffectSpec();
|
||||
spec.Awake(this, userData);
|
||||
spec.Init(creator, owner, level);
|
||||
return spec;
|
||||
@ -87,7 +87,7 @@ namespace GAS.Runtime
|
||||
/// <returns></returns>
|
||||
public EntityRef<GameplayEffectSpec> CreateSpec(object userData = null)
|
||||
{
|
||||
var spec = JexGasObjectPool.Instance.Fetch<GameplayEffectSpec>();
|
||||
var spec = new GameplayEffectSpec();
|
||||
spec.Awake(this, userData);
|
||||
return spec;
|
||||
}
|
||||
@ -141,7 +141,7 @@ namespace GAS.Runtime
|
||||
return Array.Empty<GrantedAbilityFromEffect>();
|
||||
}
|
||||
|
||||
var grantedAbilityFromEffects = JexGasObjectPool.Instance.Fetch<List<GrantedAbilityFromEffect>>();
|
||||
var grantedAbilityFromEffects = new List<GrantedAbilityFromEffect>();
|
||||
foreach (var grantedAbilityConfig in grantedAbilities)
|
||||
{
|
||||
if (grantedAbilityConfig.AbilityAsset != null)
|
||||
@ -151,7 +151,7 @@ namespace GAS.Runtime
|
||||
var ret = GrantedAbilityFromEffectArrayPool.Fetch(grantedAbilityFromEffects.Count);
|
||||
grantedAbilityFromEffects.CopyTo(ret);
|
||||
grantedAbilityFromEffects.Clear();
|
||||
JexGasObjectPool.Instance.Recycle(grantedAbilityFromEffects);
|
||||
// JexGasObjectPool.Instance.Recycle(grantedAbilityFromEffects);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,8 @@ namespace GAS.Runtime
|
||||
|
||||
#region Base Info
|
||||
|
||||
public string Name => name;
|
||||
|
||||
[TitleGroup(GRP_BASE)]
|
||||
[HorizontalGroup(GRP_BASE_H, Width = 1 - 0.618f)]
|
||||
[TabGroup(GRP_BASE_H_LEFT, "Summary", SdfIconType.InfoSquareFill, TextColor = "#0BFFC5")]
|
||||
@ -320,7 +322,6 @@ namespace GAS.Runtime
|
||||
bool IsGrantedAbilitiesInvalid() => IsDurationalPolicy() && GrantedAbilities != null && GrantedAbilities.Any(abilityConfig => abilityConfig.AbilityAsset == null);
|
||||
|
||||
#region IGameplayEffectData
|
||||
|
||||
public string GetDisplayName() => name;
|
||||
|
||||
public EffectsDurationPolicy GetDurationPolicy() => DurationPolicy;
|
||||
@ -378,16 +379,13 @@ namespace GAS.Runtime
|
||||
/// <para>缺点: Editor下实时修改GameplayEffectAsset无法实时生效, 因为共享实例一旦创建, 就不会再改变, 可以设置GasRuntimeSettings.DisableGameplayEffectSharedInstance来禁用Editor模式下的SharedInstance</para>
|
||||
/// </remarks>
|
||||
/// </summary>
|
||||
public GameplayEffect SharedInstance
|
||||
public GameplayEffect SharedInstance()
|
||||
{
|
||||
get
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (GasRuntimeSettings.DisableGameplayEffectSharedInstance)
|
||||
return new GameplayEffect(this);
|
||||
if (GasRuntimeSettings.DisableGameplayEffectSharedInstance)
|
||||
return new GameplayEffect(this);
|
||||
#endif
|
||||
return _sharedInstance ??= new GameplayEffect(this);
|
||||
}
|
||||
return _sharedInstance ??= new GameplayEffect(this);
|
||||
}
|
||||
|
||||
private GameplayEffect _sharedInstance;
|
||||
|
@ -25,7 +25,7 @@ namespace GAS.Runtime
|
||||
|
||||
public void Tick(int dt)
|
||||
{
|
||||
var gameplayEffectSpecs = JexGasObjectPool.Instance.Fetch<List<GameplayEffectSpec>>();
|
||||
var gameplayEffectSpecs = _owner.GetManager().ObjectPool.Fetch<List<GameplayEffectSpec>>();
|
||||
gameplayEffectSpecs.AddRange(_gameplayEffectSpecs);
|
||||
|
||||
foreach (var gameplayEffectSpec in gameplayEffectSpecs)
|
||||
@ -37,7 +37,7 @@ namespace GAS.Runtime
|
||||
}
|
||||
|
||||
gameplayEffectSpecs.Clear();
|
||||
JexGasObjectPool.Instance.Recycle(gameplayEffectSpecs);
|
||||
_owner.GetManager().ObjectPool.Recycle(gameplayEffectSpecs);
|
||||
}
|
||||
|
||||
public void RegisterOnGameplayEffectContainerIsDirty(Action action)
|
||||
@ -54,7 +54,7 @@ namespace GAS.Runtime
|
||||
{
|
||||
if (tags.Empty) return;
|
||||
|
||||
var removeList = JexGasObjectPool.Instance.Fetch<List<GameplayEffectSpec>>();
|
||||
var removeList = _owner.GetManager().ObjectPool.Fetch<List<GameplayEffectSpec>>();
|
||||
|
||||
foreach (var gameplayEffectSpec in _gameplayEffectSpecs)
|
||||
{
|
||||
@ -72,7 +72,7 @@ namespace GAS.Runtime
|
||||
foreach (var gameplayEffectSpec in removeList) RemoveGameplayEffectSpec(gameplayEffectSpec);
|
||||
|
||||
removeList.Clear();
|
||||
JexGasObjectPool.Instance.Recycle(removeList);
|
||||
_owner.GetManager().ObjectPool.Recycle(removeList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -4,7 +4,8 @@ namespace GAS.Runtime
|
||||
{
|
||||
public class InstantGameplayEffectData : IGameplayEffectData
|
||||
{
|
||||
private string Name { get; }
|
||||
private string name;
|
||||
public string Name => name;
|
||||
|
||||
public GameplayEffectSnapshotPolicy SnapshotPolicy { get; set; } = GameplayEffectSnapshotPolicy.Specified;
|
||||
|
||||
@ -15,7 +16,7 @@ namespace GAS.Runtime
|
||||
public GameplayEffectModifier[] Modifiers { get; set; } = Array.Empty<GameplayEffectModifier>();
|
||||
public GameplayEffectSpecifiedSnapshotConfig[] SpecifiedSnapshotConfigs { get; set; } = Array.Empty<GameplayEffectSpecifiedSnapshotConfig>();
|
||||
|
||||
public InstantGameplayEffectData(string name) => Name = name;
|
||||
public InstantGameplayEffectData(string name) => this.name = name;
|
||||
|
||||
public string GetDisplayName() => Name;
|
||||
|
||||
@ -62,6 +63,11 @@ namespace GAS.Runtime
|
||||
public virtual GrantedAbilityConfig[] GetGrantedAbilities() => Array.Empty<GrantedAbilityConfig>();
|
||||
|
||||
public virtual GameplayEffectStacking GetStacking() => GameplayEffectStacking.None;
|
||||
|
||||
public GameplayEffect SharedInstance()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class InfiniteGameplayEffectData : InstantGameplayEffectData
|
||||
|
@ -37,7 +37,7 @@ namespace GAS.Runtime
|
||||
Modifiers = GameplayEffect.Modifiers;
|
||||
if (gameplayEffect.DurationPolicy != EffectsDurationPolicy.Instant)
|
||||
{
|
||||
var periodTicker = JexGasObjectPool.Instance.Fetch<GameplayEffectPeriodTicker>();
|
||||
var periodTicker = new GameplayEffectPeriodTicker();
|
||||
periodTicker.Awake(this);
|
||||
// EntityRef之前必须确定InstanceId的值
|
||||
PeriodTicker = periodTicker;
|
||||
@ -62,7 +62,7 @@ namespace GAS.Runtime
|
||||
if (gameplayEffectPeriodTicker != null)
|
||||
{
|
||||
gameplayEffectPeriodTicker.Release();
|
||||
JexGasObjectPool.Instance.Recycle(gameplayEffectPeriodTicker);
|
||||
// JexGasObjectPool.Instance.Recycle(gameplayEffectPeriodTicker);
|
||||
}
|
||||
|
||||
PeriodTicker = default;
|
||||
@ -80,12 +80,12 @@ namespace GAS.Runtime
|
||||
if (grantedAbilitySpecFromEffect != null)
|
||||
{
|
||||
grantedAbilitySpecFromEffect.Release();
|
||||
JexGasObjectPool.Instance.Recycle(grantedAbilitySpecFromEffect);
|
||||
// JexGasObjectPool.Instance.Recycle(grantedAbilitySpecFromEffect);
|
||||
}
|
||||
}
|
||||
|
||||
GrantedAbilitiesSpecFromEffect.Clear();
|
||||
JexGasObjectPool.Instance.Recycle(GrantedAbilitiesSpecFromEffect);
|
||||
// JexGasObjectPool.Instance.Recycle(GrantedAbilitiesSpecFromEffect);
|
||||
GrantedAbilitiesSpecFromEffect = default;
|
||||
}
|
||||
|
||||
@ -95,13 +95,13 @@ namespace GAS.Runtime
|
||||
if (SnapshotSourceAttributes != null)
|
||||
{
|
||||
SnapshotSourceAttributes.Clear();
|
||||
JexGasObjectPool.Instance.Recycle(SnapshotSourceAttributes);
|
||||
// JexGasObjectPool.Instance.Recycle(SnapshotSourceAttributes);
|
||||
}
|
||||
|
||||
if (SnapshotTargetAttributes != null && SnapshotSourceAttributes != SnapshotTargetAttributes)
|
||||
{
|
||||
SnapshotTargetAttributes.Clear();
|
||||
JexGasObjectPool.Instance.Recycle(SnapshotTargetAttributes);
|
||||
// JexGasObjectPool.Instance.Recycle(SnapshotTargetAttributes);
|
||||
}
|
||||
|
||||
SnapshotSourceAttributes = null;
|
||||
@ -112,14 +112,14 @@ namespace GAS.Runtime
|
||||
if (_valueMapWithTag != null)
|
||||
{
|
||||
_valueMapWithTag.Clear();
|
||||
JexGasObjectPool.Instance.Recycle(_valueMapWithTag);
|
||||
// JexGasObjectPool.Instance.Recycle(_valueMapWithTag);
|
||||
_valueMapWithTag = null;
|
||||
}
|
||||
|
||||
if (_valueMapWithName != null)
|
||||
{
|
||||
_valueMapWithName.Clear();
|
||||
JexGasObjectPool.Instance.Recycle(_valueMapWithName);
|
||||
// JexGasObjectPool.Instance.Recycle(_valueMapWithName);
|
||||
_valueMapWithName = null;
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ namespace GAS.Runtime
|
||||
OnStackChanged = default;
|
||||
}
|
||||
|
||||
JexGasObjectPool.Instance.Recycle(this);
|
||||
// JexGasObjectPool.Instance.Recycle(this);
|
||||
}
|
||||
|
||||
public void Init(AbilitySystemComponent source, AbilitySystemComponent owner, LFloat level)
|
||||
@ -221,7 +221,8 @@ namespace GAS.Runtime
|
||||
if (grantedAbilityFromEffects is null) return;
|
||||
if (grantedAbilityFromEffects.Length == 0) return;
|
||||
|
||||
GrantedAbilitiesSpecFromEffect = JexGasObjectPool.Instance.Fetch<List<EntityRef<GrantedAbilitySpecFromEffect>>>();
|
||||
// GrantedAbilitiesSpecFromEffect = JexGasObjectPool.Instance.Fetch<List<EntityRef<GrantedAbilitySpecFromEffect>>>();
|
||||
GrantedAbilitiesSpecFromEffect = new List<EntityRef<GrantedAbilitySpecFromEffect>>();
|
||||
foreach (var grantedAbilityFromEffect in grantedAbilityFromEffects)
|
||||
{
|
||||
GrantedAbilitiesSpecFromEffect.Add(grantedAbilityFromEffect.CreateSpec(this));
|
||||
@ -237,12 +238,12 @@ namespace GAS.Runtime
|
||||
if (grantedAbilitySpecFromEffect != null)
|
||||
{
|
||||
grantedAbilitySpecFromEffect.Release();
|
||||
JexGasObjectPool.Instance.Recycle(grantedAbilitySpecFromEffect);
|
||||
// JexGasObjectPool.Instance.Recycle(grantedAbilitySpecFromEffect);
|
||||
}
|
||||
}
|
||||
|
||||
GrantedAbilitiesSpecFromEffect.Clear();
|
||||
JexGasObjectPool.Instance.Recycle(GrantedAbilitiesSpecFromEffect);
|
||||
// JexGasObjectPool.Instance.Recycle(GrantedAbilitiesSpecFromEffect);
|
||||
}
|
||||
|
||||
public void SetStacking(GameplayEffectStacking stacking)
|
||||
@ -317,7 +318,8 @@ namespace GAS.Runtime
|
||||
ReleaseCueDurationalSpecs();
|
||||
if (GameplayEffect.CueDurational is { Length: > 0 })
|
||||
{
|
||||
_cueDurationalSpecs = JexGasObjectPool.Instance.Fetch<List<GameplayCueDurationalSpec>>();
|
||||
// _cueDurationalSpecs = JexGasObjectPool.Instance.Fetch<List<GameplayCueDurationalSpec>>();
|
||||
_cueDurationalSpecs = new List<GameplayCueDurationalSpec>();
|
||||
foreach (var cueDurational in GameplayEffect.CueDurational)
|
||||
{
|
||||
var cueSpec = cueDurational.ApplyFrom(this);
|
||||
@ -489,7 +491,8 @@ namespace GAS.Runtime
|
||||
{
|
||||
case GameplayEffectSpecifiedSnapshotConfig.ESnapshotTarget.Source:
|
||||
{
|
||||
SnapshotSourceAttributes ??= JexGasObjectPool.Instance.Fetch<Dictionary<string, LFloat>>();
|
||||
// SnapshotSourceAttributes ??= JexGasObjectPool.Instance.Fetch<Dictionary<string, LFloat>>();
|
||||
SnapshotSourceAttributes ??= new Dictionary<string, LFloat>();
|
||||
var attribute = Source.AttributeSetContainer.GetAttributeAttributeValue(config.AttributeSetName, config.AttributeShortName);
|
||||
if (attribute != null)
|
||||
{
|
||||
@ -504,7 +507,8 @@ namespace GAS.Runtime
|
||||
}
|
||||
case GameplayEffectSpecifiedSnapshotConfig.ESnapshotTarget.Target:
|
||||
{
|
||||
SnapshotTargetAttributes ??= JexGasObjectPool.Instance.Fetch<Dictionary<string, LFloat>>();
|
||||
// SnapshotTargetAttributes ??= JexGasObjectPool.Instance.Fetch<Dictionary<string, LFloat>>();
|
||||
SnapshotTargetAttributes ??= new Dictionary<string, LFloat>();
|
||||
var attribute = Owner.AttributeSetContainer.GetAttributeAttributeValue(config.AttributeSetName, config.AttributeShortName);
|
||||
if (attribute != null)
|
||||
{
|
||||
@ -542,13 +546,15 @@ namespace GAS.Runtime
|
||||
|
||||
public void RegisterValue(in GameplayTag tag, LFloat value)
|
||||
{
|
||||
_valueMapWithTag ??= JexGasObjectPool.Instance.Fetch<Dictionary<GameplayTag, LFloat>>();
|
||||
// _valueMapWithTag ??= JexGasObjectPool.Instance.Fetch<Dictionary<GameplayTag, LFloat>>();
|
||||
_valueMapWithTag ??= new Dictionary<GameplayTag, LFloat>();
|
||||
_valueMapWithTag[tag] = value;
|
||||
}
|
||||
|
||||
public void RegisterValue(string name, LFloat value)
|
||||
{
|
||||
_valueMapWithName ??= JexGasObjectPool.Instance.Fetch<Dictionary<string, LFloat>>();
|
||||
// _valueMapWithName ??= JexGasObjectPool.Instance.Fetch<Dictionary<string, LFloat>>();
|
||||
_valueMapWithName ??= new Dictionary<string, LFloat>();
|
||||
_valueMapWithName[name] = value;
|
||||
}
|
||||
|
||||
@ -618,7 +624,7 @@ namespace GAS.Runtime
|
||||
if (_cueDurationalSpecs != null)
|
||||
{
|
||||
_cueDurationalSpecs.Clear();
|
||||
JexGasObjectPool.Instance.Recycle(_cueDurationalSpecs);
|
||||
// JexGasObjectPool.Instance.Recycle(_cueDurationalSpecs);
|
||||
_cueDurationalSpecs = null;
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ namespace GAS.Runtime
|
||||
overflowEffects = new GameplayEffect[overflowEffectAssets.Length];
|
||||
for (var i = 0; i < overflowEffectAssets.Length; ++i)
|
||||
{
|
||||
overflowEffects[i] = overflowEffectAssets[i].SharedInstance;
|
||||
overflowEffects[i] = overflowEffectAssets[i].SharedInstance();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,7 @@ namespace GAS.Runtime
|
||||
|
||||
public GrantedAbilitySpecFromEffect CreateSpec(GameplayEffectSpec sourceEffectSpec)
|
||||
{
|
||||
var grantedAbilitySpecFromEffect = JexGasObjectPool.Instance.Fetch<GrantedAbilitySpecFromEffect>();
|
||||
var grantedAbilitySpecFromEffect = new GrantedAbilitySpecFromEffect();
|
||||
grantedAbilitySpecFromEffect.Awake(this, sourceEffectSpec);
|
||||
return grantedAbilitySpecFromEffect;
|
||||
}
|
||||
|
@ -2,6 +2,11 @@
|
||||
{
|
||||
public interface IGameplayEffectData
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源标识,对应ScriptableObject的name
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
string GetDisplayName();
|
||||
EffectsDurationPolicy GetDurationPolicy();
|
||||
int GetDuration();
|
||||
@ -38,5 +43,16 @@
|
||||
|
||||
//Stacking
|
||||
GameplayEffectStacking GetStacking();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 共享实例, 一个GameplayEffectAsset对应一个共享实例, 首次访问时创建
|
||||
/// <remarks>
|
||||
/// <para>优点: 通过共享实例, 可以减少GameplayEffect的实例化次数, 减少内存开销, 同时也可以减少GC的产生, 提高性能</para>
|
||||
/// <para>缺点: Editor下实时修改GameplayEffectAsset无法实时生效, 因为共享实例一旦创建, 就不会再改变, 可以设置GasRuntimeSettings.DisableGameplayEffectSharedInstance来禁用Editor模式下的SharedInstance</para>
|
||||
/// </remarks>
|
||||
/// </summary>
|
||||
public GameplayEffect SharedInstance();
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// 属性采样来源类型枚举
|
||||
/// </summary>
|
||||
public enum AttributeFrom : byte
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[Sirenix.OdinInspector.LabelText("来源(Source)", Sirenix.OdinInspector.SdfIconType.Magic)]
|
||||
#endif
|
||||
Source,
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[Sirenix.OdinInspector.LabelText("目标(Target)", Sirenix.OdinInspector.SdfIconType.Person)]
|
||||
#endif
|
||||
Target
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 属性捕获类型枚举
|
||||
/// </summary>
|
||||
public enum GEAttributeCaptureType : byte
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[Sirenix.OdinInspector.LabelText("快照(SnapShot)", Sirenix.OdinInspector.SdfIconType.Camera)]
|
||||
#endif
|
||||
SnapShot,
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[Sirenix.OdinInspector.LabelText("实时(Track)", Sirenix.OdinInspector.SdfIconType.Speedometer2)]
|
||||
#endif
|
||||
Track
|
||||
}
|
||||
|
||||
public enum EnumMMCType : ushort
|
||||
{
|
||||
PureAttrBasedWithStackModCalculation = 1,
|
||||
PureAttributeBasedModCalculation = 2,
|
||||
PureScalableFloatModCalculation = 3,
|
||||
PureStackModCalculation = 4,
|
||||
|
||||
EnumBuiltinCount = 10,
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5952d6cd83f4e0db54536fb85503d13
|
||||
timeCreated: 1729498418
|
@ -0,0 +1,73 @@
|
||||
using JNGame.Math;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// 基于属性混合GE堆栈的MMC
|
||||
/// </summary>
|
||||
[CreateAssetMenu(fileName = "AttrBasedWithStackModCalculation", menuName = "GAS/MMC/AttrBasedWithStackModCalculation")]
|
||||
public class PureAttrBasedWithStackModCalculation : PureAttributeBasedModCalculation
|
||||
{
|
||||
public enum StackMagnitudeOperation
|
||||
{
|
||||
Add,
|
||||
Multiply
|
||||
}
|
||||
|
||||
[InfoBox(" 公式:StackCount * sK + sB")]
|
||||
[TabGroup("Default", "AttributeBasedModCalculation")]
|
||||
[Title("堆叠幅值计算")]
|
||||
[LabelText("系数(sK)")]
|
||||
public LFloat sK = 1;
|
||||
|
||||
[TabGroup("Default", "AttributeBasedModCalculation")]
|
||||
[LabelText("常量(sB)")]
|
||||
public LFloat 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 LFloat CalculateMagnitude(GameplayEffectSpec spec, LFloat 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: 6b7892b02c5a49f3a56e7ca1215086c3
|
||||
timeCreated: 1729498090
|
@ -0,0 +1,136 @@
|
||||
using System.Linq;
|
||||
using JNGame.Math;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
[CreateAssetMenu(fileName = "AttributeBasedModCalculation", menuName = "GAS/MMC/AttributeBasedModCalculation")]
|
||||
public class PureAttributeBasedModCalculation : PureModifierMagnitudeCalculation
|
||||
{
|
||||
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("计算逻辑与ScalableLFloatModCalculation一致, 公式:AttributeValue * k + b")]
|
||||
[TabGroup("Default", "AttributeBasedModCalculation")]
|
||||
[LabelText("系数(k)")]
|
||||
public LFloat k = 1;
|
||||
|
||||
[TabGroup("Default", "AttributeBasedModCalculation")]
|
||||
[LabelText("常量(b)")]
|
||||
public LFloat b = 0;
|
||||
|
||||
public override LFloat CalculateMagnitude(GameplayEffectSpec spec, LFloat modifierMagnitude)
|
||||
{
|
||||
LFloat 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: 74fb43f815744dac9bcc44b7ae35549d
|
||||
timeCreated: 1729498090
|
@ -0,0 +1,59 @@
|
||||
using System.Linq;
|
||||
using GAS.General;
|
||||
using JNGame.Math;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public abstract class PureModifierMagnitudeCalculation : ScriptableObject,IModifierMagnitudeCalculation
|
||||
{
|
||||
public virtual ushort TypeId => 0;
|
||||
|
||||
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 LFloat CalculateMagnitude(GameplayEffectSpec spec, LFloat 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: 38469c588420428dbd16a6fda9439591
|
||||
timeCreated: 1729498090
|
@ -0,0 +1,25 @@
|
||||
using JNGame.Math;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
[CreateAssetMenu(fileName = "ScalableLFloatModCalculation", menuName = "GAS/MMC/ScalableLFloatModCalculation")]
|
||||
public class PureScalableLFloatModCalculation : PureModifierMagnitudeCalculation
|
||||
{
|
||||
private const string Desc = "计算公式:ModifierMagnitude * k + b";
|
||||
|
||||
private const string Detail =
|
||||
"ScalableLFloatModCalculation:可缩放浮点数计算\n该类型是根据Magnitude计算Modifier模值的,计算公式为:ModifierMagnitude * k + b 实际上就是一个线性函数,k和b为可编辑参数,可以在编辑器中设置。";
|
||||
|
||||
[DetailedInfoBox(Desc, Detail, InfoMessageType.Info)] [SerializeField]
|
||||
private LFloat k = LFloat.L1;
|
||||
|
||||
[SerializeField] private LFloat b = LFloat.L0;
|
||||
|
||||
public override LFloat CalculateMagnitude(GameplayEffectSpec spec, LFloat input)
|
||||
{
|
||||
return input * k + b;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 062e7b5a35be434b839d3d2ecbab97a8
|
||||
timeCreated: 1729498090
|
@ -0,0 +1,19 @@
|
||||
using JNGame.Math;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
[CreateAssetMenu(fileName = "SetByCallerFromName", menuName = "GAS/MMC/SetByCallerFromNameModCalculation")]
|
||||
public class PureSetByCallerFromNameModCalculation : PureModifierMagnitudeCalculation
|
||||
{
|
||||
[SerializeField] private string valueName;
|
||||
public override LFloat CalculateMagnitude(GameplayEffectSpec spec,LFloat 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: ab0276bbb7c8483cbde7d5a2708b4585
|
||||
timeCreated: 1729498090
|
@ -0,0 +1,24 @@
|
||||
using JNGame.Math;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
[CreateAssetMenu(fileName = "SetByCallerFromTag", menuName = "GAS/MMC/SetByCallerFromTagModCalculation")]
|
||||
public class PureSetByCallerFromTagModCalculation : PureModifierMagnitudeCalculation
|
||||
{
|
||||
[SerializeField]
|
||||
[ValueDropdown("@ValueDropdownHelper.GameplayTagChoices", HideChildProperties = true)]
|
||||
private GameplayTag _tag;
|
||||
|
||||
public override LFloat CalculateMagnitude(GameplayEffectSpec spec, LFloat 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: 0394869df5504d90bc580383dbbc7289
|
||||
timeCreated: 1729498090
|
@ -0,0 +1,27 @@
|
||||
using JNGame.Math;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
[CreateAssetMenu( fileName = "StackModCalculation", menuName = "GAS/MMC/StackModCalculation" )]
|
||||
public class PureStackModCalculation : PureModifierMagnitudeCalculation
|
||||
{
|
||||
[InfoBox("计算逻辑与ScalableLFloatModCalculation一致, 公式:(StackCount) * k + b")]
|
||||
[TabGroup("Default", "StackModCalculation")]
|
||||
[LabelText("系数(k)")]
|
||||
public LFloat k = 1;
|
||||
|
||||
[TabGroup("Default", "StackModCalculation")]
|
||||
[LabelText("常量(b)")]
|
||||
public LFloat b = 0;
|
||||
|
||||
public override LFloat CalculateMagnitude(GameplayEffectSpec spec, LFloat modifierMagnitude)
|
||||
{
|
||||
if (spec.Stacking.stackingType == StackingType.None) return 0;
|
||||
|
||||
var stackCount = spec.StackCount;
|
||||
return stackCount * k + b;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7acf84e0af1440a7bd995578f44a4ce7
|
||||
timeCreated: 1729498090
|
@ -0,0 +1,12 @@
|
||||
using GAS.Runtime;
|
||||
|
||||
namespace JNGame.Runtime.GAS
|
||||
{
|
||||
public interface IJexGASObject
|
||||
{
|
||||
|
||||
public JexGasManager GetManager();
|
||||
public void SetManager(JexGasManager manager);
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 878812783d9a43eaa7da120f0eac8f78
|
||||
timeCreated: 1729480508
|
@ -17,6 +17,7 @@ namespace GAS.Runtime
|
||||
|
||||
public JexGasManager()
|
||||
{
|
||||
ObjectPool = new JexGasObjectPool(this);
|
||||
#if UNITY_EDITOR
|
||||
//预览GAS
|
||||
Editor = this;
|
||||
@ -31,7 +32,7 @@ namespace GAS.Runtime
|
||||
/// <summary>
|
||||
/// GAS 专用对象池 (只限制当前管理器)
|
||||
/// </summary>
|
||||
private JexGasObjectPool ObjectPool = new JexGasObjectPool();
|
||||
public JexGasObjectPool ObjectPool { get; private set; }
|
||||
|
||||
//GAS 更新
|
||||
public void Update(int dt)
|
||||
@ -39,7 +40,7 @@ namespace GAS.Runtime
|
||||
|
||||
Profiler.BeginSample($"{nameof(JexGasManager)}::Tick()");
|
||||
|
||||
var abilitySystemComponents = JexGasObjectPool.Instance.Fetch<List<AbilitySystemComponent>>();
|
||||
var abilitySystemComponents = ObjectPool.Fetch<List<AbilitySystemComponent>>();
|
||||
abilitySystemComponents.AddRange(AbilitySystemComponents);
|
||||
|
||||
foreach (var abilitySystemComponent in abilitySystemComponents)
|
||||
@ -48,7 +49,7 @@ namespace GAS.Runtime
|
||||
}
|
||||
|
||||
abilitySystemComponents.Clear();
|
||||
JexGasObjectPool.Instance.Recycle(abilitySystemComponents);
|
||||
ObjectPool.Recycle(abilitySystemComponents);
|
||||
|
||||
Profiler.EndSample();
|
||||
|
||||
@ -77,16 +78,11 @@ namespace GAS.Runtime
|
||||
/// 创建 AbilitySystemComponent
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public T CreateAbilitySystemComponent<T>(AbilitySystemComponentPreset ascPreset,int level = 1) where T : AbilitySystemComponent, new()
|
||||
public T CreateAbilitySystemComponent<T>() where T : AbilitySystemComponent, new()
|
||||
{
|
||||
|
||||
var asc = new T();
|
||||
asc.OnCreate();
|
||||
asc.SetPreset(ascPreset);
|
||||
asc.SetLevel(level);
|
||||
Register(asc);
|
||||
return asc;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 29fcc5027c714f648f896f1fdb3dd65a
|
||||
timeCreated: 1729497471
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f55f838e9004c68a22984dbf2aa59fb
|
||||
timeCreated: 1729497482
|
@ -0,0 +1,69 @@
|
||||
|
||||
using System;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// Ability基础配置数据接口
|
||||
/// </summary>
|
||||
public interface IAbilityAsset
|
||||
{
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ability唯一标识字符串
|
||||
/// </summary>
|
||||
string UniqueName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ability的消耗GE配置
|
||||
/// </summary>
|
||||
IGameplayEffectData Cost { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ability的冷却效果
|
||||
/// </summary>
|
||||
IGameplayEffectData Cooldown { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ability的冷却时长,单位毫秒
|
||||
/// </summary>
|
||||
int CooldownTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 描述性质的标签,用来描述Ability的特性表现,比如伤害、治疗、控制等。
|
||||
/// </summary>
|
||||
GameplayTag[] AssetTags { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ability激活时,Ability持有者当前持有的所有Ability中,拥有【任意】这些标签的Ability会被取消。
|
||||
/// </summary>
|
||||
GameplayTag[] CancelAbilityTags { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ability激活时,Ability持有者当前持有的所有Ability中,拥有【任意】这些标签的Ability会被阻塞激活。
|
||||
/// </summary>
|
||||
GameplayTag[] BlockAbilityTags { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ability激活时,持有者会获得这些标签,Ability被失活时,这些标签也会被移除。
|
||||
/// </summary>
|
||||
GameplayTag[] ActivationOwnedTags { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ability只有在其拥有者拥有【所有】这些标签时才可激活。
|
||||
/// </summary>
|
||||
GameplayTag[] ActivationRequiredTags { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ability在其拥有者拥有【任意】这些标签时不能被激活。
|
||||
/// </summary>
|
||||
GameplayTag[] ActivationBlockedTags { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取运行时的Ability类型
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Type AbilityType();
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c3c0cb099744f90af5faaefac71bfba
|
||||
timeCreated: 1729499278
|
@ -0,0 +1,20 @@
|
||||
using JNGame.Math;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public interface IModifierMagnitudeCalculation
|
||||
{
|
||||
/// <summary>
|
||||
/// Modifier的类型Id
|
||||
/// </summary>
|
||||
ushort TypeId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 属性计算
|
||||
/// </summary>
|
||||
/// <param name="spec"></param>
|
||||
/// <param name="modifierMagnitude"></param>
|
||||
/// <returns></returns>
|
||||
LFloat CalculateMagnitude(GameplayEffectSpec spec, LFloat modifierMagnitude);
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e92e5303b6443c0a36218b3bfc7ae77
|
||||
timeCreated: 1729497485
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77b9750491334df1822a19708b3b13e8
|
||||
timeCreated: 1729505134
|
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using JNGame.Serialization;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public abstract class PureAbilityAsset : IAbilityAsset,ISerializable
|
||||
{
|
||||
protected const int WIDTH_LABEL = 70;
|
||||
|
||||
|
||||
public string m_Name;
|
||||
public string m_UniqueName;
|
||||
public IGameplayEffectData m_Cost;
|
||||
public IGameplayEffectData m_Cooldown;
|
||||
public int m_CooldownTime;
|
||||
public GameplayTag[] m_AssetTags;
|
||||
public GameplayTag[] m_CancelAbilityTags;
|
||||
public GameplayTag[] m_BlockAbilityTags;
|
||||
public GameplayTag[] m_ActivationOwnedTags;
|
||||
public GameplayTag[] m_ActivationRequiredTags;
|
||||
public GameplayTag[] m_ActivationBlockedTags;
|
||||
|
||||
public string Name => m_Name;
|
||||
public string UniqueName => m_UniqueName;
|
||||
public IGameplayEffectData Cost => m_Cost;
|
||||
public IGameplayEffectData Cooldown => m_Cooldown;
|
||||
public int CooldownTime => m_CooldownTime;
|
||||
public GameplayTag[] AssetTags => m_AssetTags;
|
||||
public GameplayTag[] CancelAbilityTags => m_CancelAbilityTags;
|
||||
public GameplayTag[] BlockAbilityTags => m_BlockAbilityTags;
|
||||
public GameplayTag[] ActivationOwnedTags => m_ActivationOwnedTags;
|
||||
public GameplayTag[] ActivationRequiredTags => m_ActivationRequiredTags;
|
||||
public GameplayTag[] ActivationBlockedTags => m_ActivationBlockedTags;
|
||||
|
||||
public abstract Type AbilityType();
|
||||
|
||||
public void Serialize(Serializer writer)
|
||||
{
|
||||
}
|
||||
|
||||
public void Deserialize(Deserializer reader)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 15fd65bc8eb34108a617f535c2e4ee66
|
||||
timeCreated: 1729503254
|
@ -157,7 +157,7 @@ namespace GAS.Runtime
|
||||
}
|
||||
else
|
||||
{
|
||||
var list = JexGasObjectPool.Instance.Fetch<List<object>>();
|
||||
var list = _owner.GetManager().ObjectPool.Fetch<List<object>>();
|
||||
list.Add(source);
|
||||
_dynamicAddedTags.Add(tag, list);
|
||||
}
|
||||
@ -172,7 +172,7 @@ namespace GAS.Runtime
|
||||
if (_dynamicAddedTags.TryGetValue(tag, out var addedTag))
|
||||
{
|
||||
addedTag.Clear();
|
||||
JexGasObjectPool.Instance.Recycle(addedTag);
|
||||
_owner.GetManager().ObjectPool.Recycle(addedTag);
|
||||
dirty = _dynamicAddedTags.Remove(tag);
|
||||
}
|
||||
|
||||
@ -184,7 +184,7 @@ namespace GAS.Runtime
|
||||
}
|
||||
else
|
||||
{
|
||||
var list = JexGasObjectPool.Instance.Fetch<List<object>>();
|
||||
var list = _owner.GetManager().ObjectPool.Fetch<List<object>>();
|
||||
list.Add(source);
|
||||
_dynamicRemovedTags.Add(tag, list);
|
||||
}
|
||||
@ -205,7 +205,7 @@ namespace GAS.Runtime
|
||||
dirty = tagList.Count == 0;
|
||||
if (dirty)
|
||||
{
|
||||
JexGasObjectPool.Instance.Recycle(tagList);
|
||||
_owner.GetManager().ObjectPool.Recycle(tagList);
|
||||
dynamicTag.Remove(tag);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b06cadfa1714076bafde3b55634aa54
|
||||
timeCreated: 1729504568
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2cace2b74934df1ba47e6682854751c
|
||||
timeCreated: 1729504662
|
@ -8,18 +8,31 @@ using UnityEngine.Serialization;
|
||||
|
||||
namespace GAS.Runtime
|
||||
{
|
||||
public abstract class AbilityAsset : ScriptableObject
|
||||
public abstract class AbilityAsset : ScriptableObject,IAbilityAsset
|
||||
{
|
||||
protected const int WIDTH_LABEL = 70;
|
||||
|
||||
public abstract Type AbilityType();
|
||||
|
||||
|
||||
public string Name => name;
|
||||
public string UniqueName => uniqueName;
|
||||
public IGameplayEffectData Cost => cost;
|
||||
public IGameplayEffectData Cooldown => cooldown;
|
||||
public int CooldownTime => cooldownTime;
|
||||
public GameplayTag[] AssetTags => assetTags;
|
||||
public GameplayTag[] CancelAbilityTags => cancelAbilityTags;
|
||||
public GameplayTag[] BlockAbilityTags => blockAbilityTags;
|
||||
public GameplayTag[] ActivationOwnedTags => activationOwnedTags;
|
||||
public GameplayTag[] ActivationRequiredTags => activationRequiredTags;
|
||||
public GameplayTag[] ActivationBlockedTags => activationBlockedTags;
|
||||
|
||||
[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;
|
||||
[FormerlySerializedAs("Description")]
|
||||
public string description;
|
||||
|
||||
[TabGroup("Base/H1/V2", "General", SdfIconType.AwardFill, TextColor = "#FF7F00", Order = 2)]
|
||||
[LabelText("所属能力", SdfIconType.FileCodeFill)]
|
||||
@ -59,86 +72,93 @@ namespace GAS.Runtime
|
||||
[LabelText("U-Name", SdfIconType.Fingerprint)]
|
||||
[LabelWidth(WIDTH_LABEL)]
|
||||
[ValidateInput("@GAS.General.Validation.Validations.IsValidVariableName($value)", "无效的名字 - 不符合C#标识符命名规则")]
|
||||
[InlineButton("@UniqueName = name", "Auto", Icon = SdfIconType.Hammer)]
|
||||
public string UniqueName;
|
||||
[FormerlySerializedAs("UniqueName")]
|
||||
public string uniqueName;
|
||||
|
||||
[TabGroup("Base/H1/V2", "General")]
|
||||
[Title("消耗&冷却", bold: true)]
|
||||
[LabelWidth(WIDTH_LABEL)]
|
||||
[AssetSelector]
|
||||
[LabelText(SdfIconType.HeartHalf, Text = GASTextDefine.ABILITY_EFFECT_COST)]
|
||||
public GameplayEffectAsset Cost;
|
||||
[FormerlySerializedAs("Cost")]
|
||||
public GameplayEffectAsset cost;
|
||||
|
||||
[TabGroup("Base/H1/V2", "General")]
|
||||
[LabelWidth(WIDTH_LABEL)]
|
||||
[AssetSelector]
|
||||
[LabelText(SdfIconType.StopwatchFill, Text = GASTextDefine.ABILITY_EFFECT_CD)]
|
||||
public GameplayEffectAsset Cooldown;
|
||||
[FormerlySerializedAs("Cooldown")]
|
||||
public GameplayEffectAsset cooldown;
|
||||
|
||||
[TabGroup("Base/H1/V2", "General")]
|
||||
[LabelWidth(WIDTH_LABEL)]
|
||||
[LabelText(SdfIconType.ClockFill, Text = GASTextDefine.ABILITY_CD_TIME)]
|
||||
[Unit(Units.Millisecond)]
|
||||
public int CooldownTime;
|
||||
[FormerlySerializedAs("CooldownTime")]
|
||||
public int cooldownTime;
|
||||
|
||||
// Tags
|
||||
[TabGroup("Base/H1/V3", "Tags", SdfIconType.TagsFill, TextColor = "#45B1FF", Order = 3)]
|
||||
[ListDrawerSettings(ShowFoldout = true, ShowItemCount = false, DraggableItems = false)]
|
||||
[DisableContextMenu(disableForMember: false, disableCollectionElements: true)]
|
||||
[CustomContextMenu("排序", "@AssetTags = TagHelper.Sort($value)")]
|
||||
// [CustomContextMenu("排序", "@AssetTags = TagHelper.Sort($value)")]
|
||||
[ValueDropdown("@ValueDropdownHelper.GameplayTagChoices", IsUniqueList = true, HideChildProperties = true)]
|
||||
[Tooltip("描述性质的标签,用来描述Ability的特性表现,比如伤害、治疗、控制等。")]
|
||||
[FormerlySerializedAs("AssetTag")]
|
||||
public GameplayTag[] AssetTags;
|
||||
[FormerlySerializedAs("AssetTags")]
|
||||
public GameplayTag[] assetTags;
|
||||
|
||||
|
||||
[Space]
|
||||
[TabGroup("Base/H1/V3", "Tags")]
|
||||
[ListDrawerSettings(ShowFoldout = true, ShowItemCount = false, DraggableItems = false)]
|
||||
[DisableContextMenu(disableForMember: false, disableCollectionElements: true)]
|
||||
[CustomContextMenu("排序", "@CancelAbilityTags = TagHelper.Sort($value)")]
|
||||
// [CustomContextMenu("排序", "@CancelAbilityTags = TagHelper.Sort($value)")]
|
||||
[ValueDropdown("@ValueDropdownHelper.GameplayTagChoices", IsUniqueList = true, HideChildProperties = true)]
|
||||
[LabelText("CancelAbility With Tags ")]
|
||||
[Tooltip("Ability激活时,Ability持有者当前持有的所有Ability中,拥有【任意】这些标签的Ability会被取消。")]
|
||||
public GameplayTag[] CancelAbilityTags;
|
||||
[FormerlySerializedAs("CancelAbilityTags")]
|
||||
public GameplayTag[] cancelAbilityTags;
|
||||
|
||||
[Space]
|
||||
[TabGroup("Base/H1/V3", "Tags")]
|
||||
[ListDrawerSettings(ShowFoldout = true, ShowItemCount = false, DraggableItems = false)]
|
||||
[DisableContextMenu(disableForMember: false, disableCollectionElements: true)]
|
||||
[CustomContextMenu("排序", "@BlockAbilityTags = TagHelper.Sort($value)")]
|
||||
// [CustomContextMenu("排序", "@BlockAbilityTags = TagHelper.Sort($value)")]
|
||||
[ValueDropdown("@ValueDropdownHelper.GameplayTagChoices", IsUniqueList = true, HideChildProperties = true)]
|
||||
[LabelText("BlockAbility With Tags ")]
|
||||
[Tooltip("Ability激活时,Ability持有者当前持有的所有Ability中,拥有【任意】这些标签的Ability会被阻塞激活。")]
|
||||
public GameplayTag[] BlockAbilityTags;
|
||||
[FormerlySerializedAs("BlockAbilityTags")]
|
||||
public GameplayTag[] blockAbilityTags;
|
||||
|
||||
[Space]
|
||||
[TabGroup("Base/H1/V3", "Tags")]
|
||||
[ListDrawerSettings(ShowFoldout = true, ShowItemCount = false, DraggableItems = false)]
|
||||
[DisableContextMenu(disableForMember: false, disableCollectionElements: true)]
|
||||
[CustomContextMenu("排序", "@ActivationOwnedTags = TagHelper.Sort($value)")]
|
||||
// [CustomContextMenu("排序", "@ActivationOwnedTags = TagHelper.Sort($value)")]
|
||||
[ValueDropdown("@ValueDropdownHelper.GameplayTagChoices", IsUniqueList = true, HideChildProperties = true)]
|
||||
[Tooltip("Ability激活时,持有者会获得这些标签,Ability被失活时,这些标签也会被移除。")]
|
||||
[FormerlySerializedAs("ActivationOwnedTag")]
|
||||
public GameplayTag[] ActivationOwnedTags;
|
||||
public GameplayTag[] activationOwnedTags;
|
||||
|
||||
[Space]
|
||||
[TabGroup("Base/H1/V3", "Tags")]
|
||||
[ListDrawerSettings(ShowFoldout = true, ShowItemCount = false, DraggableItems = false)]
|
||||
[DisableContextMenu(disableForMember: false, disableCollectionElements: true)]
|
||||
[CustomContextMenu("排序", "@ActivationRequiredTags = TagHelper.Sort($value)")]
|
||||
// [CustomContextMenu("排序", "@ActivationRequiredTags = TagHelper.Sort($value)")]
|
||||
[ValueDropdown("@ValueDropdownHelper.GameplayTagChoices", IsUniqueList = true, HideChildProperties = true)]
|
||||
[Tooltip("Ability只有在其拥有者拥有【所有】这些标签时才可激活。")]
|
||||
public GameplayTag[] ActivationRequiredTags;
|
||||
[FormerlySerializedAs("ActivationRequiredTags")]
|
||||
public GameplayTag[] activationRequiredTags;
|
||||
|
||||
[Space]
|
||||
[TabGroup("Base/H1/V3", "Tags")]
|
||||
[ListDrawerSettings(ShowFoldout = true, ShowItemCount = false, DraggableItems = false)]
|
||||
[DisableContextMenu(disableForMember: false, disableCollectionElements: true)]
|
||||
[CustomContextMenu("排序", "@ActivationBlockedTags = TagHelper.Sort($value)")]
|
||||
// [CustomContextMenu("排序", "@ActivationBlockedTags = TagHelper.Sort($value)")]
|
||||
[ValueDropdown("@ValueDropdownHelper.GameplayTagChoices", IsUniqueList = true, HideChildProperties = true)]
|
||||
[Tooltip("Ability在其拥有者拥有【任意】这些标签时不能被激活。")]
|
||||
public GameplayTag[] ActivationBlockedTags;
|
||||
[FormerlySerializedAs("ActivationBlockedTags")]
|
||||
public GameplayTag[] activationBlockedTags;
|
||||
// public GameplayTag[] SourceRequiredTags;
|
||||
// public GameplayTag[] SourceBlockedTags;
|
||||
// public GameplayTag[] TargetRequiredTags;
|
||||
@ -146,11 +166,11 @@ namespace GAS.Runtime
|
||||
}
|
||||
|
||||
|
||||
public abstract class AbilityAssetT<T> : AbilityAsset where T : class
|
||||
{
|
||||
public sealed override Type AbilityType()
|
||||
{
|
||||
return typeof(T);
|
||||
}
|
||||
}
|
||||
// public abstract class AbilityAssetT<T> : AbilityAsset where T : class
|
||||
// {
|
||||
// public sealed override Type AbilityType()
|
||||
// {
|
||||
// return typeof(T);
|
||||
// }
|
||||
// }
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86bcaa66216445e19e861ed7d4c980ba
|
||||
timeCreated: 1729505774
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user