mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-09-27 10:46:17 +00:00
简单提交
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
public const string TITLE_BASE_INFO = "基本信息";
|
||||
public const string TITLE_DESCRIPTION = "描述";
|
||||
|
||||
|
||||
|
||||
#region GASSettingAsset
|
||||
|
||||
public const string TIP_CREATE_GEN_AscUtilCode =
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Tag
|
||||
|
||||
public const string BUTTON_ExpandAllTag = "展开全部";
|
||||
@@ -33,14 +33,14 @@
|
||||
public const string BUTTON_GenTagCode = "生成TagLib";
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
#region Attribute
|
||||
public const string TIP_Warning_EmptyAttribute =
|
||||
"<size=13><color=yellow><color=orange>Attribute名</color>不准为<color=red><b>空</b></color>! " +
|
||||
"Please check!</color></size>";
|
||||
public const string BUTTON_GenerateAttributeCollection = " 生成AttrLib";
|
||||
|
||||
|
||||
public const string TIP_Warning_DuplicatedAttribute =
|
||||
"<size=13><color=yellow>The <color=orange>Attribute名</color> 禁止 <color=red><b>重复</b></color>!\n" +
|
||||
"重复的Attributes名:<size=15><b><color=white> {0} </color></b></size>.</color></size>";
|
||||
@@ -53,31 +53,30 @@
|
||||
public const string ERROR_Empty = "<size=16><b>AttributeSet至少要有一个Attribute!</b></size>";
|
||||
public const string ERROR_EmptyName = "<size=16><b>AttributeSet名不可以为空!</b></size>";
|
||||
public const string ERROR_InElements = "<size=16><b><color=orange>请先修复AttributeSet的提示错误!</color></b></size>";
|
||||
|
||||
|
||||
public const string ERROR_DuplicatedAttributeSet = "<size=16><b><color=orange>存在重复AttributeSet!\n" +
|
||||
"<color=white> -> {0}</color></color></b></size>";
|
||||
public const string BUTTON_GenerateAttributeSetCode = " 生成AttrSetLib";
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region GameplayEffect
|
||||
|
||||
public const string TIP_BASE_INFO="仅用于描述,方便理解。";
|
||||
public const string TIP_GE_POLICY="Instant=瞬时,Duration=持续性,Infinite=永久";
|
||||
|
||||
public const string TIP_BASE_INFO = "仅用于描述,方便理解。";
|
||||
public const string TIP_GE_POLICY = "Instant=瞬时,Duration=持续性,Infinite=永久";
|
||||
public const string LABLE_GE_NAME = "效果名称";
|
||||
public const string LABLE_GE_DESCRIPTION = "效果描述";
|
||||
public const string TITLE_GE_POLICY="Gameplay Effect实施策略";
|
||||
public const string TITLE_GE_POLICY = "Gameplay Effect实施策略";
|
||||
public const string LABLE_GE_POLICY = "时限策略";
|
||||
public const string LABLE_GE_DURATION = "持续时间";
|
||||
public const string LABLE_GE_INTERVAL = "间隔时间";
|
||||
public const string LABLE_GE_EXEC = "间隔效果";
|
||||
public const string LABLE_GE_SnapshotPolicy = "快照策略";
|
||||
public const string TITLE_GE_GrantedAbilities = "授予能力(Ability)";
|
||||
public const string TITLE_GE_MOD = "修改器Modifier";
|
||||
public const string TITLE_GE_TAG = "标签Tag";
|
||||
public const string TITLE_GE_CUE = "提示Cue";
|
||||
|
||||
|
||||
public const string TITLE_GE_TAG_AssetTags = "AssetTags - 该[游戏效果]自身的标签";
|
||||
public const string TIP_GE_TAG_AssetTags = "AssetTags: 标签用于描述[游戏效果]自身的特定属性,包括但不限于伤害、治疗、控制等效果类型。\n这些标签有助于区分和定义[游戏效果]的作用和表现。\n可配合RemoveGameplayEffectsWithTags食用。";
|
||||
public const string TITLE_GE_TAG_GrantedTags = "GrantedTags - 授予目标单位的标签";
|
||||
@@ -90,14 +89,14 @@
|
||||
public const string TIP_GE_TAG_RemoveGameplayEffectsWithTags = "RemoveGameplayEffectsWithTags: [游戏效果]的目标单位当前持有的所有[游戏效果]中,其AssetTags或GrantedTags中具有【任一】这些标签的[游戏效果]将被移除。";
|
||||
public const string TITLE_GE_TAG_ApplicationImmunityTags = "ApplicationImmunityTags - 无法应用于具有【任一】标签的目标";
|
||||
public const string TIP_GE_TAG_ApplicationImmunityTags = "ApplicationImmunityTags: 该[游戏效果]无法作用于拥有【任一】这些标签的目标单位。";
|
||||
|
||||
|
||||
public const string TITLE_GE_CUE_CueOnExecute = "CueOnExecute - 执行时触发";
|
||||
public const string TITLE_GE_CUE_CueDurational = "CueDurational - 存在时持续触发";
|
||||
public const string TITLE_GE_CUE_CueOnAdd = "CueOnAdd - 添加时触发";
|
||||
public const string TITLE_GE_CUE_CueOnRemove = "CueOnRemove - 移除时触发";
|
||||
public const string TITLE_GE_CUE_CueOnActivate = "CueOnActivate - 激活时触发";
|
||||
public const string TITLE_GE_CUE_CueOnDeactivate = "CueOnDeactivate - 失活时触发";
|
||||
|
||||
|
||||
public const string LABEL_GRANT_ABILITY = "授予能力";
|
||||
public const string LABEL_GRANT_ABILITY_LEVEL = "能力等级";
|
||||
public const string LABEL_GRANT_ABILITY_ACTIVATION_POLICY = "激活策略";
|
||||
@@ -105,15 +104,15 @@
|
||||
public const string LABEL_GRANT_ABILITY_REMOVE_POLICY = "移除策略";
|
||||
public const string TIP_GRANT_ABILITY_ACTIVATION_POLICY = "None = 不激活,需要用户手动调用ASC相关接口激活; " +
|
||||
"WhenAdded = 添加时就激活;" +
|
||||
"SyncWithEffect = 同步GE,GE激活时激活";
|
||||
"SyncWithEffect = 同步GE,GE激活时激活";
|
||||
public const string TIP_GRANT_ABILITY_DEACTIVATION_POLICY = "None = 无相关取消激活逻辑, 需要用户调用ASC取消激活; " +
|
||||
"SyncWithEffect = 同步GE,GE失活时取消激活";
|
||||
"SyncWithEffect = 同步GE,GE失活时取消激活";
|
||||
public const string TIP_GRANT_ABILITY_REMOVE_POLICY = "None = 不移除能力;" +
|
||||
"SyncWithEffect = 同步GE,GE移除时移除" +
|
||||
"WhenEnd = 能力结束时,移除自身;" +
|
||||
"WhenCancel = 能力取消时,移除自身;" +
|
||||
"WhenCancelOrEnd = 能力取消或结束时,移除自身";
|
||||
|
||||
|
||||
public const string TITLE_GE_STACKING = "堆叠配置";
|
||||
public const string LABEL_GE_STACKING_CODENAME = "堆叠GE识别码";
|
||||
public const string LABEL_GE_STACKING_TYPE = "堆叠类型";
|
||||
@@ -124,40 +123,39 @@
|
||||
public const string LABEL_GE_STACKING_DENY_OVERFLOW_APPLICATION = "溢出的GE不生效";
|
||||
public const string LABEL_GE_STACKING_CLEAR_STACK_ON_OVERFLOW = "溢出时清空堆叠";
|
||||
public const string LABEL_GE_STACKING_CLEAR_OVERFLOW_EFFECTS = "溢出时触发的GE";
|
||||
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Ability
|
||||
|
||||
public const string ABILITY_BASEINFO="基本信息";
|
||||
public const string ABILITY_BASEINFO = "基本信息";
|
||||
public const string TIP_UNAME =
|
||||
"<size=12><b><color=white><color=orange>U-Name非常重要!</color>" +
|
||||
"GAS会使用U-Name作为Ability的标识符。" +
|
||||
"所以你必须保证U-Name的唯一性。" +
|
||||
"别担心,生成AbilityLib时工具会提醒你这一点。</color></b></size>";
|
||||
public const string ABILITY_CD_TIME="冷却时长";
|
||||
public const string ABILITY_EFFECT_CD="冷却效果";
|
||||
public const string ABILITY_EFFECT_COST="消耗效果";
|
||||
public const string ABILITY_CD_TIME = "冷却时长";
|
||||
public const string ABILITY_EFFECT_CD = "冷却效果";
|
||||
public const string ABILITY_EFFECT_COST = "消耗效果";
|
||||
public const string ABILITY_MANUAL_ENDABILITY = "手动结束能力";
|
||||
public const string BUTTON_CHECK_TIMELINE_ABILITY = "查看/编辑能力时间轴";
|
||||
public const string ABILITY_PLAY_RATE = "播放速率";
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region ASC
|
||||
|
||||
public const string TIP_ASC_BASEINFO="基本信息只用于描述这个ASC,方便策划阅读理解该ASC。";
|
||||
public const string ASC_BASE_TAG="固有标签";
|
||||
public const string ASC_BASE_ABILITY="固有能力";
|
||||
public const string ASC_AttributeSet="属性集";
|
||||
|
||||
|
||||
public const string TIP_ASC_BASEINFO = "基本信息只用于描述这个ASC,方便策划阅读理解该ASC。";
|
||||
public const string ASC_BASE_TAG = "固有标签";
|
||||
public const string ASC_BASE_ABILITY = "固有能力";
|
||||
public const string ASC_AttributeSet = "属性集";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Watcher
|
||||
|
||||
public const string TIP_WATCHER = "该窗口用于监视GAS运行状态,建议在调试GAS的角色能力,效果时打开该窗口。";
|
||||
public const string TIP_WATCHER_OnlyForGameRunning =
|
||||
public const string TIP_WATCHER_OnlyForGameRunning =
|
||||
"<size=20><b><color=yellow>监视器只在游戏运行时可用.</color></b></size>";
|
||||
|
||||
#endregion
|
||||
@@ -165,14 +163,13 @@
|
||||
#region Gameplay Cue
|
||||
|
||||
public const string CUE_ANIMATION_PATH = "动画机相对路径";
|
||||
public const string CUE_ANIMATION_INCLUDE_CHILDREN = "包括子节点";
|
||||
public const string CUE_ANIMATION_INCLUDE_CHILDREN_ANIMATOR_TIP = "在自身及孩子节点中查找动画机, 当你的动画机路径不能完全确定时(例如: 不同的皮肤节点不一致), 可勾选此项";
|
||||
public const string CUE_ANIMATION_STATE = "Animation State名";
|
||||
public const string CUE_ANIMATION_PATH_TIP = "为空表示物体根节点,示例:'A'=根节点下名为'A'的子物体,'A/B'='A'节点下名为'B'的子物体";
|
||||
|
||||
public const string CUE_SOUND_EFFECT = "音效源";
|
||||
public const string CUE_ATTACH_TO_OWNER = "是否附加到Owner";
|
||||
|
||||
|
||||
public const string CUE_VFX_PREFAB = "特效预制体";
|
||||
public const string CUE_VFX_OFFSET = "特效偏移";
|
||||
public const string CUE_VFX_ROTATION = "特效旋转";
|
||||
|
@@ -1,43 +1,50 @@
|
||||
using System;
|
||||
using GAS.Runtime;
|
||||
using JNGame.Math;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.General
|
||||
namespace GAS.General
|
||||
{
|
||||
public class GASTimer
|
||||
{
|
||||
// TODO 矫正时间差(服务器客户端时间差/暂停游戏导致的时间差)
|
||||
static int _deltaTime;
|
||||
// // TODO 矫正时间差(服务器客户端时间差/暂停游戏导致的时间差)
|
||||
// static int _deltaTime;
|
||||
|
||||
public static long Timestamp() => DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + _deltaTime;
|
||||
// public static long Timestamp() => DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + _deltaTime;
|
||||
|
||||
public static long TimestampSeconds() => Timestamp() / 1000;
|
||||
// public static long TimestampSeconds() => Timestamp() / 1000;
|
||||
|
||||
private static int _currentFrameCount;
|
||||
public static int CurrentFrameCount => _currentFrameCount;
|
||||
public static void UpdateCurrentFrameCount()
|
||||
{
|
||||
_currentFrameCount = LMath.FloorToInt((Timestamp() - _startTimestamp) / LFloat.L1000 * JexGasManager.FrameRate);
|
||||
}
|
||||
// private static int _currentFrameCount;
|
||||
// public static int CurrentFrameCount => _currentFrameCount;
|
||||
// public static void UpdateCurrentFrameCount()
|
||||
// {
|
||||
// _currentFrameCount = Mathf.FloorToInt((Timestamp() - _startTimestamp) / 1000f * FrameRate);
|
||||
// }
|
||||
|
||||
private static long _startTimestamp;
|
||||
public static long StartTimestamp => _startTimestamp;
|
||||
public static void InitStartTimestamp()
|
||||
{
|
||||
_startTimestamp = Timestamp();
|
||||
}
|
||||
// private static long _startTimestamp;
|
||||
// public static long StartTimestamp => _startTimestamp;
|
||||
// public static void InitStartTimestamp()
|
||||
// {
|
||||
// _startTimestamp = Timestamp();
|
||||
// }
|
||||
|
||||
private static long _pauseTimestamp;
|
||||
public static void Pause()
|
||||
{
|
||||
_pauseTimestamp = Timestamp();
|
||||
}
|
||||
|
||||
public static void Unpause()
|
||||
{
|
||||
_deltaTime -= (int)(Timestamp() - _pauseTimestamp);
|
||||
}
|
||||
// private static long _pauseTimestamp;
|
||||
// public static void Pause()
|
||||
// {
|
||||
// _pauseTimestamp = Timestamp();
|
||||
// }
|
||||
|
||||
// public static void Unpause()
|
||||
// {
|
||||
// _deltaTime -= (int)(Timestamp() - _pauseTimestamp);
|
||||
// }
|
||||
|
||||
// private static int _frameRate = 60;
|
||||
// public static int FrameRate => _frameRate;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private static int _TimeLineAbilityTickTime = 20;
|
||||
|
||||
public static int TimeLineAbilityTickTime => _TimeLineAbilityTickTime;
|
||||
|
||||
public static int FrameRateValue => 1000 / _TimeLineAbilityTickTime;
|
||||
}
|
||||
}
|
@@ -1,507 +1,47 @@
|
||||
using JNGame.Math;
|
||||
using UnityEngine;
|
||||
// using UnityEngine;
|
||||
|
||||
namespace GAS.General
|
||||
{
|
||||
public static class DebugExtension
|
||||
{
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DebugBox(LVector2 center, LVector2 size, LFloat angle, Color color, LFloat showTime)
|
||||
{
|
||||
var halfSize = size * LFloat.L0D5;
|
||||
var p1 = new LVector2(center.x - halfSize.x, center.y - halfSize.y);
|
||||
var p2 = new LVector2(center.x + halfSize.x, center.y - halfSize.y);
|
||||
var p3 = new LVector2(center.x + halfSize.x, center.y + halfSize.y);
|
||||
var p4 = new LVector2(center.x - halfSize.x, center.y + halfSize.y);
|
||||
// p1 绕center旋转angle角度
|
||||
p1 = RotatePoint(center, p1, angle);
|
||||
p2 = RotatePoint(center, p2, angle);
|
||||
p3 = RotatePoint(center, p3, angle);
|
||||
p4 = RotatePoint(center, p4, angle);
|
||||
DrawLine(p1, p2, color, showTime);
|
||||
DrawLine(p2, p3, color, showTime);
|
||||
DrawLine(p3, p4, color, showTime);
|
||||
DrawLine(p4, p1, color, showTime);
|
||||
}
|
||||
// namespace GAS.General
|
||||
// {
|
||||
// public static class DebugExtension
|
||||
// {
|
||||
// public static void DebugBox(Vector2 center, Vector2 size, float angle, Color color, float showTime)
|
||||
// {
|
||||
// var halfSize = size / 2;
|
||||
// var p1 = new Vector2(center.x - halfSize.x, center.y - halfSize.y);
|
||||
// var p2 = new Vector2(center.x + halfSize.x, center.y - halfSize.y);
|
||||
// var p3 = new Vector2(center.x + halfSize.x, center.y + halfSize.y);
|
||||
// var p4 = new Vector2(center.x - halfSize.x, center.y + halfSize.y);
|
||||
// // p1 绕center旋转angle角度
|
||||
// p1 = RotatePoint(center, p1, angle);
|
||||
// p2 = RotatePoint(center, p2, angle);
|
||||
// p3 = RotatePoint(center, p3, angle);
|
||||
// p4 = RotatePoint(center, p4, angle);
|
||||
// Debug.DrawLine(p1, p2, color, showTime);
|
||||
// Debug.DrawLine(p2, p3, color, showTime);
|
||||
// Debug.DrawLine(p3, p4, color, showTime);
|
||||
// Debug.DrawLine(p4, p1, color, showTime);
|
||||
// }
|
||||
|
||||
public static LVector2 RotatePoint(LVector2 center, LVector2 point, LFloat angle)
|
||||
{
|
||||
var cos = LMath.Cos(angle * LMath.Deg2Rad);
|
||||
var sin = LMath.Sin(angle * LMath.Deg2Rad);
|
||||
var x = cos * (point.x - center.x) - sin * (point.y - center.y) + center.x;
|
||||
var y = sin * (point.x - center.x) + cos * (point.y - center.y) + center.y;
|
||||
return new LVector2(x, y);
|
||||
}
|
||||
// public static Vector2 RotatePoint(Vector2 center, Vector2 point, float angle)
|
||||
// {
|
||||
// var cos = Mathf.Cos(angle * Mathf.Deg2Rad);
|
||||
// var sin = Mathf.Sin(angle * Mathf.Deg2Rad);
|
||||
// var x = cos * (point.x - center.x) - sin * (point.y - center.y) + center.x;
|
||||
// var y = sin * (point.x - center.x) + cos * (point.y - center.y) + center.y;
|
||||
// return new Vector2(x, y);
|
||||
// }
|
||||
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DebugDrawCircle(LVector2 center, LFloat radius, Color color, LFloat showTime, LFloat segments = default) // segments = 120
|
||||
{
|
||||
var step = LFloat.L360 / segments;
|
||||
var from = center + new LVector2(radius, LFloat.L0);
|
||||
for (var i = 0; i < segments; i++)
|
||||
{
|
||||
var to = center + new LVector2(radius * LMath.Cos((i + 1) * step * LMath.Deg2Rad),
|
||||
radius * LMath.Sin((i + 1) * step * LMath.Deg2Rad));
|
||||
DrawLine(from, to, color, showTime);
|
||||
from = to;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制一个圆形
|
||||
/// </summary>
|
||||
/// <param name="position">位置, 圆心</param>
|
||||
/// <param name="rotation">旋转</param>
|
||||
/// <param name="radius">半径</param>
|
||||
/// <param name="segments">分段数(建议与角度适配, 如每10°分一段: segments = LMath.CeilToInt(angle / 10))</param>
|
||||
/// <param name="color">颜色</param>
|
||||
/// <param name="duration">绘制时长(0为1帧)</param>
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawCircle(in LVector3 position, in LQuaternion rotation, LFloat radius, int segments = 36,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
DrawArc(position, rotation, radius, 360, segments, color, duration);
|
||||
}
|
||||
|
||||
public static void DrawCircle(in LVector3 position, in LVector3 forward, LFloat radius, int segments = 36,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
DrawCircle(position, LQuaternion.LookRotation(forward), radius, segments, color, duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制一个圆弧
|
||||
/// </summary>
|
||||
/// <param name="position">位置</param>
|
||||
/// <param name="rotation">旋转</param>
|
||||
/// <param name="radius">半径</param>
|
||||
/// <param name="angle">角度</param>
|
||||
/// <param name="segments">分段数(建议与角度适配, 如每10°分一段: segments = LMath.CeilToInt(angle / 10))(建议与角度适配, 如每10°分一段: segments = LMath.CeilToInt(angle / 10))</param>
|
||||
/// <param name="color">颜色</param>
|
||||
/// <param name="duration">绘制时长(0为1帧)</param>
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawArc(in LVector3 position, in LQuaternion rotation, LFloat radius, LFloat angle, int segments = 12,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
if (angle <= 0) return;
|
||||
if (radius <= 0) return;
|
||||
if (segments <= 0) return;
|
||||
|
||||
var angleStep = angle / segments;
|
||||
var lastPoint = position + rotation * (LVector3.Right * radius);
|
||||
for (int i = 1; i <= segments; i++)
|
||||
{
|
||||
var currentAngle = i * angleStep;
|
||||
var nextPoint = position + rotation * (LQuaternion.Euler(0, currentAngle, 0) * LVector3.Right * radius);
|
||||
DrawLine(lastPoint, nextPoint, color, duration);
|
||||
lastPoint = nextPoint;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawArc(in LVector3 position, in LVector3 forward, LFloat radius, LFloat angle, int segments = 12,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
DrawArc(position, LQuaternion.LookRotation(forward), radius, angle, segments, color, duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制一个圆环
|
||||
/// </summary>
|
||||
/// <param name="position">位置, 圆心</param>
|
||||
/// <param name="rotation">旋转</param>
|
||||
/// <param name="outerRadius">外圈半径</param>
|
||||
/// <param name="innerRadius">内圈半径</param>
|
||||
/// <param name="segments">分段数(建议与角度适配, 如每10°分一段: segments = LMath.CeilToInt(angle / 10))</param>
|
||||
/// <param name="color">颜色</param>
|
||||
/// <param name="duration">绘制时长(0为1帧)</param>
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawRing(in LVector3 position, in LQuaternion rotation, LFloat outerRadius, LFloat innerRadius, int segments = 36,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
if (outerRadius <= 0) return;
|
||||
if (segments <= 0) return;
|
||||
|
||||
innerRadius = LMath.Clamp(innerRadius, LFloat.L0, outerRadius);
|
||||
|
||||
// 计算圆的每个点的位置
|
||||
var angleStep = LFloat.L360 / segments;
|
||||
var lastOuterPoint = position + rotation * (LVector3.Right * outerRadius);
|
||||
var lastInnerPoint = position + rotation * (LVector3.Right * innerRadius);
|
||||
for (int i = 1; i <= segments; i++)
|
||||
{
|
||||
var angle = i * angleStep;
|
||||
var nextOuterPoint = position + rotation * (LQuaternion.Euler(0, angle, 0) * LVector3.Right * outerRadius);
|
||||
var nextInnerPoint = position + rotation * (LQuaternion.Euler(0, angle, 0) * LVector3.Right * innerRadius);
|
||||
DrawLine(lastOuterPoint, nextOuterPoint, color, duration);
|
||||
DrawLine(lastInnerPoint, nextInnerPoint, color, duration);
|
||||
DrawLine(nextOuterPoint, nextInnerPoint, color, duration);
|
||||
lastOuterPoint = nextOuterPoint;
|
||||
lastInnerPoint = nextInnerPoint;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawRing(in LVector3 position, in LVector3 forward, LFloat outerRadius, LFloat innerRadius, int segments = 36,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
DrawRing(position, LQuaternion.LookRotation(forward), outerRadius, innerRadius, segments, color, duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制一个矩形
|
||||
/// </summary>
|
||||
/// <param name="position">位置, 矩形中心点</param>
|
||||
/// <param name="rotation">旋转</param>
|
||||
/// <param name="size">矩形的宽长, 宽:左右(垂直于朝向), 长:前后(与朝向一致)</param>
|
||||
/// <param name="color">颜色</param>
|
||||
/// <param name="duration">绘制时长(0为1帧)</param>
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawRectangle(in LVector3 position, in LQuaternion rotation, in LVector2 size,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
// 计算矩形的四个角点在局部坐标系中的位置
|
||||
var halfSize = new LVector3(size.x * LFloat.L0D5, LFloat.L0, size.y * LFloat.L0D5);
|
||||
var corners = new LVector3[4];
|
||||
corners[0] = new LVector3(-halfSize.x, LFloat.L0, -halfSize.z); // 左下角
|
||||
corners[1] = new LVector3(halfSize.x, LFloat.L0, -halfSize.z); // 右下角
|
||||
corners[2] = new LVector3(halfSize.x, LFloat.L0, halfSize.z); // 右上角
|
||||
corners[3] = new LVector3(-halfSize.x, LFloat.L0, halfSize.z); // 左上角
|
||||
|
||||
// 旋转角点并转换到世界坐标系
|
||||
for (int i = 0; i < corners.Length; i++)
|
||||
{
|
||||
corners[i] = position + rotation * corners[i];
|
||||
}
|
||||
|
||||
// 绘制矩形的四条边
|
||||
DrawLine(corners[0], corners[1], color, duration); // 底边
|
||||
DrawLine(corners[1], corners[2], color, duration); // 右边
|
||||
DrawLine(corners[2], corners[3], color, duration); // 顶边
|
||||
DrawLine(corners[3], corners[0], color, duration); // 左边
|
||||
}
|
||||
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawRectangle(in LVector3 position, in LVector3 forward, in LVector2 size,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
DrawRectangle(position, LQuaternion.LookRotation(forward), size, color, duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基于位置和朝向, 在其前方绘制一个矩形(如: 基于技能释放者前方的矩形攻击范围)
|
||||
/// </summary>
|
||||
/// <param name="position">位置</param>
|
||||
/// <param name="rotation">旋转</param>
|
||||
/// <param name="size">矩形的宽长(宽:左右, 长:前后)</param>
|
||||
/// <param name="color">颜色</param>
|
||||
/// <param name="duration">绘制时长(0为1帧)</param>
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawFrontRectangle(in LVector3 position, in LQuaternion rotation, in LVector2 size,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
// 计算矩形的四个角点在局部坐标系中的位置
|
||||
var halfX = size.x * LFloat.L0D5;
|
||||
var corners = new LVector3[4];
|
||||
corners[0] = new LVector3(-halfX, LFloat.L0, LFloat.L0); // 左下角
|
||||
corners[1] = new LVector3(halfX, LFloat.L0, LFloat.L0); // 右下角
|
||||
corners[2] = new LVector3(halfX, LFloat.L0, size.y); // 右上角
|
||||
corners[3] = new LVector3(-halfX, LFloat.L0, size.y); // 左上角
|
||||
|
||||
// 旋转角点并转换到世界坐标系
|
||||
for (int i = 0; i < corners.Length; i++)
|
||||
{
|
||||
corners[i] = position + rotation * corners[i];
|
||||
}
|
||||
|
||||
// 绘制矩形的四条边
|
||||
DrawLine(corners[0], corners[1], color, duration); // 底边
|
||||
DrawLine(corners[1], corners[2], color, duration); // 右边
|
||||
DrawLine(corners[2], corners[3], color, duration); // 顶边
|
||||
DrawLine(corners[3], corners[0], color, duration); // 左边
|
||||
}
|
||||
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawFrontRectangle(in LVector3 position, in LVector3 forward, in LVector2 size,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
DrawFrontRectangle(position, LQuaternion.LookRotation(forward), size, color, duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制一个立方体
|
||||
/// </summary>
|
||||
/// <param name="position">立方体中心点</param>
|
||||
/// <param name="rotation">立方体的朝向</param>
|
||||
/// <param name="size">立方体的尺寸</param>
|
||||
/// <param name="color">颜色</param>
|
||||
/// <param name="duration">绘制时长(0为1帧)</param>
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawCube(in LVector3 position, in LQuaternion rotation, in LVector3 size,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
// 计算立方体的八个顶点在局部坐标系中的位置
|
||||
var halfSize = size * LFloat.L0D5;
|
||||
var vertices = new LVector3[8];
|
||||
|
||||
// 下底面四个顶点
|
||||
vertices[0] = new LVector3(-halfSize.x, -halfSize.y, -halfSize.z);
|
||||
vertices[1] = new LVector3(halfSize.x, -halfSize.y, -halfSize.z);
|
||||
vertices[2] = new LVector3(halfSize.x, -halfSize.y, halfSize.z);
|
||||
vertices[3] = new LVector3(-halfSize.x, -halfSize.y, halfSize.z);
|
||||
|
||||
// 上顶面四个顶点
|
||||
vertices[4] = new LVector3(-halfSize.x, halfSize.y, -halfSize.z);
|
||||
vertices[5] = new LVector3(halfSize.x, halfSize.y, -halfSize.z);
|
||||
vertices[6] = new LVector3(halfSize.x, halfSize.y, halfSize.z);
|
||||
vertices[7] = new LVector3(-halfSize.x, halfSize.y, halfSize.z);
|
||||
|
||||
// 旋转顶点并转换到世界坐标系
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
vertices[i] = position + rotation * vertices[i];
|
||||
}
|
||||
|
||||
// 绘制立方体的十二条边
|
||||
DrawLine(vertices[0], vertices[1], color, duration); // 底面边
|
||||
DrawLine(vertices[1], vertices[2], color, duration);
|
||||
DrawLine(vertices[2], vertices[3], color, duration);
|
||||
DrawLine(vertices[3], vertices[0], color, duration);
|
||||
|
||||
DrawLine(vertices[4], vertices[5], color, duration); // 顶面边
|
||||
DrawLine(vertices[5], vertices[6], color, duration);
|
||||
DrawLine(vertices[6], vertices[7], color, duration);
|
||||
DrawLine(vertices[7], vertices[4], color, duration);
|
||||
|
||||
DrawLine(vertices[0], vertices[4], color, duration); // 竖向边
|
||||
DrawLine(vertices[1], vertices[5], color, duration);
|
||||
DrawLine(vertices[2], vertices[6], color, duration);
|
||||
DrawLine(vertices[3], vertices[7], color, duration);
|
||||
}
|
||||
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawCube(in LVector3 position, in LVector3 forward, in LVector3 size,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
DrawCube(position, LQuaternion.LookRotation(forward), size, color, duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制一个圆柱体
|
||||
/// </summary>
|
||||
/// <param name="position"></param>
|
||||
/// <param name="rotation">朝向, 以圆柱的侧面为forward/right, 上下面为up</param>
|
||||
/// <param name="radius"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="segments"> </param>
|
||||
/// <param name="color"></param>
|
||||
/// <param name="duration"></param>
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawCylinder(in LVector3 position, in LQuaternion rotation, LFloat radius, LFloat height, int segments = 12,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
var offset = rotation * LVector3.Up * (height * LFloat.L0D5);
|
||||
var topCenter = position + offset;
|
||||
var bottomCenter = position - offset;
|
||||
DrawCylinder(topCenter, bottomCenter, radius, segments, color, duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制一个圆柱体
|
||||
/// </summary>
|
||||
/// <param name="position"></param>
|
||||
/// <param name="forward">朝向, forward是圆柱体的侧面(其实对于圆柱体而言forward/right都一样)</param>
|
||||
/// <param name="radius"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="segments"></param>
|
||||
/// <param name="color"></param>
|
||||
/// <param name="duration"></param>
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawCylinder(in LVector3 position, in LVector3 forward, LFloat radius, LFloat height, int segments = 12,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
DrawCylinder(position, LQuaternion.LookRotation(forward), radius, height, segments, in color, duration);
|
||||
}
|
||||
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawCylinder(in LVector3 topCenter, in LVector3 bottomCenter, LFloat radius, int segments = 12,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
if (radius <= 0) return;
|
||||
if (segments <= 0) return;
|
||||
|
||||
if (LVector3.Distance(topCenter, bottomCenter) <= LFloat.EPSILON) return;
|
||||
|
||||
var direction = (topCenter - bottomCenter).Normalized;
|
||||
|
||||
// 计算一个垂直于direction的向量作为forward
|
||||
var forward = LVector3.Cross(direction, LVector3.Up).Normalized;
|
||||
|
||||
// 如果forward和direction平行(即direction和LVector3.up共线),则选择一个不同的方向作为forward
|
||||
if (forward == LVector3.Zero)
|
||||
{
|
||||
forward = LVector3.Cross(direction, LVector3.Right).Normalized;
|
||||
}
|
||||
|
||||
var rotation = LQuaternion.LookRotation(forward, direction);
|
||||
|
||||
var angleStep = LFloat.L360 / segments;
|
||||
var offset = rotation * (LVector3.Right * radius);
|
||||
var lastTopPoint = topCenter + offset;
|
||||
var lastBottomPoint = bottomCenter + offset;
|
||||
for (int i = 1; i <= segments; i++)
|
||||
{
|
||||
var currentAngle = i * angleStep;
|
||||
offset = rotation * (LQuaternion.Euler(0, currentAngle, 0) * (LVector3.Right * radius));
|
||||
var nextTopPoint = topCenter + offset;
|
||||
var nextBottomPoint = bottomCenter + offset;
|
||||
DrawLine(lastTopPoint, nextTopPoint, color, duration);
|
||||
DrawLine(lastBottomPoint, nextBottomPoint, color, duration);
|
||||
DrawLine(nextTopPoint, nextBottomPoint, color, duration);
|
||||
lastTopPoint = nextTopPoint;
|
||||
lastBottomPoint = nextBottomPoint;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制一个扇形
|
||||
/// </summary>
|
||||
/// <param name="position">位置, 扇形所在圆的圆心</param>
|
||||
/// <param name="rotation">旋转</param>
|
||||
/// <param name="radius">扇形的半径</param>
|
||||
/// <param name="angle">扇形的角度(度)</param>
|
||||
/// <param name="segments">分段数(建议与角度适配, 如每10°分一段: segments = LMath.CeilToInt(angle / 10))</param>
|
||||
/// <param name="color">颜色</param>
|
||||
/// <param name="duration">绘制时长(0为1帧)</param>
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawSector(LVector3 position, LQuaternion rotation, LFloat radius, LFloat angle, int segments = 12,
|
||||
Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
DrawAnnularSector(position, rotation, radius, 0, angle, segments, color, duration);
|
||||
}
|
||||
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawSector(in LVector3 position, in LVector3 forward, LFloat radius, LFloat angle, int segments = 12,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
DrawSector(position, LQuaternion.LookRotation(forward), radius, angle, segments, color, duration);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 绘制一个环形扇区
|
||||
/// </summary>
|
||||
/// <param name="position">位置, 扇形所在圆的圆心</param>
|
||||
/// <param name="rotation">旋转</param>
|
||||
/// <param name="outerRadius">扇形的外半径</param>
|
||||
/// <param name="innerRadius">扇形的内半径, 为0时为标准扇形</param>
|
||||
/// <param name="angle">扇形的角度(度)</param>
|
||||
/// <param name="segments">分段数(建议与角度适配, 如每10°分一段: segments = LMath.CeilToInt(angle / 10))</param>
|
||||
/// <param name="color">颜色</param>
|
||||
/// <param name="duration">绘制时长(0为1帧)</param>
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawAnnularSector(in LVector3 position, in LQuaternion rotation, LFloat outerRadius, LFloat innerRadius, LFloat angle, int segments = 12,
|
||||
in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
if (outerRadius <= 0) return;
|
||||
if (segments <= 0) return;
|
||||
if (angle <= 0) return;
|
||||
|
||||
innerRadius = LMath.Clamp(innerRadius, LFloat.L0, outerRadius);
|
||||
|
||||
var angleStep = angle / segments;
|
||||
var currentAngle = -angle * LFloat.L0D5;
|
||||
|
||||
var outerPoints = new LVector3[segments + 1];
|
||||
var innerPoints = new LVector3[segments + 1];
|
||||
|
||||
// 计算内外扇形的点
|
||||
for (var i = 0; i <= segments; i++)
|
||||
{
|
||||
var currentDirection = rotation * LQuaternion.Euler(0, currentAngle, 0) * LVector3.Forward;
|
||||
outerPoints[i] = position + currentDirection * outerRadius;
|
||||
innerPoints[i] = position + currentDirection * innerRadius;
|
||||
currentAngle += angleStep;
|
||||
}
|
||||
|
||||
// 绘制内外扇形的边缘
|
||||
for (var i = 0; i <= segments; i++)
|
||||
{
|
||||
// 绘制内扇形的边缘
|
||||
if (i > 0)
|
||||
{
|
||||
DrawLine(innerPoints[i - 1], innerPoints[i], color, duration);
|
||||
DrawLine(outerPoints[i - 1], outerPoints[i], color, duration);
|
||||
}
|
||||
|
||||
// 绘制从中心到内外扇形点的线段
|
||||
DrawLine(innerPoints[i], outerPoints[i], color, duration);
|
||||
}
|
||||
|
||||
// 绘制内扇形的两侧边缘
|
||||
DrawLine(position, innerPoints[0], color, duration);
|
||||
DrawLine(position, innerPoints[segments], color, duration);
|
||||
}
|
||||
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawAnnularSector(in LVector3 position, in LVector3 forward, LFloat outerRadius, LFloat innerRadius, LFloat angle, int segments = 12, in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
DrawAnnularSector(position, LQuaternion.LookRotation(forward), outerRadius, innerRadius, angle, segments, color, duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制一条线段
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="end"></param>
|
||||
/// <param name="color">颜色</param>
|
||||
/// <param name="duration">绘制时长(0为1帧)</param>
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawLine(in LVector3 start, in LVector3 end, in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
Debug.DrawLine(start.ToVector3(), end.ToVector3(), color ?? Color.cyan, duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制一个箭头
|
||||
/// </summary>
|
||||
/// <param name="origin"></param>
|
||||
/// <param name="destination"></param>
|
||||
/// <param name="color">颜色</param>
|
||||
/// <param name="duration">绘制时长(0为1帧)</param>
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawArrow(in LVector3 origin, in LVector3 destination, in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
DrawLine(origin, destination, color, duration);
|
||||
var direction = destination - origin;
|
||||
var right = LQuaternion.LookRotation(direction) * LQuaternion.Euler(0, 180 + 30, 0) * LVector3.Forward;
|
||||
var left = LQuaternion.LookRotation(direction) * LQuaternion.Euler(0, 180 - 30, 0) * LVector3.Forward;
|
||||
DrawLine(destination, destination + right, color, duration);
|
||||
DrawLine(destination, destination + left, color, duration);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 绘制一个箭头
|
||||
/// </summary>
|
||||
/// <param name="origin"></param>
|
||||
/// <param name="rotation"></param>
|
||||
/// <param name="length">长度</param>
|
||||
/// <param name="color">颜色</param>
|
||||
/// <param name="duration">绘制时长(0为1帧)</param>
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawArrow(in LVector3 origin, in LQuaternion rotation, LFloat length, in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
var direction = rotation * LVector3.Forward;
|
||||
var destination = origin + direction * length;
|
||||
DrawArrow(origin, destination, color, duration);
|
||||
}
|
||||
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void DrawArrow(in LVector3 origin, in LVector3 direction, LFloat length, in Color? color = null, LFloat duration = default) //duration = 0
|
||||
{
|
||||
var destination = origin + direction.Normalized * length;
|
||||
DrawArrow(origin, destination, color, duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
// public static void DebugDrawCircle (Vector2 center, float radius, Color color, float showTime,float segments = 120)
|
||||
// {
|
||||
// var step = 360f / segments;
|
||||
// var from = center + new Vector2(radius, 0);
|
||||
// for (var i = 0; i < segments; i++)
|
||||
// {
|
||||
// var to = center + new Vector2(radius * Mathf.Cos((i + 1) * step * Mathf.Deg2Rad),
|
||||
// radius * Mathf.Sin((i + 1) * step * Mathf.Deg2Rad));
|
||||
// Debug.DrawLine(from, to, color, showTime);
|
||||
// from = to;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
@@ -1,90 +1,89 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.Animations;
|
||||
#endif
|
||||
// using System.Collections.Generic;
|
||||
// using UnityEngine;
|
||||
|
||||
namespace GAS.General
|
||||
{
|
||||
public static class GASAnimatorUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// Only For Editor
|
||||
/// </summary>
|
||||
/// <param name="animator"></param>
|
||||
/// <param name="layerIndex"></param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<string, AnimationClip> GetAllAnimationState(this Animator animator, int layerIndex = 0)
|
||||
{
|
||||
#pragma warning disable 162
|
||||
#if UNITY_EDITOR
|
||||
var result = new Dictionary<string, AnimationClip>();
|
||||
// namespace GAS.General
|
||||
// {
|
||||
// #if UNITY_EDITOR
|
||||
// using UnityEditor;
|
||||
// using UnityEditor.Animations;
|
||||
// #endif
|
||||
|
||||
var runtimeController = animator.runtimeAnimatorController;
|
||||
if (runtimeController == null)
|
||||
{
|
||||
Debug.LogError("RuntimeAnimatorController must not be null.");
|
||||
return null;
|
||||
}
|
||||
// public static class GASAnimatorUtil
|
||||
// {
|
||||
// /// <summary>
|
||||
// /// Only For Editor
|
||||
// /// </summary>
|
||||
// /// <param name="animator"></param>
|
||||
// /// <param name="layerIndex"></param>
|
||||
// /// <returns></returns>
|
||||
// public static Dictionary<string, AnimationClip> GetAllAnimationState(this Animator animator, int layerIndex = 0)
|
||||
// {
|
||||
// #if UNITY_EDITOR
|
||||
// var result = new Dictionary<string, AnimationClip>();
|
||||
|
||||
if (animator.runtimeAnimatorController is AnimatorOverrideController)
|
||||
{
|
||||
var overrideController =
|
||||
AssetDatabase.LoadAssetAtPath<AnimatorOverrideController>(
|
||||
AssetDatabase.GetAssetPath(runtimeController));
|
||||
if (overrideController == null)
|
||||
{
|
||||
Debug.LogErrorFormat("AnimatorOverrideController must not be null.");
|
||||
return null;
|
||||
}
|
||||
// var runtimeController = animator.runtimeAnimatorController;
|
||||
// if (runtimeController == null)
|
||||
// {
|
||||
// Debug.LogError("RuntimeAnimatorController must not be null.");
|
||||
// return null;
|
||||
// }
|
||||
|
||||
var controller =
|
||||
AssetDatabase.LoadAssetAtPath<AnimatorController>(
|
||||
AssetDatabase.GetAssetPath(overrideController.runtimeAnimatorController));
|
||||
var overrides = new List<KeyValuePair<AnimationClip, AnimationClip>>();
|
||||
overrideController.GetOverrides(overrides);
|
||||
// 获取 Layer 的状态机
|
||||
var stateMachine = controller.layers[layerIndex].stateMachine;
|
||||
// 遍历所有状态并打印名称
|
||||
foreach (var state in stateMachine.states)
|
||||
{
|
||||
if (state.state.motion is AnimationClip clip)
|
||||
{
|
||||
foreach (var pair in overrides)
|
||||
{
|
||||
if (pair.Key.name == clip.name)
|
||||
{
|
||||
result.Add(state.state.name, pair.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if (animator.runtimeAnimatorController is AnimatorOverrideController)
|
||||
// {
|
||||
// var overrideController =
|
||||
// AssetDatabase.LoadAssetAtPath<AnimatorOverrideController>(
|
||||
// AssetDatabase.GetAssetPath(runtimeController));
|
||||
// if (overrideController == null)
|
||||
// {
|
||||
// Debug.LogErrorFormat("AnimatorOverrideController must not be null.");
|
||||
// return null;
|
||||
// }
|
||||
|
||||
if (!result.ContainsKey(state.state.name)) result.Add(state.state.name, clip);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var controller =
|
||||
AssetDatabase.LoadAssetAtPath<AnimatorController>(AssetDatabase.GetAssetPath(runtimeController));
|
||||
if (controller == null)
|
||||
{
|
||||
Debug.LogErrorFormat("AnimatorController must not be null.");
|
||||
return null;
|
||||
}
|
||||
// var controller =
|
||||
// AssetDatabase.LoadAssetAtPath<AnimatorController>(
|
||||
// AssetDatabase.GetAssetPath(overrideController.runtimeAnimatorController));
|
||||
// var overrides = new List<KeyValuePair<AnimationClip, AnimationClip>>();
|
||||
// overrideController.GetOverrides(overrides);
|
||||
// // 获取 Layer 的状态机
|
||||
// var stateMachine = controller.layers[layerIndex].stateMachine;
|
||||
// // 遍历所有状态并打印名称
|
||||
// foreach (var state in stateMachine.states)
|
||||
// {
|
||||
// if (state.state.motion is AnimationClip clip)
|
||||
// {
|
||||
// foreach (var pair in overrides)
|
||||
// {
|
||||
// if (pair.Key.name == clip.name)
|
||||
// {
|
||||
// result.Add(state.state.name, pair.Value);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if(!result.ContainsKey(state.state.name)) result.Add(state.state.name, clip);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// var controller =
|
||||
// AssetDatabase.LoadAssetAtPath<AnimatorController>(AssetDatabase.GetAssetPath(runtimeController));
|
||||
// if (controller == null)
|
||||
// {
|
||||
// Debug.LogErrorFormat("AnimatorController must not be null.");
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// 获取第一个 Layer 的状态机
|
||||
var stateMachine = controller.layers[layerIndex].stateMachine;
|
||||
// 遍历所有状态并打印名称
|
||||
foreach (var state in stateMachine.states)
|
||||
result.Add(state.state.name, state.state.motion as AnimationClip);
|
||||
}
|
||||
// // 获取第一个 Layer 的状态机
|
||||
// var stateMachine = controller.layers[layerIndex].stateMachine;
|
||||
// // 遍历所有状态并打印名称
|
||||
// foreach (var state in stateMachine.states)
|
||||
// result.Add(state.state.name, state.state.motion as AnimationClip);
|
||||
// }
|
||||
|
||||
return result;
|
||||
#endif
|
||||
return null;
|
||||
#pragma warning restore 162
|
||||
}
|
||||
}
|
||||
}
|
||||
// return result;
|
||||
// #endif
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
@@ -1,13 +0,0 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace System.Runtime.CompilerServices
|
||||
{
|
||||
/// <summary>
|
||||
/// 让Unity支持init setter
|
||||
/// <see href="https://docs.unity.cn/cn/2022.3/Manual/CSharpCompiler.html">unity文档</see>。
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public class IsExternalInit
|
||||
{
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac5d19bb315743de9f460aae665ccd42
|
||||
timeCreated: 1723619186
|
@@ -1,3 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6f50d4142b94bc3b37233ff4806abf6
|
||||
timeCreated: 1723102748
|
||||
fileFormatVersion: 2
|
||||
guid: 4786837dcf7f48c8abd8fd5d6d92fda7
|
||||
timeCreated: 1723551728
|
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
using JNGame.Runtime.Util;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
namespace GAS.General
|
||||
{
|
||||
@@ -30,9 +30,7 @@ namespace GAS.General
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
Debug.LogWarning("ArrayPool<T>.Recycle: obj is null");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -115,9 +113,7 @@ namespace GAS.General
|
||||
}
|
||||
|
||||
Interlocked.Decrement(ref _numItems);
|
||||
#if UNITY_EDITOR
|
||||
Debug.LogWarning($"ArrayPool<{typeof(T).FullName}>.Return: Exceed max capacity({_maxCapacity}), consider increase max capacity.");
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@@ -2,8 +2,8 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using JNGame.Runtime.Util;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
namespace GAS.General
|
||||
{
|
||||
@@ -12,20 +12,19 @@ namespace GAS.General
|
||||
bool IsFromPool { get; set; }
|
||||
}
|
||||
|
||||
public class JexGasObjectPool
|
||||
public class ObjectPool
|
||||
{
|
||||
private static JexGasObjectPool _singleton;
|
||||
|
||||
public static JexGasObjectPool Instance => _singleton ??= new JexGasObjectPool();
|
||||
private static ObjectPool _singleton;
|
||||
public static ObjectPool Instance => _singleton ??= new ObjectPool();
|
||||
|
||||
private readonly ConcurrentDictionary<Type, Pool> _objPool = new();
|
||||
|
||||
private readonly Func<Type, Pool> _addPoolFunc = type => new Pool(type, 1024);
|
||||
|
||||
public static void Awake()
|
||||
public static void Init()
|
||||
{
|
||||
_singleton = null;
|
||||
_singleton = new JexGasObjectPool();
|
||||
_singleton = new ObjectPool();
|
||||
}
|
||||
|
||||
public static void Destroy()
|
||||
@@ -90,7 +89,7 @@ namespace GAS.General
|
||||
/// <summary>
|
||||
/// 线程安全的无锁对象池
|
||||
/// </summary>
|
||||
private class Pool
|
||||
public class Pool
|
||||
{
|
||||
private readonly Type _objectType;
|
||||
private readonly int _maxCapacity;
|
||||
@@ -140,9 +139,7 @@ namespace GAS.General
|
||||
}
|
||||
|
||||
Interlocked.Decrement(ref _numItems);
|
||||
#if UNITY_EDITOR
|
||||
Debug.LogWarning($"Pool<{_objectType.FullName}>.Return: Exceed max capacity({_maxCapacity}), consider increase max capacity.");
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
@@ -1,350 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GAS.General
|
||||
{
|
||||
/// <summary>
|
||||
/// 按优先级取值
|
||||
/// <para>可以动态修改默认优先级和默认值, 适用于延迟初始化的情况</para>
|
||||
/// <para>通过设置默认值, 配合RemoveAll()使用可立刻恢复默认值</para>
|
||||
/// <para>一般来说默认值的优先级应该是最低的, 但是允许默认值的优先级高于其他值</para>
|
||||
/// <para>优先级可以相同, 则取优先级为: 默认值 > 先添加的值 > 后添加的值</para>
|
||||
/// </summary>
|
||||
public sealed class PriorityValue<T> : IDisposable
|
||||
{
|
||||
#if false //C# 10.0+
|
||||
public readonly record struct Data(string Key, int Priority, T Value);
|
||||
#else
|
||||
public record Data(string Key, int Priority, T Value)
|
||||
{
|
||||
public string Key { get; } = Key;
|
||||
public int Priority { get; } = Priority;
|
||||
public T Value { get; } = Value;
|
||||
}
|
||||
#endif
|
||||
|
||||
private readonly List<Data> _datas; // 按优先级降序排列
|
||||
private readonly object _lock;
|
||||
|
||||
public string CurrentKey
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _currentData.Key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int CurrentPriority
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _currentData.Priority;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public T CurrentValue
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _currentData.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string DefaultKey => "@default";
|
||||
|
||||
public int DefaultPriority
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _defaultData.Priority;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public T DefaultValue
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _defaultData.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Data _defaultData;
|
||||
private Data _currentData;
|
||||
|
||||
public delegate void PostValueChanged(T oldValue, T newValue);
|
||||
|
||||
private event PostValueChanged OnPostValueChanged;
|
||||
|
||||
public PriorityValue() : this(default)
|
||||
{
|
||||
}
|
||||
|
||||
public PriorityValue(T defaultValue) :
|
||||
this(int.MinValue, defaultValue)
|
||||
{
|
||||
}
|
||||
|
||||
public PriorityValue(int defaultPriority, T defaultValue)
|
||||
{
|
||||
_defaultData = new(DefaultKey, defaultPriority, defaultValue);
|
||||
_currentData = _defaultData;
|
||||
_datas = new();
|
||||
_lock = new();
|
||||
}
|
||||
|
||||
public T Add(string key, int priority, T value)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key));
|
||||
|
||||
var index = _datas.FindIndex(data => data.Key == key);
|
||||
if (index < 0)
|
||||
{
|
||||
Insert(key, priority, value);
|
||||
Refresh();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Key {key} already exists.");
|
||||
}
|
||||
|
||||
return CurrentValue;
|
||||
}
|
||||
}
|
||||
|
||||
public T AddOrSet(string key, int priority, T value)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key));
|
||||
|
||||
var index = _datas.FindIndex(data => data.Key == key);
|
||||
if (index >= 0)
|
||||
{
|
||||
if (_datas[index].Priority == priority)
|
||||
{
|
||||
_datas[index] = new(key, priority, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
_datas.RemoveAt(index);
|
||||
Insert(key, priority, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Insert(key, priority, value);
|
||||
}
|
||||
|
||||
Refresh();
|
||||
|
||||
return CurrentValue;
|
||||
}
|
||||
}
|
||||
|
||||
private void Insert(string key, int priority, T value)
|
||||
{
|
||||
var data = new Data(key, priority, value);
|
||||
var insertIndex = _datas.Count;
|
||||
for (var i = 0; i < _datas.Count; i++)
|
||||
{
|
||||
if (priority > _datas[i].Priority)
|
||||
{
|
||||
insertIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_datas.Insert(insertIndex, data);
|
||||
}
|
||||
|
||||
public T SetDefault(int priority, T value)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_defaultData.Priority != priority || !EqualityComparer<T>.Default.Equals(_defaultData.Value, value))
|
||||
{
|
||||
_defaultData = new(DefaultKey, priority, value);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
return CurrentValue;
|
||||
}
|
||||
}
|
||||
|
||||
public T SetDefaultPriority(int priority)
|
||||
{
|
||||
return SetDefault(priority, DefaultValue);
|
||||
}
|
||||
|
||||
public T SetDefaultValue(T value)
|
||||
{
|
||||
return SetDefault(DefaultPriority, value);
|
||||
}
|
||||
|
||||
public T Remove(string key)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
var index = _datas.FindIndex(data => data.Key == key);
|
||||
if (index >= 0)
|
||||
{
|
||||
_datas.RemoveAt(index);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
return CurrentValue;
|
||||
}
|
||||
}
|
||||
|
||||
public T RemoveAll()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_datas.Count > 0)
|
||||
{
|
||||
_datas.Clear();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
return CurrentValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_currentData = _defaultData;
|
||||
_datas.Clear();
|
||||
OnPostValueChanged = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void Refresh()
|
||||
{
|
||||
var oldValue = _currentData.Value;
|
||||
|
||||
_currentData = _defaultData;
|
||||
|
||||
if (_datas.Count > 0)
|
||||
{
|
||||
var data = _datas[0];
|
||||
if (data.Priority > _defaultData.Priority)
|
||||
{
|
||||
_currentData = data;
|
||||
}
|
||||
}
|
||||
|
||||
if (EqualityComparer<T>.Default.Equals(oldValue, _currentData.Value) == false)
|
||||
{
|
||||
OnPostValueChanged?.Invoke(oldValue, _currentData.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterPostValueChanged(PostValueChanged listener)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
OnPostValueChanged += listener;
|
||||
}
|
||||
}
|
||||
|
||||
public void UnregisterPostValueChanged(PostValueChanged listener)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
OnPostValueChanged -= listener;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过Enable控制PriorityValue的某个key是否生效, 省去了手动管理Add/Remove等繁琐操作
|
||||
/// </summary>
|
||||
public sealed class PriorityValueToggle<T> : IDisposable
|
||||
{
|
||||
private PriorityValue<T>.Data _data;
|
||||
public PriorityValue<T> PriorityValue { get; }
|
||||
|
||||
public string Key => _data.Key;
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get => _data.Priority;
|
||||
set
|
||||
{
|
||||
if (_data.Priority != value)
|
||||
{
|
||||
_data = new(Key, value, Value);
|
||||
if (Enabled)
|
||||
{
|
||||
PriorityValue?.AddOrSet(Key, Priority, Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public T Value
|
||||
{
|
||||
get => _data.Value;
|
||||
set
|
||||
{
|
||||
if (!EqualityComparer<T>.Default.Equals(_data.Value, value))
|
||||
{
|
||||
_data = new(Key, Priority, value);
|
||||
if (Enabled)
|
||||
{
|
||||
PriorityValue?.AddOrSet(Key, Priority, Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _enabled;
|
||||
|
||||
public bool Enabled
|
||||
{
|
||||
get => _enabled;
|
||||
set
|
||||
{
|
||||
if (_enabled != value)
|
||||
{
|
||||
_enabled = value;
|
||||
if (_enabled) PriorityValue?.AddOrSet(Key, Priority, Value);
|
||||
else PriorityValue?.Remove(Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PriorityValueToggle(PriorityValue<T> priorityValue, string key, int priority, T value, bool enableImmediately = false)
|
||||
{
|
||||
PriorityValue = priorityValue;
|
||||
_data = new(key, priority, value);
|
||||
|
||||
if (enableImmediately)
|
||||
Enabled = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5fa92b69503043a58c6b9b79b15b8f2c
|
||||
timeCreated: 1719295275
|
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace GAS.General
|
||||
@@ -17,8 +16,14 @@ namespace GAS.General
|
||||
try
|
||||
{
|
||||
var types = assembly.GetTypes();
|
||||
|
||||
sonTypes.AddRange(types.Where(type => type.IsSubclassOf(parentType) && !type.IsAbstract));
|
||||
foreach (var type in types)
|
||||
{
|
||||
if (type.IsSubclassOf(parentType) && !type.IsAbstract)
|
||||
{
|
||||
sonTypes.Add(type);
|
||||
}
|
||||
}
|
||||
// sonTypes.AddRange(types.Where(type => type.IsSubclassOf(parentType) && !type.IsAbstract));
|
||||
}
|
||||
catch (ReflectionTypeLoadException)
|
||||
{
|
||||
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 51efeef0278341a9ab883d49a20bd485
|
||||
timeCreated: 1711514345
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 207a4ba83f8f4b799e477e19a8d8b9d9
|
||||
timeCreated: 1729569447
|
Reference in New Issue
Block a user