1
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Spine.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
@@ -277,10 +279,178 @@ public class FlyTurretData : TurretData
|
||||
base.ChangeState(newState);
|
||||
}
|
||||
|
||||
// ==================== XJMH 进房入场动画(原版 Battery:EnterAction,进入房间时本地座位播一次) ====================
|
||||
// 原版链路(PW_Data.InitPlayer 收到自己"大飞机信息"):
|
||||
// GC.BatteryMgr.PlayEnterAction(chairId, PW_Data.EnterAction) —— 首次 false 播完整动画+声音,
|
||||
// 之后 true 只立即摆好。完整流程:
|
||||
// Enter 音效 → 容器(底座)Spine 播 "out" → 炮台本体隐藏、飞机出现 →
|
||||
// 飞机从下方两段升起(EInQuart 0.5s → 停 0.3s → EOutQuart 0.5s)→
|
||||
// PlaneBack 音效 + 飞机播 "back" → 约 1 秒后飞机隐藏、炮台本体播 "out" 出现。
|
||||
|
||||
[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 音效 → 容器 "out" → 飞机从停靠位下方两段升起(PlaneBack 音效 + "back")→
|
||||
/// 延迟后飞机隐藏、炮台本体播 "out" 出现。
|
||||
/// ⭐ 未激活(面板加载中/座位隐藏)时直接返回——SitPosData 会挂起并在激活后补播。
|
||||
/// 找不到飞机节点时只播炮台出现动画(兜底不报错)。
|
||||
/// </summary>
|
||||
public void PlayEnterAction()
|
||||
{
|
||||
if (!isActiveAndEnabled) return;
|
||||
Debug.Log($"[XJMH入场] {name} 开始播放(Enter音效={enterAudioID} 回位音效={enterBackAudioID})");
|
||||
|
||||
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)
|
||||
{
|
||||
Debug.LogWarning($"[XJMH入场] {name} 未找到飞机节点(名字含 feiji),只播炮台出现动画");
|
||||
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);
|
||||
|
||||
// ⭐ 原版 EnterAction 第 6 步:底部(容器/底座外壳)Spine 播 "out" 出场
|
||||
// (PW_Battery.txt:EnterAction → bottomSkeleton.AnimationState:SetAnimation(0,"out",false))
|
||||
PlayContainerOutAnim();
|
||||
|
||||
// 原版:入场时炮台本体隐藏、飞机出现(飞机从下方升上来,"变"回炮台)
|
||||
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>
|
||||
/// 容器(底座/炮台外壳)出场动画:XJMH 炮台容器自身的 Spine 播 "out"(容器动画为 close/open/out)。
|
||||
/// 对应原版 EnterAction 第 6 步 bottomSkeleton "out";容器上没有该动画时跳过、不报错。
|
||||
/// </summary>
|
||||
private void PlayContainerOutAnim()
|
||||
{
|
||||
var shell = GetComponent<SkeletonGraphic>();
|
||||
if (shell == null || shell.AnimationState == null) return;
|
||||
if (shell.Skeleton != null && shell.Skeleton.Data != null
|
||||
&& shell.Skeleton.Data.FindAnimation("out") == null) return; // 没有 out 动画:跳过
|
||||
shell.AnimationState.SetAnimation(0, "out", false);
|
||||
shell.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>入场动画清理:停协程 + 复位(飞机隐藏回停靠位、炮台本体恢复显示),禁用/回收不残留</summary>
|
||||
private 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()
|
||||
{
|
||||
// ⭐ 基类入场动画清理:子类 OnDisable 会覆盖基类的私有 OnDisable(Unity 只调最派生),
|
||||
// 必须显式调用,保证"飞机升起/炮台出场"的清理不被漏掉(在提前 return 之前调用)
|
||||
// ⭐ 入场动画清理(停协程、飞机复位隐藏、炮台本体恢复显示):必须在提前 return 之前调用
|
||||
CleanupEnterAction();
|
||||
|
||||
// 切炮台/座位被禁用时兜底复位
|
||||
|
||||
@@ -456,6 +456,7 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
{
|
||||
// 入场动画标记复位:座位再次激活(重进房/重新入座)时重新播
|
||||
_xjmhEnterPlayed = false;
|
||||
_xjmhEnterPending = false;
|
||||
|
||||
if (localPlayerSit == this)
|
||||
localPlayerSit = null;
|
||||
@@ -476,6 +477,8 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
|
||||
private void Update()
|
||||
{
|
||||
UpdateXJMHEnterPending(); // ⭐ XJMH 入场动画挂起补播(面板/炮台就绪即播,避免加载期播了看不到)
|
||||
|
||||
UpdateZhanShenLaser();
|
||||
|
||||
// ⭐ 长按 img_OpenPT 计时:到达阈值触发一次(提前松手不触发)
|
||||
@@ -1148,21 +1151,65 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
|
||||
/// <summary>XJMH 本地座位进房入场动画是否已播(本次激活周期只播一次;OnDisable 复位)</summary>
|
||||
private bool _xjmhEnterPlayed;
|
||||
/// <summary>已到入座时机但炮台/面板尚未激活(播了看不到)→ 挂起,等激活后 Update 补播</summary>
|
||||
private bool _xjmhEnterPending;
|
||||
|
||||
/// <summary>
|
||||
/// XJMH 本地座位进房入场动画(原版 Battery:EnterAction 非立即分支):
|
||||
/// 本次激活周期只播一次,防 ShowPlayer 被重复调用时重播。
|
||||
/// XJMH 本地座位进房入场动画(原版 PW_Data.InitPlayer → BatteryMgr.PlayEnterAction,首次播完整动画+声音):
|
||||
/// 入座时调用一次;面板/炮台未激活时挂起(此时播玩家看不到、协程也起不来)→ Update 补播。
|
||||
/// </summary>
|
||||
private void PlayXJMHEnterActionOnce()
|
||||
{
|
||||
if (_xjmhEnterPlayed) return;
|
||||
_xjmhEnterPlayed = true;
|
||||
if (_xjmhEnterPlayed || _xjmhEnterPending) return;
|
||||
|
||||
var turret = currentTurret;
|
||||
if (turret == null && xjmhTurretList != null && xjmhTurretList.Count > 0)
|
||||
turret = xjmhTurretList[0];
|
||||
if (turret != null)
|
||||
turret.PlayEnterAction();
|
||||
|
||||
// 炮台当前不可播(面板加载中/炮台未激活):挂起等就绪
|
||||
if (turret == null || !turret.isActiveAndEnabled)
|
||||
{
|
||||
_xjmhEnterPending = true;
|
||||
Debug.Log($"[XJMH入场] 座位 {name} 挂起(炮台未就绪:turret={(turret == null ? "null" : turret.name)})");
|
||||
return;
|
||||
}
|
||||
|
||||
_xjmhEnterPlayed = true;
|
||||
Debug.Log($"[XJMH入场] 座位 {name} 触发播放(炮台={turret.name})");
|
||||
if (turret is FlyTurretData flyTurret)
|
||||
flyTurret.PlayEnterAction();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// XJMH 入场动画触发/补播检查(Update 每帧):
|
||||
/// ① 兜底触发:本地座位已入座(user=本地)且从未触发过 → 走一次触发(覆盖 ShowPlayer 路径未走到的情况);
|
||||
/// ② 挂起补播:已触发但炮台/面板当时未激活 → 就绪(玩家可见)立即播。
|
||||
/// </summary>
|
||||
private void UpdateXJMHEnterPending()
|
||||
{
|
||||
// ⭐ 加载到 100% 前不触发/不补播(玩家看不到、位置未就绪):等加载完成后 Update 自然触发
|
||||
var panel = CreateFishManager.Instance?.currGameType as GameMainPanel_FishBase;
|
||||
if (panel == null || !panel.IsGameLoadCompleted) return;
|
||||
|
||||
// ① 兜底触发(Update 只在座位/面板激活时执行 → 触发时玩家已可见)
|
||||
if (turretControlMode == TurretControlMode.XJMH
|
||||
&& !_xjmhEnterPlayed && !_xjmhEnterPending
|
||||
&& !string.IsNullOrEmpty(user) && user == GameManager.Instance?.user?.id)
|
||||
{
|
||||
PlayXJMHEnterActionOnce();
|
||||
}
|
||||
|
||||
// ② 挂起补播
|
||||
if (!_xjmhEnterPending || _xjmhEnterPlayed) return;
|
||||
|
||||
var turret = currentTurret;
|
||||
if (turret == null || !turret.isActiveAndEnabled) return;
|
||||
|
||||
_xjmhEnterPending = false;
|
||||
_xjmhEnterPlayed = true;
|
||||
Debug.Log($"[XJMH入场] 座位 {name} 补播(炮台={turret.name})");
|
||||
if (turret is FlyTurretData flyTurret)
|
||||
flyTurret.PlayEnterAction();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1175,6 +1222,9 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
if (toggle_AutoAttack != null)
|
||||
toggle_AutoAttack.gameObject.SetActive(false);
|
||||
|
||||
// ⭐ 离座取消入场挂起(重进房时重新播放)
|
||||
_xjmhEnterPending = false;
|
||||
|
||||
if (turretControlMode == TurretControlMode.XJMH) return;
|
||||
|
||||
if (transform.childCount > 0)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -319,6 +319,13 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
public ProgressBar JinDuTiao;
|
||||
#region UI
|
||||
bool isfirstShow = true;
|
||||
|
||||
/// <summary>加载到 100% 是否已完成(进房初始化/入场动画等需在加载完成后执行:玩家可见、位置就绪)</summary>
|
||||
public bool IsGameLoadCompleted { get; private set; }
|
||||
/// <summary>进房"首个初始化"(座位/房间信息)已挂起、等加载到 100% 后执行</summary>
|
||||
private bool _pendingFirstShowInit;
|
||||
/// <summary>挂起时保存的进房通知(ApplyFirstShowInit 里写入 gameData.roomJoinNotice)</summary>
|
||||
private RoomJoinNotice _pendingRoomJoinNotice;
|
||||
protected override void OnShow(object args = null)
|
||||
{
|
||||
base.OnShow(args);
|
||||
@@ -358,61 +365,10 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
}
|
||||
if (isfirstShow)
|
||||
{
|
||||
string roomId = GameManager.Instance.gameData.currRoomData.roomId;
|
||||
//string roomId = GameManager.Instance.gameData.currRoomData;
|
||||
|
||||
|
||||
foreach (var item in GameManager.Instance.gameData.currRoomData.players)
|
||||
{
|
||||
JoinGame(item.position, item.gold, item.diamond, item.cannonMultiple, 0, item.userId, item.cannonId, item.wingsId, item.warGodId);
|
||||
// ⭐ 优先用后端 isBot 字段,兼容 userId.StartsWith("bot_")
|
||||
var sit = list_Sits.Find(s => s.posID == item.position);
|
||||
if (sit != null)
|
||||
{
|
||||
bool isBot = item.isBot ||
|
||||
(!string.IsNullOrEmpty(item.userId) && item.userId.StartsWith("bot_"));
|
||||
if (isBot) sit.isBot = true;
|
||||
}
|
||||
}
|
||||
GameManager.Instance.gameData.roomJoinNotice = v.arguments[0];
|
||||
isfirstShow = false;
|
||||
|
||||
foreach (var item in list_Sits)
|
||||
{
|
||||
// ⭐ 座位镜像:本地玩家的显示座位 = 服务端座位转显示空间(上方座位翻转后落回下方)
|
||||
if (item.posID == SeatMirror.ToDisplay(roomJoinNotice.Position))
|
||||
{
|
||||
currSitData = item;
|
||||
// ⭐ 长按本地座位的 img_OpenPT 开关炮台面板(与 btn_ChangeTurret 同逻辑)
|
||||
HookOpenPTLongPress(currSitData);
|
||||
// ⭐ 本地座位自动攻击关闭时广播 Idle 状态给其他客户端
|
||||
HookAutoAttackOff(currSitData);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ⭐ 非本地座位隐藏加减炮倍:Normal 藏座位按钮(未拖引用为 null 跳过),
|
||||
// XJMH 藏炮台上的加减倍(TurretData.obj_Add / obj_Down)
|
||||
item.HideTurretAddMinusUI();
|
||||
// ⭐ 自动攻击开关与加减倍按钮一样:非本地座位隐藏
|
||||
if (item.toggle_AutoAttack != null)
|
||||
item.toggle_AutoAttack.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
}
|
||||
//// currSitData.ChangeTurret(1); — 已由 SitPosData.OnEnable 自动加载
|
||||
if (currSitData.currentTurret != null)
|
||||
SyncChangeTurret(currSitData.currentTurret.turretNumber);
|
||||
currSitData.lockFX.transform.GetChild(0).gameObject.SetActive(false);
|
||||
currSitData.lockFX.transform.GetChild(1).gameObject.SetActive(true);
|
||||
if (mySitAnim != null && currSitData.turretParent != null)
|
||||
{
|
||||
// ⭐ 座位位置 + 左右座位各自的偏移:把"我在这"圆圈摆到座位上面
|
||||
// (左右座位镜像后需要的偏移不一样,分左/右两套配置,面板上调)
|
||||
Vector3 sitAnimOffset = IsLeftSeat(currSitData) ? mySitAnimOffsetLeft : mySitAnimOffsetRight;
|
||||
mySitAnim.transform.position = currSitData.turretParent.position + sitAnimOffset;
|
||||
// ⭐ 进入游戏圆圈:6 秒后自动消失(点击屏幕立即消失的逻辑在 HandleInput)
|
||||
StartCoroutine(HideMySitAnimAfter(6f));
|
||||
}
|
||||
// ⭐ 座位/房间信息初始化推迟到"加载到 100%"后执行(见 ApplyFirstShowInit 与加载完成点):
|
||||
// 原来在这里立即 JoinGame/摆座位,进房入场动画会在加载期播放——玩家看不到、位置未就绪。
|
||||
_pendingFirstShowInit = true;
|
||||
_pendingRoomJoinNotice = roomJoinNotice;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -454,6 +410,72 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 进房首个初始化(座位/房间信息):原 OnShow 里 isfirstShow 的整段逻辑(原样搬入),
|
||||
/// 现由"加载到 100%"的加载完成点调用——保证入场动画等在玩家可见、位置就绪后才初始化/播放。
|
||||
/// </summary>
|
||||
private void ApplyFirstShowInit()
|
||||
{
|
||||
RoomJoinNotice roomJoinNotice = _pendingRoomJoinNotice;
|
||||
if (roomJoinNotice == null) return;
|
||||
|
||||
string roomId = GameManager.Instance.gameData.currRoomData.roomId;
|
||||
|
||||
|
||||
foreach (var item in GameManager.Instance.gameData.currRoomData.players)
|
||||
{
|
||||
JoinGame(item.position, item.gold, item.diamond, item.cannonMultiple, 0, item.userId, item.cannonId, item.wingsId, item.warGodId);
|
||||
// ⭐ 优先用后端 isBot 字段,兼容 userId.StartsWith("bot_")
|
||||
var sit = list_Sits.Find(s => s.posID == item.position);
|
||||
if (sit != null)
|
||||
{
|
||||
bool isBot = item.isBot ||
|
||||
(!string.IsNullOrEmpty(item.userId) && item.userId.StartsWith("bot_"));
|
||||
if (isBot) sit.isBot = true;
|
||||
}
|
||||
}
|
||||
GameManager.Instance.gameData.roomJoinNotice = roomJoinNotice;
|
||||
isfirstShow = false;
|
||||
|
||||
foreach (var item in list_Sits)
|
||||
{
|
||||
// ⭐ 座位镜像:本地玩家的显示座位 = 服务端座位转显示空间(上方座位翻转后落回下方)
|
||||
if (item.posID == SeatMirror.ToDisplay(roomJoinNotice.Position))
|
||||
{
|
||||
currSitData = item;
|
||||
// ⭐ 长按本地座位的 img_OpenPT 开关炮台面板(与 btn_ChangeTurret 同逻辑)
|
||||
HookOpenPTLongPress(currSitData);
|
||||
// ⭐ 本地座位自动攻击关闭时广播 Idle 状态给其他客户端
|
||||
HookAutoAttackOff(currSitData);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ⭐ 非本地座位隐藏加减炮倍:Normal 藏座位按钮(未拖引用为 null 跳过),
|
||||
// XJMH 藏炮台上的加减倍(TurretData.obj_Add / obj_Down)
|
||||
item.HideTurretAddMinusUI();
|
||||
// ⭐ 自动攻击开关与加减倍按钮一样:非本地座位隐藏
|
||||
if (item.toggle_AutoAttack != null)
|
||||
item.toggle_AutoAttack.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
}
|
||||
//// currSitData.ChangeTurret(1); — 已由 SitPosData.OnEnable 自动加载
|
||||
if (currSitData.currentTurret != null)
|
||||
SyncChangeTurret(currSitData.currentTurret.turretNumber);
|
||||
currSitData.lockFX.transform.GetChild(0).gameObject.SetActive(false);
|
||||
currSitData.lockFX.transform.GetChild(1).gameObject.SetActive(true);
|
||||
if (mySitAnim != null && currSitData.turretParent != null)
|
||||
{
|
||||
// ⭐ 座位位置 + 左右座位各自的偏移:把"我在这"圆圈摆到座位上面
|
||||
// (左右座位镜像后需要的偏移不一样,分左/右两套配置,面板上调)
|
||||
Vector3 sitAnimOffset = IsLeftSeat(currSitData) ? mySitAnimOffsetLeft : mySitAnimOffsetRight;
|
||||
mySitAnim.transform.position = currSitData.turretParent.position + sitAnimOffset;
|
||||
// ⭐ 进入游戏圆圈:6 秒后自动消失(点击屏幕立即消失的逻辑在 HandleInput)
|
||||
StartCoroutine(HideMySitAnimAfter(6f));
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshGGKCount()
|
||||
{
|
||||
var user = GameManager.Instance.user;
|
||||
@@ -1401,6 +1423,15 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
else if (JinDuTiao != null)
|
||||
JinDuTiao.Hide();
|
||||
|
||||
// ⭐ 加载到 100%(进度条已隐藏):标记完成 + 执行挂起的进房初始化(座位/房间信息)。
|
||||
// 入场动画等表现由初始化链路在此之后触发——玩家可见、位置已就绪
|
||||
IsGameLoadCompleted = true;
|
||||
if (_pendingFirstShowInit)
|
||||
{
|
||||
_pendingFirstShowInit = false;
|
||||
ApplyFirstShowInit();
|
||||
}
|
||||
|
||||
// ⭐ 无操作自动退出:加载完成,从现在开始计无操作时间
|
||||
ArmIdleAutoExit();
|
||||
}
|
||||
@@ -3065,7 +3096,8 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
{
|
||||
// ⭐ 起飞炮台(FlyTurretData):
|
||||
// 飞行/悬停中 → 点击空白处=改目标(点到哪飞到哪),立即响应;
|
||||
// 未起飞 → 仅记录轻点判定,继续走下方正常开火流程(松开时判定轻点才起飞),
|
||||
// 未起飞 → 仅记录轻点判定,继续走下方正常开火流程(松开时判定轻点是否起飞,
|
||||
// 是否允许由 FlyTurretData.allowTapTakeoff 控制,默认关=没点起飞按钮不起飞),
|
||||
// 保证平时按住扫射/自动开火与普通炮台完全一致
|
||||
if (currSitData.currentTurret is FlyTurretData flyTurret)
|
||||
{
|
||||
@@ -3129,7 +3161,7 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
return;
|
||||
}
|
||||
|
||||
// ⭐ 起飞炮台:轻点空白处=起飞(按下时已正常开火,松开时判定轻点→触发起飞)
|
||||
// ⭐ 起飞炮台:轻点空白处=起飞(受 allowTapTakeoff 控制,默认关;按下时已正常开火)
|
||||
// 长按/拖动扫射时此判定不通过,正常走下方 Idle,普通开火完全不受影响
|
||||
if (_flyTapPending)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6148,8 +6148,11 @@ MonoBehaviour:
|
||||
goldNum: 0
|
||||
consumeGoldNum: 0
|
||||
tMP_GoldNum: {fileID: 5250310886200927483}
|
||||
goldNum_UGUI: {fileID: 0}
|
||||
tMP_DiamondNum: {fileID: 9208482097770273619}
|
||||
diamondNum_UGUI: {fileID: 0}
|
||||
tMP_TurretConsumeNum: {fileID: 6996998917093333593}
|
||||
turretConsumeNum_UGUI: {fileID: 0}
|
||||
wingParent: {fileID: 5982321734877658021}
|
||||
zhanShenParent: {fileID: 3297566421429981692}
|
||||
currentZhanShenNumber: 0
|
||||
@@ -6165,7 +6168,7 @@ MonoBehaviour:
|
||||
xjmhTurretList: []
|
||||
tra_CurrTurret: {fileID: 0}
|
||||
currentAngle: 0
|
||||
maxRotationAngle: 70
|
||||
maxRotationAngle: 92
|
||||
monCotl_Lock: {fileID: 0}
|
||||
monCotl_Lock_Position: {fileID: 0}
|
||||
isLock: 0
|
||||
|
||||
Reference in New Issue
Block a user