2025-07-14 11:40:08 +08:00
|
|
|
|
using System;
|
2025-07-13 19:23:45 +08:00
|
|
|
|
using System.Xml.Linq;
|
2025-07-14 11:40:08 +08:00
|
|
|
|
using UnityEngine;
|
2025-07-13 19:23:45 +08:00
|
|
|
|
|
|
|
|
|
|
namespace Data
|
|
|
|
|
|
{
|
2025-07-14 11:40:08 +08:00
|
|
|
|
public enum Orientation
|
|
|
|
|
|
{
|
|
|
|
|
|
Down,
|
|
|
|
|
|
Left,
|
|
|
|
|
|
Right,
|
|
|
|
|
|
Up
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-27 19:56:49 +08:00
|
|
|
|
public enum EntityState
|
2025-07-14 11:40:08 +08:00
|
|
|
|
{
|
2025-08-27 19:56:49 +08:00
|
|
|
|
Idle,
|
|
|
|
|
|
Walking,
|
|
|
|
|
|
MeleeAttack,
|
|
|
|
|
|
RangedAttack,
|
2025-09-28 15:02:57 +08:00
|
|
|
|
Death,
|
2025-07-14 11:40:08 +08:00
|
|
|
|
}
|
2025-08-27 19:56:49 +08:00
|
|
|
|
|
2025-07-13 20:54:44 +08:00
|
|
|
|
public class DrawingOrderDef : Define
|
2025-07-13 19:23:45 +08:00
|
|
|
|
{
|
2025-08-27 19:56:49 +08:00
|
|
|
|
public DrawNodeDef idle_down;
|
|
|
|
|
|
public DrawNodeDef idle_up;
|
|
|
|
|
|
public DrawNodeDef idle_left;
|
|
|
|
|
|
public DrawNodeDef idle_right;
|
|
|
|
|
|
|
|
|
|
|
|
public DrawNodeDef walk_down;
|
|
|
|
|
|
public DrawNodeDef walk_up;
|
|
|
|
|
|
public DrawNodeDef walk_left;
|
|
|
|
|
|
public DrawNodeDef walk_right;
|
|
|
|
|
|
|
|
|
|
|
|
public DrawNodeDef meleeAttack_down;
|
|
|
|
|
|
public DrawNodeDef meleeAttack_up;
|
|
|
|
|
|
public DrawNodeDef meleeAttack_left;
|
|
|
|
|
|
public DrawNodeDef meleeAttack_right;
|
|
|
|
|
|
|
|
|
|
|
|
public DrawNodeDef rangedAttack_down;
|
|
|
|
|
|
public DrawNodeDef rangedAttack_up;
|
|
|
|
|
|
public DrawNodeDef rangedAttack_left;
|
|
|
|
|
|
public DrawNodeDef rangedAttack_right;
|
2025-09-28 15:02:57 +08:00
|
|
|
|
|
|
|
|
|
|
public DrawNodeDef death_down;
|
|
|
|
|
|
public DrawNodeDef death_up;
|
|
|
|
|
|
public DrawNodeDef death_left;
|
|
|
|
|
|
public DrawNodeDef death_right;
|
2025-08-28 16:20:24 +08:00
|
|
|
|
|
2025-08-27 19:56:49 +08:00
|
|
|
|
public DrawNodeDef GetDrawNodeDef(EntityState state, Orientation orientation,
|
|
|
|
|
|
out Orientation? fallbackOrientation)
|
2025-07-13 19:23:45 +08:00
|
|
|
|
{
|
2025-08-27 19:56:49 +08:00
|
|
|
|
fallbackOrientation = null;
|
|
|
|
|
|
|
|
|
|
|
|
// 根据状态和方向获取对应的DrawNodeDef
|
|
|
|
|
|
var result = GetDrawNodeDefInternal(state, orientation);
|
2025-07-14 11:40:08 +08:00
|
|
|
|
|
2025-08-27 19:56:49 +08:00
|
|
|
|
if (result != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
2025-08-19 20:22:10 +08:00
|
|
|
|
|
2025-08-27 19:56:49 +08:00
|
|
|
|
// 如果找不到,按照规则查找替补
|
2025-07-25 19:16:58 +08:00
|
|
|
|
switch (orientation)
|
2025-07-21 13:58:58 +08:00
|
|
|
|
{
|
2025-07-25 19:16:58 +08:00
|
|
|
|
case Orientation.Up:
|
2025-08-27 19:56:49 +08:00
|
|
|
|
// 上方向优先找下方向
|
|
|
|
|
|
result = GetDrawNodeDefInternal(state, Orientation.Down);
|
|
|
|
|
|
if (result != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
fallbackOrientation = Orientation.Down;
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 其次找左右方向
|
|
|
|
|
|
result = GetDrawNodeDefInternal(state, Orientation.Left);
|
|
|
|
|
|
if (result != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
fallbackOrientation = Orientation.Left;
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result = GetDrawNodeDefInternal(state, Orientation.Right);
|
|
|
|
|
|
if (result != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
fallbackOrientation = Orientation.Right;
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-25 19:16:58 +08:00
|
|
|
|
break;
|
2025-08-27 19:56:49 +08:00
|
|
|
|
|
|
|
|
|
|
case Orientation.Down:
|
|
|
|
|
|
// 下方向优先找上方向
|
|
|
|
|
|
result = GetDrawNodeDefInternal(state, Orientation.Up);
|
|
|
|
|
|
if (result != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
fallbackOrientation = Orientation.Up;
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 其次找左右方向
|
|
|
|
|
|
result = GetDrawNodeDefInternal(state, Orientation.Left);
|
|
|
|
|
|
if (result != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
fallbackOrientation = Orientation.Left;
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result = GetDrawNodeDefInternal(state, Orientation.Right);
|
|
|
|
|
|
if (result != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
fallbackOrientation = Orientation.Right;
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
2025-07-25 19:16:58 +08:00
|
|
|
|
case Orientation.Left:
|
2025-08-27 19:56:49 +08:00
|
|
|
|
// 左方向优先找右方向
|
|
|
|
|
|
result = GetDrawNodeDefInternal(state, Orientation.Right);
|
|
|
|
|
|
if (result != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
fallbackOrientation = Orientation.Right;
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 其次找上下方向
|
|
|
|
|
|
result = GetDrawNodeDefInternal(state, Orientation.Up);
|
|
|
|
|
|
if (result != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
fallbackOrientation = Orientation.Up;
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result = GetDrawNodeDefInternal(state, Orientation.Down);
|
|
|
|
|
|
if (result != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
fallbackOrientation = Orientation.Down;
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-25 19:16:58 +08:00
|
|
|
|
break;
|
2025-08-27 19:56:49 +08:00
|
|
|
|
|
2025-07-25 19:16:58 +08:00
|
|
|
|
case Orientation.Right:
|
2025-08-27 19:56:49 +08:00
|
|
|
|
// 右方向优先找左方向
|
|
|
|
|
|
result = GetDrawNodeDefInternal(state, Orientation.Left);
|
|
|
|
|
|
if (result != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
fallbackOrientation = Orientation.Left;
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 其次找上下方向
|
|
|
|
|
|
result = GetDrawNodeDefInternal(state, Orientation.Up);
|
|
|
|
|
|
if (result != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
fallbackOrientation = Orientation.Up;
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result = GetDrawNodeDefInternal(state, Orientation.Down);
|
|
|
|
|
|
if (result != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
fallbackOrientation = Orientation.Down;
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-25 19:16:58 +08:00
|
|
|
|
break;
|
|
|
|
|
|
default:
|
2025-08-27 19:56:49 +08:00
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(orientation), orientation, null);
|
2025-07-21 13:58:58 +08:00
|
|
|
|
}
|
2025-07-14 17:57:27 +08:00
|
|
|
|
|
2025-08-27 19:56:49 +08:00
|
|
|
|
// 如果所有替补都找不到,返回null
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2025-07-21 13:58:58 +08:00
|
|
|
|
|
2025-08-27 19:56:49 +08:00
|
|
|
|
private DrawNodeDef GetDrawNodeDefInternal(EntityState state, Orientation orientation)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 根据状态和方向获取对应的DrawNodeDef
|
|
|
|
|
|
switch (state)
|
2025-08-19 20:22:10 +08:00
|
|
|
|
{
|
2025-08-27 19:56:49 +08:00
|
|
|
|
case EntityState.Idle:
|
|
|
|
|
|
switch (orientation)
|
|
|
|
|
|
{
|
|
|
|
|
|
case Orientation.Down: return idle_down;
|
|
|
|
|
|
case Orientation.Up: return idle_up;
|
|
|
|
|
|
case Orientation.Left: return idle_left;
|
|
|
|
|
|
case Orientation.Right: return idle_right;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case EntityState.Walking:
|
|
|
|
|
|
switch (orientation)
|
|
|
|
|
|
{
|
|
|
|
|
|
case Orientation.Down: return walk_down;
|
|
|
|
|
|
case Orientation.Up: return walk_up;
|
|
|
|
|
|
case Orientation.Left: return walk_left;
|
|
|
|
|
|
case Orientation.Right: return walk_right;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case EntityState.MeleeAttack:
|
|
|
|
|
|
switch (orientation)
|
|
|
|
|
|
{
|
|
|
|
|
|
case Orientation.Down: return meleeAttack_down;
|
|
|
|
|
|
case Orientation.Up: return meleeAttack_up;
|
|
|
|
|
|
case Orientation.Left: return meleeAttack_left;
|
|
|
|
|
|
case Orientation.Right: return meleeAttack_right;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case EntityState.RangedAttack:
|
|
|
|
|
|
switch (orientation)
|
|
|
|
|
|
{
|
|
|
|
|
|
case Orientation.Down: return rangedAttack_down;
|
|
|
|
|
|
case Orientation.Up: return rangedAttack_up;
|
|
|
|
|
|
case Orientation.Left: return rangedAttack_left;
|
|
|
|
|
|
case Orientation.Right: return rangedAttack_right;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-28 15:02:57 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case EntityState.Death:
|
|
|
|
|
|
switch (orientation)
|
|
|
|
|
|
{
|
|
|
|
|
|
case Orientation.Down: return death_down;
|
|
|
|
|
|
case Orientation.Up: return death_up;
|
|
|
|
|
|
case Orientation.Left: return death_left;
|
|
|
|
|
|
case Orientation.Right: return death_right;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-27 19:56:49 +08:00
|
|
|
|
break;
|
2025-08-19 20:22:10 +08:00
|
|
|
|
}
|
2025-07-21 13:58:58 +08:00
|
|
|
|
|
2025-08-27 19:56:49 +08:00
|
|
|
|
return null;
|
2025-07-21 13:58:58 +08:00
|
|
|
|
}
|
2025-07-13 19:23:45 +08:00
|
|
|
|
}
|
2025-07-14 11:40:08 +08:00
|
|
|
|
|
|
|
|
|
|
public class DrawNodeDef : Define
|
2025-07-13 19:23:45 +08:00
|
|
|
|
{
|
2025-09-19 08:26:54 +08:00
|
|
|
|
public string[] textures;
|
|
|
|
|
|
public DrawNodeDef[] nodes;
|
2025-07-14 11:40:08 +08:00
|
|
|
|
public string nodeName;
|
|
|
|
|
|
public Vector2 position = new(0, 0);
|
2025-09-19 08:26:54 +08:00
|
|
|
|
public float FPS = 5f;
|
2025-07-14 11:40:08 +08:00
|
|
|
|
|
2025-07-13 19:23:45 +08:00
|
|
|
|
public override bool Init(XElement xmlDef)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.Init(xmlDef);
|
2025-07-14 11:40:08 +08:00
|
|
|
|
|
2025-08-28 16:20:24 +08:00
|
|
|
|
nodeName = xmlDef.Attribute("name")?.Value ?? "noName";
|
2025-09-28 15:02:57 +08:00
|
|
|
|
position = Utils.StringUtils.StringToVector2(xmlDef.Attribute("position")?.Value ?? "0,0");
|
2025-09-19 08:26:54 +08:00
|
|
|
|
FPS = float.TryParse(xmlDef.Attribute("FPS")?.Value, out var result) ? result : 5.0f;
|
2025-08-27 19:56:49 +08:00
|
|
|
|
return false;
|
2025-07-13 19:23:45 +08:00
|
|
|
|
}
|
2025-07-14 11:40:08 +08:00
|
|
|
|
|
2025-09-28 15:02:57 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取播放一遍动画所需的最小时间(取当前节点动画与所有子集动画的最大值)。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>播放一遍动画所需的最小时间(秒),如果无动画则为0。</returns>
|
|
|
|
|
|
public float GetMinAnimationDuration()
|
|
|
|
|
|
{
|
|
|
|
|
|
var maxDuration = 0f;
|
|
|
|
|
|
// 计算当前节点自身的动画时间
|
|
|
|
|
|
if (textures != null && textures.Length > 0)
|
2025-07-14 11:40:08 +08:00
|
|
|
|
{
|
2025-09-28 15:02:57 +08:00
|
|
|
|
// 只有当FPS大于0时,才计算有效的动画时间。
|
|
|
|
|
|
// 如果FPS <= 0,表示该部分动画无法播放,其时长贡献为0,不参与最大值计算。
|
|
|
|
|
|
if (FPS > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
maxDuration = Math.Max(maxDuration, textures.Length / FPS);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-07-14 11:40:08 +08:00
|
|
|
|
|
2025-09-28 15:02:57 +08:00
|
|
|
|
// 递归计算子节点的动画时间,并更新最大值
|
|
|
|
|
|
if (nodes != null && nodes.Length > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var node in nodes)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (node != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
maxDuration = Math.Max(maxDuration, node.GetMinAnimationDuration());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-07-14 11:40:08 +08:00
|
|
|
|
}
|
2025-08-27 19:56:49 +08:00
|
|
|
|
|
2025-09-28 15:02:57 +08:00
|
|
|
|
return maxDuration;
|
2025-07-14 11:40:08 +08:00
|
|
|
|
}
|
2025-07-13 19:23:45 +08:00
|
|
|
|
}
|
2025-07-14 15:00:56 +08:00
|
|
|
|
|
2025-07-13 19:23:45 +08:00
|
|
|
|
}
|