1
This commit is contained in:
@@ -126,6 +126,14 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
[Tooltip("当前装备的炮台编号")]
|
||||
public int currentTurretNumber;
|
||||
|
||||
/// <summary>
|
||||
/// 当前 XJMH 炮台在 <see cref="xjmhTurretList"/> 中的索引(-1=未初始化)。
|
||||
/// ⭐ XJMH 四把炮台的 turretNumber 全是 0(不对接后端、没有编号),
|
||||
/// 炮台身份只能用列表索引表示:切换按钮、帧同步广播/接收统一都用索引。
|
||||
/// </summary>
|
||||
[System.NonSerialized]
|
||||
public int currentTurretIndex = -1;
|
||||
|
||||
/// <summary>当前运行中的炮台实例</summary>
|
||||
public TurretData currentTurret;
|
||||
|
||||
@@ -268,8 +276,8 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
if (turretControlMode == TurretControlMode.XJMH && tMP_DiamondNum != null)
|
||||
tMP_DiamondNum.gameObject.SetActive(false);
|
||||
|
||||
// XJMH 模式:炮台是座位自带子对象,预制体里已摆好,不需要加载。
|
||||
// 这里只做引用初始化,不做激活/停用。
|
||||
// XJMH 模式:炮台是座位自带子对象,不需要从资源加载,只做初始化
|
||||
// (整理炮台列表 + 激活默认炮台 = 列表索引 0)
|
||||
if (turretControlMode == TurretControlMode.XJMH)
|
||||
InitXJMHTurret();
|
||||
}
|
||||
@@ -322,9 +330,8 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// XJMH 模式:炮台是座位自带子对象,预制体里已摆好激活状态,不需要 LoadTurret 加载。
|
||||
/// 此方法只做引用初始化:从 <see cref="xjmhTurretList"/> 取第一个激活的炮台赋给 currentTurret,
|
||||
/// 并绑定旋转节点、状态机入口、世界坐标缓存。不做任何激活/停用操作。
|
||||
/// XJMH 模式:炮台是座位自带子对象,预制体里已摆好,不需要 LoadTurret 加载。
|
||||
/// ⭐ 默认炮台 = 排序后索引 0 的那把(对应座位 GetChild(0) 的绿炮台)。
|
||||
/// </summary>
|
||||
private void InitXJMHTurret()
|
||||
{
|
||||
@@ -334,33 +341,92 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
return;
|
||||
}
|
||||
|
||||
// 优先取列表中第一个激活的炮台;若全部未激活,取 list[0]
|
||||
TurretData found = null;
|
||||
foreach (var td in xjmhTurretList)
|
||||
NormalizeXJMHTurretList();
|
||||
ApplyXJMHTurret(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 整理 XJMH 炮台列表:剔除空引用,并按座位下的兄弟顺序排序。
|
||||
/// ⭐ 排序原因:切换面板的 4 个按钮固定是 绿/蓝/金/VIP(索引 0~3),
|
||||
/// 而座位里这四把炮台的兄弟顺序正好就是 绿/蓝/金/VIP。
|
||||
/// 不排序的话,Inspector 里拖拽的先后顺序会让按钮和炮台对不上。
|
||||
/// </summary>
|
||||
private void NormalizeXJMHTurretList()
|
||||
{
|
||||
xjmhTurretList.RemoveAll(t => t == null);
|
||||
xjmhTurretList.Sort((a, b) =>
|
||||
a.transform.GetSiblingIndex().CompareTo(b.transform.GetSiblingIndex()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// XJMH:按列表索引激活炮台(只激活目标那把,其余全部停用)。
|
||||
/// ⭐ 不能再用 turretNumber 匹配:XJMH 四把炮台的 turretNumber 全是 0,
|
||||
/// 按编号匹配会把四把一次全激活,且切换到"同编号"的炮台会被判成无需切换(点按钮没反应)。
|
||||
/// </summary>
|
||||
private void ApplyXJMHTurret(int index)
|
||||
{
|
||||
if (xjmhTurretList == null || index < 0 || index >= xjmhTurretList.Count) return;
|
||||
|
||||
TurretData target = xjmhTurretList[index];
|
||||
if (target == null) return;
|
||||
|
||||
for (int i = 0; i < xjmhTurretList.Count; i++)
|
||||
{
|
||||
if (td == null) continue;
|
||||
if (td.gameObject.activeSelf)
|
||||
{
|
||||
found = td;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == null)
|
||||
{
|
||||
found = xjmhTurretList[0];
|
||||
found.gameObject.SetActive(true);
|
||||
var td = xjmhTurretList[i];
|
||||
if (td != null)
|
||||
td.gameObject.SetActive(i == index);
|
||||
}
|
||||
|
||||
currentTurret = found;
|
||||
currentTurretNumber = found.turretNumber;
|
||||
|
||||
// 缓存旋转节点:优先用 TurretData.tra_RotationPivot,否则回退父节点
|
||||
tra_CurrTurret = GetTurretRotationPivot(currentTurret);
|
||||
|
||||
OnStateChange = currentTurret.ChangeState;
|
||||
currentTurretIndex = index;
|
||||
currentTurret = target;
|
||||
currentTurretNumber = target.turretNumber; // XJMH 下恒为 0,仅保持字段同步
|
||||
tra_CurrTurret = GetTurretRotationPivot(target);
|
||||
EnsureXJMHTurretMuzzle(target, tra_CurrTurret);
|
||||
EnsureXJMHTurretAnim(target, tra_CurrTurret);
|
||||
OnStateChange = target.ChangeState;
|
||||
UpdateTurretWorldPos();
|
||||
target.PlayAppearAnim(); // 出现动画(各 SkeletonGraphic 的 Spine startingAnimation)
|
||||
|
||||
Debug.Log($"[SitPosData] XJMH 炮台引用已初始化: #{currentTurretNumber}");
|
||||
Debug.Log($"[SitPosData] XJMH 炮台已切换: 索引{index} ({target.name})");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// XJMH:修正子弹发射点。
|
||||
/// ⭐ 预制体里绿/蓝/金三把炮台的 tra_BulletStartPosition 指到了"炮体美术节点"
|
||||
/// (它的 pivot 在炮体盒子底部,相对旋转中心是 -29.8,等于旋转中心后方),子弹会从炮台后面出来。
|
||||
/// 真正的炮口是旋转节点下那个空节点 Bullit(相对旋转中心 +50,正前方)——VIP 就是这么配的。
|
||||
/// ⭐ 只在当前指向的是「带 Graphic 的美术节点」时才修正:自己拖进来的炮口标记节点(无 Graphic)不动。
|
||||
/// </summary>
|
||||
private static void EnsureXJMHTurretMuzzle(TurretData turret, Transform pivot)
|
||||
{
|
||||
if (pivot == null) return;
|
||||
|
||||
// 当前指向的节点没有 Graphic(是炮口标记节点)→ 说明是手动配好的,不动
|
||||
if (turret.tra_BulletStartPosition != null
|
||||
&& turret.tra_BulletStartPosition.GetComponent<Graphic>() == null) return;
|
||||
|
||||
Transform muzzle = pivot.Find("Bullit");
|
||||
if (muzzle == null) return;
|
||||
|
||||
Debug.LogWarning($"[SitPosData] XJMH 炮台 {turret.name} 的 tra_BulletStartPosition 指向了美术节点,已自动改用炮口节点 Bullit");
|
||||
turret.tra_BulletStartPosition = muzzle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// XJMH:补上炮台动画组件。
|
||||
/// ⭐ 预制体里绿/蓝/金三把炮台的 TurretData.skeletonAnimation 都是空的(只有 VIP 拖了),
|
||||
/// 而 TurretData.PlaySkeleton 遇到 null 会直接 return → 这三把炮台动画完全不播。
|
||||
/// 这里按 VIP 的同一套结构自动补:旋转节点(炮台本体组)下面那个 SkeletonGraphic 就是炮体动画,
|
||||
/// VIP 的 skeletonAnimation 指的正是它。Inspector 里已经拖了的不会被覆盖。
|
||||
/// </summary>
|
||||
private static void EnsureXJMHTurretAnim(TurretData turret, Transform pivot)
|
||||
{
|
||||
if (turret.skeletonAnimation != null || pivot == null) return;
|
||||
|
||||
turret.skeletonAnimation = pivot.GetComponentInChildren<SkeletonGraphic>(true);
|
||||
Debug.LogWarning(turret.skeletonAnimation != null
|
||||
? $"[SitPosData] XJMH 炮台 {turret.name} 的 TurretData.skeletonAnimation 未配置,已自动取旋转节点下的 {turret.skeletonAnimation.name}"
|
||||
: $"[SitPosData] XJMH 炮台 {turret.name} 的 TurretData.skeletonAnimation 未配置,且旋转节点下没找到 SkeletonGraphic,动画不会播放");
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
@@ -407,18 +473,34 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
|
||||
// ==================== 长按 img_OpenPT(打开炮台面板) ====================
|
||||
|
||||
/// <summary>按下:命中 img_OpenPT(或其子对象)才开始长按计时(其他区域不响应)</summary>
|
||||
/// <summary>按下:按点落在 img_OpenPT 的屏幕矩形内才开始长按计时(其他区域不响应)</summary>
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
if (img_OpenPT == null) return;
|
||||
var hit = eventData.pointerCurrentRaycast.gameObject;
|
||||
if (hit == null) return;
|
||||
if (hit != img_OpenPT.gameObject && !hit.transform.IsChildOf(img_OpenPT.transform)) return;
|
||||
if (!IsPointerOnOpenPT(eventData.position)) return;
|
||||
|
||||
_openPTPressing = true;
|
||||
_openPTPressTimer = 0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按点是否落在 img_OpenPT 的屏幕矩形内。
|
||||
/// ⭐ 用坐标矩形判定,而不是比较射线命中的对象:座位下还挂着昵称/表情/炮台等一堆兄弟 UI,
|
||||
/// 实际被射线命中的往往是它们而不是 img_OpenPT,但它们同属座位层级,
|
||||
/// 按下事件照样会冒泡到本组件,所以只有按坐标判定才可靠。
|
||||
/// </summary>
|
||||
private bool IsPointerOnOpenPT(Vector2 screenPos)
|
||||
{
|
||||
if (img_OpenPT == null) return false;
|
||||
RectTransform rect = img_OpenPT.rectTransform;
|
||||
if (rect == null) return false;
|
||||
|
||||
Canvas canvas = rect.GetComponentInParent<Canvas>();
|
||||
Camera cam = canvas != null && canvas.renderMode != RenderMode.ScreenSpaceOverlay
|
||||
? canvas.worldCamera
|
||||
: null;
|
||||
return RectTransformUtility.RectangleContainsScreenPoint(rect, screenPos, cam);
|
||||
}
|
||||
|
||||
/// <summary>松开:取消长按计时(未达阈值不触发)</summary>
|
||||
public void OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
@@ -989,13 +1071,18 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
|
||||
/// <summary>
|
||||
/// 玩家加入 → 显示玩家 UI(child0),隐藏等待界面(child1)。
|
||||
/// ⭐ XJMH 座位没有"玩家界面/等待界面"这一对子节点(child0~3 是四把炮台),
|
||||
/// 不能在这里动子对象显隐,否则会把炮台当等待界面切来切去,和切换炮台的激活状态互相打架。
|
||||
/// </summary>
|
||||
public void ShowPlayer()
|
||||
{
|
||||
if (transform.childCount > 0)
|
||||
transform.GetChild(0).gameObject.SetActive(true);
|
||||
if (transform.childCount > 1)
|
||||
transform.GetChild(1).gameObject.SetActive(false);
|
||||
if (turretControlMode != TurretControlMode.XJMH)
|
||||
{
|
||||
if (transform.childCount > 0)
|
||||
transform.GetChild(0).gameObject.SetActive(true);
|
||||
if (transform.childCount > 1)
|
||||
transform.GetChild(1).gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
// 如果是本地玩家的座位,自动注册并加载装备
|
||||
if (user == GameManager.Instance?.user?.id)
|
||||
@@ -1026,9 +1113,12 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
|
||||
/// <summary>
|
||||
/// 玩家退出/等待 → 显示等待界面(child1),隐藏玩家 UI(child0)。
|
||||
/// ⭐ XJMH 座位没有这一对子节点(child0~3 是四把炮台),跳过(原因见 ShowPlayer)。
|
||||
/// </summary>
|
||||
public void ShowWaiting()
|
||||
{
|
||||
if (turretControlMode == TurretControlMode.XJMH) return;
|
||||
|
||||
if (transform.childCount > 0)
|
||||
transform.GetChild(0).gameObject.SetActive(false);
|
||||
if (transform.childCount > 1)
|
||||
@@ -1218,7 +1308,8 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
/// <summary>
|
||||
/// 获取炮台的旋转节点。
|
||||
/// - 若 TurretData.tra_RotationPivot 已赋值 → 用它(精确指定旋转中心)
|
||||
/// - 否则回退旧逻辑:炮台父节点(Normal 克隆的中间容器 / XJMH 子对象的父节点)
|
||||
/// - XJMH:自动取"容器里那个炮台本体节点"(见 <see cref="FindXJMHRotationPivot"/>)
|
||||
/// - Normal:回退旧逻辑,用炮台父节点(克隆用的中间容器)
|
||||
/// </summary>
|
||||
private Transform GetTurretRotationPivot(TurretData turret)
|
||||
{
|
||||
@@ -1237,21 +1328,51 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
if (turret.tra_RotationPivot != null)
|
||||
return turret.tra_RotationPivot;
|
||||
|
||||
// 回退:用父节点(兼容旧逻辑)
|
||||
// ⭐ XJMH:炮台是"容器"(绿=SkeletonGraphic_Green),容器里除了炮台本体,
|
||||
// 还挂着加减倍按钮(Up)、飞机(lvptfeiji)等其他子节点。
|
||||
// 转容器本身会把它们一起甩着转;转父节点又等于转整个座位(座位就是 XJMH 炮台的父节点)。
|
||||
// 真正该转的是容器里那个炮台本体节点 → 自动找。
|
||||
if (turretControlMode == TurretControlMode.XJMH)
|
||||
{
|
||||
Transform pivot = FindXJMHRotationPivot(turret);
|
||||
return pivot != null ? pivot : turret.transform;
|
||||
}
|
||||
|
||||
// 回退:用父节点(兼容普通模式旧逻辑)
|
||||
Transform parent = turret.transform.parent;
|
||||
return parent != null ? parent : turret.transform;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// XJMH 炮台的旋转节点 = 炮口所在的、炮台的直接子节点。
|
||||
/// ⭐ 从炮口 <see cref="TurretData.tra_BulletStartPosition"/> 往上走,取"炮台的直接子节点":
|
||||
/// 炮台容器(SkeletonGraphic_Green / huangjinpaotai_1 / SkeletonGraphic_VIP)
|
||||
/// └─ 炮台本体 ← 要转的就是它(lvptpaotai_2 / huangjinpaotai_2 / vippaotai01_2)
|
||||
/// └─ …炮口 tra_BulletStartPosition…
|
||||
/// 已核对预制体:三种炮台都符合,且与 VIP 上手动填的 TurretData.tra_RotationPivot 完全一致。
|
||||
/// </summary>
|
||||
private static Transform FindXJMHRotationPivot(TurretData turret)
|
||||
{
|
||||
Transform muzzle = turret.tra_BulletStartPosition;
|
||||
if (muzzle == null) return null;
|
||||
|
||||
Transform node = muzzle;
|
||||
while (node.parent != null && node.parent != turret.transform)
|
||||
node = node.parent;
|
||||
|
||||
return node.parent == turret.transform ? node : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据炮台编号加载炮台。
|
||||
/// Normal 模式:从 Addressables 加载预制体并克隆到 turretParent。
|
||||
/// XJMH 模式:炮台是座位子对象,激活对应编号子对象、停用其他。
|
||||
/// XJMH 模式:炮台是座位自带子对象,传入值按 <see cref="xjmhTurretList"/> 索引解释(XJMH 炮台没有编号)。
|
||||
/// </summary>
|
||||
public void LoadTurret(int turretNumber)
|
||||
{
|
||||
if (turretControlMode == TurretControlMode.XJMH)
|
||||
{
|
||||
SwitchTurretChild(turretNumber);
|
||||
SwitchTurretByIndex(turretNumber);
|
||||
return;
|
||||
}
|
||||
LoadTurretNormal(turretNumber);
|
||||
@@ -1324,104 +1445,25 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// XJMH 模式:炮台都是座位的子对象,激活对应编号的炮台、停用其他。
|
||||
/// 不需要 Instantiate/Destroy,只做激活/停用,无需额外处理。
|
||||
/// 优先从 <see cref="xjmhTurretList"/> 查找,列表为空时回退遍历子对象。
|
||||
/// XJMH 模式:按列表索引切换炮台。
|
||||
/// ⭐ 切换面板的 4 个按钮、帧同步接收端都走这里(XJMH 炮台没有编号,只能用索引)。
|
||||
/// </summary>
|
||||
private void SwitchTurretChild(int turretNumber)
|
||||
{
|
||||
BulletPool.Instance.ClearActive();
|
||||
|
||||
// 炮台挂载根:turretParent 优先,否则用座位自身
|
||||
Transform parent = turretParent != null ? turretParent : transform;
|
||||
|
||||
// 优先用 Inspector 配置的炮台列表
|
||||
TurretData found = null;
|
||||
if (xjmhTurretList != null && xjmhTurretList.Count > 0)
|
||||
{
|
||||
foreach (var td in xjmhTurretList)
|
||||
{
|
||||
if (td == null) continue;
|
||||
bool active = td.turretNumber == turretNumber;
|
||||
td.gameObject.SetActive(active);
|
||||
if (active) found = td;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 回退:列表未配置时遍历子对象
|
||||
for (int i = 0; i < parent.childCount; i++)
|
||||
{
|
||||
var child = parent.GetChild(i);
|
||||
var td = child.GetComponent<TurretData>();
|
||||
if (td == null) continue;
|
||||
|
||||
if (td.turretNumber == turretNumber)
|
||||
{
|
||||
child.gameObject.SetActive(true);
|
||||
found = td;
|
||||
}
|
||||
else
|
||||
{
|
||||
child.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found == null)
|
||||
{
|
||||
Debug.LogWarning($"[SitPosData] XJMH 子对象中未找到炮台 #{turretNumber}");
|
||||
return;
|
||||
}
|
||||
|
||||
currentTurretNumber = turretNumber;
|
||||
currentTurret = found;
|
||||
// 缓存旋转节点:优先用 TurretData.tra_RotationPivot,否则回退父节点
|
||||
tra_CurrTurret = GetTurretRotationPivot(currentTurret);
|
||||
|
||||
OnStateChange = currentTurret.ChangeState;
|
||||
UpdateTurretWorldPos();
|
||||
|
||||
Debug.Log($"[SitPosData] 炮台已切换(XJMH): #{turretNumber}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// XJMH 模式:按列表索引直接切换炮台。
|
||||
/// 用于扇形切换 UI 中按位置选择炮台,避免再做编号匹配。
|
||||
/// </summary>
|
||||
/// <param name="index">xjmhTurretList 中的索引</param>
|
||||
/// <param name="index"><see cref="xjmhTurretList"/> 中的索引</param>
|
||||
/// <returns>切换成功返回 true;索引越界或列表为空返回 false</returns>
|
||||
public bool SwitchTurretByIndex(int index)
|
||||
{
|
||||
if (turretControlMode != TurretControlMode.XJMH) return false;
|
||||
if (xjmhTurretList == null || index < 0 || index >= xjmhTurretList.Count) return false;
|
||||
if (xjmhTurretList[index] == null) return false;
|
||||
|
||||
var td = xjmhTurretList[index];
|
||||
if (td == null) return false;
|
||||
// 已经是这把 → 不重复切换(避免无谓清屏子弹);currentTurret 为空时仍需重新应用一次
|
||||
if (index == currentTurretIndex && currentTurret != null) return true;
|
||||
|
||||
// 命中当前炮台则无需切换
|
||||
if (td.turretNumber == currentTurretNumber) return true;
|
||||
|
||||
SwitchTurretChild(td.turretNumber);
|
||||
BulletPool.Instance.ClearActive();
|
||||
ApplyXJMHTurret(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// XJMH 模式:根据当前炮台在 xjmhTurretList 中的索引返回下一个炮台编号。
|
||||
/// 用于"切换到下一把"的快捷操作。循环切换,列表为空返回 -1。
|
||||
/// </summary>
|
||||
public int GetNextTurretNumber()
|
||||
{
|
||||
if (turretControlMode != TurretControlMode.XJMH) return -1;
|
||||
if (xjmhTurretList == null || xjmhTurretList.Count == 0) return -1;
|
||||
|
||||
int currIdx = xjmhTurretList.FindIndex(td => td != null && td.turretNumber == currentTurretNumber);
|
||||
if (currIdx < 0) return xjmhTurretList[0].turretNumber;
|
||||
|
||||
int nextIdx = (currIdx + 1) % xjmhTurretList.Count;
|
||||
return xjmhTurretList[nextIdx].turretNumber;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前可用的炮台编号列表。
|
||||
/// Normal 模式:从资源表按类型查询。
|
||||
@@ -1823,7 +1865,7 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
}
|
||||
else
|
||||
{
|
||||
// 兜底:列表未配置时扫 turretParent 子对象(与 SwitchTurretChild 回退一致)
|
||||
// 兜底:列表未配置时扫 turretParent 子对象
|
||||
Transform parent = turretParent != null ? turretParent : transform;
|
||||
for (int i = 0; i < parent.childCount; i++)
|
||||
HideTurretAddDown(parent.GetChild(i).GetComponent<TurretData>());
|
||||
|
||||
@@ -114,6 +114,9 @@ public class TurretData : MonoBehaviour
|
||||
|
||||
private TurretState currState;
|
||||
|
||||
/// <summary>出现动画保护截止时间:这段时间内 Idle(动画名为空)不 ClearTrack,避免出现动画刚播就被抹掉</summary>
|
||||
private float _appearAnimHoldUntil;
|
||||
|
||||
/// <summary>
|
||||
/// 从资源表查询 TurretResourcesData。表里没有则返回 null,调用方应使用 TurretData 自身的 Inspector 默认值。
|
||||
/// </summary>
|
||||
@@ -256,6 +259,26 @@ public class TurretData : MonoBehaviour
|
||||
PlayState(newState);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 播放"出现动画":各 SkeletonGraphic 上配置的 Spine startingAnimation(炮台容器/炮体上配的是 out、trans 等)。
|
||||
/// ⭐ Spine 只在 Awake(第一次激活)应用一次 startingAnimation,而 OnEnable 的 PlayState(Idle)
|
||||
/// 在动画名为空时会 ClearTrack 把它抹掉,所以切换炮台时补播一次,
|
||||
/// 并在播放期间保护它不被 Idle 清掉(见 PlaySkeleton 的空动画名分支)。
|
||||
/// </summary>
|
||||
public void PlayAppearAnim()
|
||||
{
|
||||
float hold = 0f;
|
||||
foreach (var g in GetComponentsInChildren<SkeletonGraphic>(true))
|
||||
{
|
||||
if (g == null || string.IsNullOrEmpty(g.startingAnimation) || g.AnimationState == null) continue;
|
||||
|
||||
var track = g.AnimationState.SetAnimation(0, g.startingAnimation, g.startingLoop);
|
||||
if (!g.startingLoop && track != null)
|
||||
hold = Mathf.Max(hold, track.Animation.Duration);
|
||||
}
|
||||
_appearAnimHoldUntil = Time.time + hold;
|
||||
}
|
||||
|
||||
private void PlayState(TurretState state)
|
||||
{
|
||||
switch (currTurretType)
|
||||
@@ -347,6 +370,11 @@ public class TurretData : MonoBehaviour
|
||||
// 如果动画名为空 → 停止当前动画(暂停),不再播放任何动画
|
||||
if (string.IsNullOrEmpty(anim))
|
||||
{
|
||||
// ⭐ 出现动画播放期间不覆盖:ClearTrack 会把刚播的出现动画抹掉。
|
||||
// 典型场景:切炮台后松手,HandleInput 会发一次 ChangeState(Idle),
|
||||
// 而 idleAnim 为空正好走这个分支,出现动画一帧就被清掉。
|
||||
if (Time.time < _appearAnimHoldUntil) return;
|
||||
|
||||
skeletonAnimation.AnimationState.ClearTrack(0);
|
||||
skeletonAnimation.AnimationState.SetEmptyAnimation(0, 0f);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user