This commit is contained in:
2026-10-11 21:57:58 +08:00
parent d35c47deea
commit 0d53dc073d
14 changed files with 287300 additions and 275445 deletions
-152
View File
@@ -1,5 +1,4 @@
using Spine.Unity;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
@@ -324,157 +323,6 @@ public class TurretData : MonoBehaviour
_appearAnimHoldUntil = Time.time + hold;
}
// ==================== XJMH 入场动画(原版 PW_Battery:EnterAction,进入房间时本地座位播一次) ====================
[Header("XJMH入场动画(原版 EnterAction:飞机从下方升起 → 变回炮台)")]
[Tooltip("入场音效 id(原版 PW_Enter,tbaudio 60003);0=不播")]
public int enterAudioID = 60003;
[Tooltip("飞机回位音效 id(原版 PW_PlaneBack,tbaudio 61106);0=不播")]
public int enterBackAudioID = 61106;
[Tooltip("飞机入场起点相对停靠位的 Y 偏移(负值=从更下方升起,原版从画面下方飞入)")]
public float enterStartOffsetY = -260f;
[Tooltip("第一段升起时长(秒),原版 0.5")]
public float enterRiseTime = 0.5f;
[Tooltip("两段之间的停顿(秒),原版 0.3")]
public float enterHoldTime = 0.3f;
[Tooltip("第二段升到停靠位时长(秒),原版 0.5")]
public float enterBackRiseTime = 0.5f;
[Tooltip("飞机 \"back\" 动画开始后,飞机隐藏、炮台出现的延迟(秒),原版 1.0")]
public float enterBackHoldTime = 1f;
private Coroutine _enterRoutine;
private RectTransform _enterPlane; // 入场中的飞机节点(离场清理复位用)
private Vector2 _enterPlaneHome; // 飞机停靠位(预制体配好的 anchoredPosition)
/// <summary>
/// XJMH 入场动画(移植原版 Battery:EnterAction 的非立即分支,进入房间时由本地座位调用一次):
/// Enter 音效 → 飞机从停靠位下方升起 → 停顿 → 升到停靠位(PlaneBack 音效 + 飞机播 "back")
/// → 延迟后飞机隐藏、炮台本体出现并播 "out"(原版 ShowGun)。
/// 找不到飞机节点时只播炮台出现动画(兜底不报错)。
/// </summary>
public void PlayEnterAction()
{
if (!isActiveAndEnabled) return;
if (_enterRoutine != null) StopCoroutine(_enterRoutine);
_enterRoutine = StartCoroutine(EnterActionRoutine());
}
private IEnumerator EnterActionRoutine()
{
if (enterAudioID > 0 && AudioManager.Instance != null)
AudioManager.Instance.PlayerFX(enterAudioID);
_enterPlane = FindPlaneSkeletonRect();
if (_enterPlane == null)
{
PlayTurretOutAnim();
_enterRoutine = null;
yield break;
}
SkeletonGraphic planeSg = _enterPlane.GetComponent<SkeletonGraphic>();
_enterPlaneHome = _enterPlane.anchoredPosition;
Vector2 home = _enterPlaneHome;
Vector2 start = home + new Vector2(0f, enterStartOffsetY);
Vector2 mid = home + new Vector2(0f, enterStartOffsetY * 0.5f);
// 原版:入场时炮台本体隐藏、飞机出现(飞机从下方升上来,"变"回炮台)
if (skeletonAnimation != null)
skeletonAnimation.gameObject.SetActive(false);
_enterPlane.gameObject.SetActive(true);
_enterPlane.anchoredPosition = start;
if (planeSg != null && planeSg.AnimationState != null)
planeSg.AnimationState.ClearTrack(0); // 清残留(对象池/重复入场)
// 第一段:升到中途位(原版 EInQuart)
yield return RiseTo(_enterPlane, start, mid, enterRiseTime, true);
// 停顿(原版 delay 0.3)
if (enterHoldTime > 0f) yield return new WaitForSeconds(enterHoldTime);
// 第二段:升到停靠位(原版 EOutQuart)
yield return RiseTo(_enterPlane, mid, home, enterBackRiseTime, false);
// PlaneBack 音效 + 飞机回位动画(原版 PlaneBack → PlaneBackAnim)
if (enterBackAudioID > 0 && AudioManager.Instance != null)
AudioManager.Instance.PlayerFX(enterBackAudioID);
if (planeSg != null && planeSg.AnimationState != null)
planeSg.AnimationState.SetAnimation(0, "back", false);
// 原版:back 动画 1 秒后飞机隐藏、炮台出现(ShowGun)
if (enterBackHoldTime > 0f) yield return new WaitForSeconds(enterBackHoldTime);
_enterPlane.gameObject.SetActive(false);
_enterPlane.anchoredPosition = home;
PlayTurretOutAnim();
_enterPlane = null;
_enterRoutine = null;
}
/// <summary>协程位移:EInQuart / EOutQuart 缓动(与原版 GC.Action 一致)</summary>
private static IEnumerator RiseTo(RectTransform rt, Vector2 from, Vector2 to, float time, bool easeIn)
{
if (rt == null) yield break;
if (time <= 0f) { rt.anchoredPosition = to; yield break; }
float t = 0f;
while (t < time)
{
t += Time.deltaTime;
float p = Mathf.Clamp01(t / time);
float e = easeIn ? p * p * p * p : 1f - Mathf.Pow(1f - p, 4f);
rt.anchoredPosition = Vector2.LerpUnclamped(from, to, e);
yield return null;
}
rt.anchoredPosition = to;
}
/// <summary>炮台本体出现:恢复显示并播 startingAnimation(预制体配的 "out";为空时兜底 "out")</summary>
private void PlayTurretOutAnim()
{
if (skeletonAnimation == null) return;
skeletonAnimation.gameObject.SetActive(true);
if (skeletonAnimation.AnimationState == null) return;
string anim = string.IsNullOrEmpty(skeletonAnimation.startingAnimation) ? "out" : skeletonAnimation.startingAnimation;
skeletonAnimation.AnimationState.SetAnimation(0, anim, skeletonAnimation.startingLoop);
skeletonAnimation.Update(0.1f);
}
/// <summary>找飞机节点:名字含 "feiji" 的 SkeletonGraphic(四种炮台各配一架:lvptfeiji/lanptfeiji/huangjinfeiji/vipfeiji01)</summary>
private RectTransform FindPlaneSkeletonRect()
{
foreach (var sg in GetComponentsInChildren<SkeletonGraphic>(true))
{
if (sg == null) continue;
if (sg.gameObject.name.ToLowerInvariant().Contains("feiji"))
return sg.rectTransform;
}
return null;
}
/// <summary>
/// 入场动画清理:停协程 + 复位(飞机隐藏回停靠位、炮台本体恢复显示),禁用/回收不残留。
/// ⭐ protected(不直接放 private OnDisable 里):子类(如 FlyTurretData)自带 OnDisable 时,
/// Unity 只会调用最派生的 OnDisable、基类同名私有方法被跳过,
/// 子类需在自己的 OnDisable 里显式调用本方法,保证入场动画清理不被漏掉。
/// </summary>
protected void CleanupEnterAction()
{
if (_enterRoutine != null) { StopCoroutine(_enterRoutine); _enterRoutine = null; }
if (_enterPlane != null)
{
_enterPlane.anchoredPosition = _enterPlaneHome;
_enterPlane.gameObject.SetActive(false);
_enterPlane = null;
}
if (skeletonAnimation != null && !skeletonAnimation.gameObject.activeSelf)
skeletonAnimation.gameObject.SetActive(true);
}
private void OnDisable()
{
CleanupEnterAction();
}
private void PlayState(TurretState state)
{
switch (currTurretType)