diff --git a/Assets/MyGame/aa/Game/XJMH/Boss/JiXieXie/PW_Enemy_3000.prefab b/Assets/MyGame/aa/Game/XJMH/Boss/JiXieXie/PW_Enemy_3000.prefab
index ed0b377d7..c5462d105 100644
--- a/Assets/MyGame/aa/Game/XJMH/Boss/JiXieXie/PW_Enemy_3000.prefab
+++ b/Assets/MyGame/aa/Game/XJMH/Boss/JiXieXie/PW_Enemy_3000.prefab
@@ -122,7 +122,7 @@ MonoBehaviour:
cachedCamera: {fileID: 0}
cachedUirootRect: {fileID: 0}
skeleton: {fileID: 0}
- isSpine: 1
+ isSpine: 0
fishTypeID: 12028
currState: 0
HP: 5
diff --git a/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/PW_Enemy_4000.prefab b/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/PW_Enemy_4000.prefab
index 5e6d67ed4..877f09080 100644
--- a/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/PW_Enemy_4000.prefab
+++ b/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/PW_Enemy_4000.prefab
@@ -8,10 +8,26 @@ PrefabInstance:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
+ - target: {fileID: 1146886045327190, guid: 44623ca91d5f59049b506c55c76f2aef, type: 3}
+ propertyPath: m_IsActive
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 1622780724854902, guid: 44623ca91d5f59049b506c55c76f2aef, type: 3}
+ propertyPath: m_IsActive
+ value: 0
+ objectReference: {fileID: 0}
- target: {fileID: 1658730911317380, guid: 44623ca91d5f59049b506c55c76f2aef, type: 3}
propertyPath: m_Name
value: PW_Enemy_4000
objectReference: {fileID: 0}
+ - target: {fileID: 1707060374769447, guid: 44623ca91d5f59049b506c55c76f2aef, type: 3}
+ propertyPath: m_IsActive
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 1981398447280843, guid: 44623ca91d5f59049b506c55c76f2aef, type: 3}
+ propertyPath: m_IsActive
+ value: 1
+ objectReference: {fileID: 0}
- target: {fileID: 4231307354823747, guid: 44623ca91d5f59049b506c55c76f2aef, type: 3}
propertyPath: m_LocalPosition.x
value: 0
@@ -52,6 +68,16 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: -0
objectReference: {fileID: 0}
+ - target: {fileID: 199488493079174609, guid: 44623ca91d5f59049b506c55c76f2aef,
+ type: 3}
+ propertyPath: m_Materials.Array.size
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 199656832037048821, guid: 44623ca91d5f59049b506c55c76f2aef,
+ type: 3}
+ propertyPath: m_Materials.Array.size
+ value: 1
+ objectReference: {fileID: 0}
m_RemovedComponents:
- {fileID: 7031818894128611810, guid: 44623ca91d5f59049b506c55c76f2aef, type: 3}
m_RemovedGameObjects: []
@@ -149,5 +175,10 @@ MonoBehaviour:
nonFinalDeathBjEndUI: {fileID: -382508373279050920, guid: 75a52b8c1537cad49b3d521483fe134e,
type: 3}
resumeMoveDelay: 2
+ nonFinalDeathAnimationName: stand02
+ normalAnimationName: stand01
+ skeletonChildName:
+ hittingPath: body/bone/hitting
+ hittingDuration: 2
useServerParam: 1
maxDeathCount: 2
diff --git a/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/XingJiXunHangEvent.cs b/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/XingJiXunHangEvent.cs
index c1fa42354..222ede81e 100644
--- a/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/XingJiXunHangEvent.cs
+++ b/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/XingJiXunHangEvent.cs
@@ -178,6 +178,9 @@ public class XingJiXunHangEvent : BJEventBase
[Tooltip("4条激光伸展到最长位置的耗时(秒)")]
public float laserExpandSpeed = 0.6f;
+ [Tooltip("光子激光结束后等待时长(秒),然后直接隐藏 Prop(默认1)")]
+ public float symmetraPropHideDelay = 1f;
+
[Header("光子 - 电网扫动杀鱼")]
[Tooltip("电网(Prop整体)上下扫动幅度(世界单位)")]
public float netSweepAmplitude = 5f;
@@ -202,9 +205,9 @@ public class XingJiXunHangEvent : BJEventBase
public string[] gammaLaserNames = { "laser1", "laser2", "laser3", "laser4" };
[Tooltip("射线显示后到开始旋转的等待(秒,默认1)")]
public float gammaRotateDelay = 1f;
- [Tooltip("总旋转角度(度,默认80°)")]
- public float gammaRotateAngle = 80f;
- [Tooltip("转到该角度后激光开始缩短(度,默认45°)")]
+ [Tooltip("总旋转角度(度,默认90°,转完为止)")]
+ public float gammaRotateAngle = 90f;
+ [Tooltip("转到该角度后激光开始一点一点缩短(度,默认45°)")]
public float gammaShrinkStartAngle = 45f;
[Tooltip("旋转速度(度/秒,正=逆时针)")]
public float gammaRotateSpeed = 45f;
@@ -271,6 +274,12 @@ public class XingJiXunHangEvent : BJEventBase
/// 本局电网已炸的鱼 guid(防止扫动中重复炸同一鱼)
private readonly HashSet _netKilledFish = new HashSet();
+ /// Boss 分数面板 TMP(挂在独立 UI 层,Boss 删除后仍有效)
+ private TMPro.TextMeshProUGUI _bossScoreTmp;
+
+ /// 本局杀鱼累计加到 Boss 面板的分值
+ private long _bossPanelScore = 0;
+
/// 爆奖过程中实例化的所有临时特效(die() 时统一销毁,防止残留)
private readonly System.Collections.Generic.List _spawnedEffects = new System.Collections.Generic.List();
@@ -294,6 +303,9 @@ public class XingJiXunHangEvent : BJEventBase
scoreCount = bjCount;
totalBJCount = bjCount;
+ // ⭐ 星际巡航不需要 ScoreNumScroll(Clone) 加分数字滚动特效(杀鱼分已加 Boss 面板)
+ showAddScoreFX = false;
+
// 解析武器 ID
ParseWeaponId();
@@ -324,6 +336,8 @@ public class XingJiXunHangEvent : BJEventBase
bossCtrl = null;
diePos = Vector3.zero;
_netKilledFish.Clear();
+ _bossScoreTmp = null;
+ _bossPanelScore = 0;
// ⭐ 对象池复用:清理上次残留的临时特效
for (int i = 0; i < _spawnedEffects.Count; i++)
@@ -383,7 +397,7 @@ public class XingJiXunHangEvent : BJEventBase
/// 根据武器 ID 选择对应的预制体和标签
private void SelectWeaponPrefabs()
{
- _weaponId = 8;
+ _weaponId = 7;
switch (_weaponId)
{
case 0:
@@ -842,10 +856,16 @@ public class XingJiXunHangEvent : BJEventBase
// ⭐ 逐个杀:每只间隔 = 总时长/数量,整体约 1 秒
float interval = ironFistKillTotalTime / fishes.Count;
- Vector3 sitPos = GetSeatPosition();
+ Vector3 turretPos = GetSeatPosition(); // 金币飞向炮台
int killed = 0;
foreach (var monster in fishes)
{
+ // ⭐ 分数加满(=maxScore)后停止杀鱼
+ if (BossScoreFull)
+ {
+ Debug.Log($"[XingJiXunHang] 铁拳: 面板分已达上限 {maxScore},停止杀鱼");
+ break;
+ }
if (monster == null) continue;
if (!_netKilledFish.Add(monster.guid)) continue;
@@ -853,7 +873,9 @@ public class XingJiXunHangEvent : BJEventBase
{
Amount = paoBei * monster.monsterData.fishTypeConfig.fishScore
};
- CreateFishManager.Instance.Id_DieFish_FX(monster.guid, coinNum, sitPos, isLocal: isSelf);
+ // ⭐ 飞机死亡掉金币(飞向炮台),分数同时加到 Boss 面板(封顶 maxScore)
+ CreateFishManager.Instance.Id_DieFish_FX(monster.guid, coinNum, turretPos, isLocal: isSelf);
+ AddBossPanelScore(coinNum.Amount);
killed++;
Debug.Log($"[XingJiXunHang] 铁拳: 从近到远杀鱼[{killed}/{fishes.Count}] 距离={Vector2.Distance(monster.transform.position, center):0.00}");
yield return new WaitForSeconds(interval);
@@ -959,7 +981,13 @@ public class XingJiXunHangEvent : BJEventBase
yield return StartCoroutine(ElectricNetSweep(propObj, propL, propR));
}
- yield return new WaitForSeconds(0.3f);
+ // ⭐ 激光结束:等 1 秒后直接隐藏 Prop(不再一直显示到爆奖结束才回收)
+ yield return new WaitForSeconds(symmetraPropHideDelay);
+ if (propObj != null)
+ {
+ propObj.SetActive(false);
+ Debug.Log($"[XingJiXunHang] 光子: 激光结束等待 {symmetraPropHideDelay}s 后隐藏 Prop");
+ }
}
///
@@ -1010,8 +1038,9 @@ public class XingJiXunHangEvent : BJEventBase
}
///
- /// 电网扫动:Prop 整体上下移动(幅度 netSweepAmplitude,来回 netSweepCycles 次),
+ /// 电网扫动:Prop 整体上下移动(幅度 netSweepAmplitude,最多 netSweepCycles 次),
/// 扫动过程中每帧检测 PropL~PropR 之间的矩形区域,碰到普通鱼 → 爆炸(Id_DieFish_FX)。
+ /// ⭐ 不需要一直按设定的圈数移动:面板分加满(=maxScore)后提前停止扫动。
///
private IEnumerator ElectricNetSweep(GameObject propObj, Transform propL, Transform propR)
{
@@ -1020,14 +1049,21 @@ public class XingJiXunHangEvent : BJEventBase
Vector3 basePos = propObj.transform.position;
for (int i = 0; i < netSweepCycles; i++)
{
+ // ⭐ 面板分加满:提前停止扫动(不需要一直按圈数移动)
+ if (BossScoreFull)
+ {
+ Debug.Log($"[XingJiXunHang] 光子: 面板分已达上限 {maxScore},提前停止电网扫动");
+ break;
+ }
// 上扫
yield return StartCoroutine(SweepSegment(propObj, propL, propR, basePos + Vector3.up * netSweepAmplitude));
+ if (BossScoreFull) break;
// 下扫
yield return StartCoroutine(SweepSegment(propObj, propL, propR, basePos - Vector3.up * netSweepAmplitude));
}
// 回原位
yield return StartCoroutine(SweepSegment(propObj, propL, propR, basePos));
- Debug.Log($"[XingJiXunHang] 光子: 电网扫动完成 cycles={netSweepCycles} 炸鱼数={_netKilledFish.Count}");
+ Debug.Log($"[XingJiXunHang] 光子: 电网扫动结束(计划{netSweepCycles}圈)炸鱼数={_netKilledFish.Count}");
}
/// 电网从当前位置移动到 dest(逐帧插值 + 途中杀鱼)
@@ -1045,10 +1081,12 @@ public class XingJiXunHangEvent : BJEventBase
propObj.transform.position = Vector3.Lerp(start, dest, t);
if (netKillFish)
KillFishInNet(propL, propR);
+ // ⭐ 分数加满:本段提前结束
+ if (BossScoreFull) break;
yield return null;
}
propObj.transform.position = dest;
- if (netKillFish)
+ if (netKillFish && !BossScoreFull)
KillFishInNet(propL, propR);
}
@@ -1075,10 +1113,16 @@ public class XingJiXunHangEvent : BJEventBase
Collider2D[] hits = Physics2D.OverlapAreaAll(min, max, netKillLayer);
if (hits == null || hits.Length == 0) return;
- Vector3 sitPos = GetSeatPosition();
+ Vector3 turretPos = GetSeatPosition(); // 金币飞向炮台
int killed = 0;
foreach (var hit in hits)
{
+ // ⭐ 分数加满(=maxScore)后停止杀鱼
+ if (BossScoreFull)
+ {
+ Debug.Log($"[XingJiXunHang] 电网: 面板分已达上限 {maxScore},停止杀鱼");
+ break;
+ }
if (hit == null || !hit.CompareTag("Fish")) continue;
var monster = hit.GetComponentInParent();
if (monster == null) continue;
@@ -1089,7 +1133,9 @@ public class XingJiXunHangEvent : BJEventBase
{
Amount = paoBei * monster.monsterData.fishTypeConfig.fishScore
};
- CreateFishManager.Instance.Id_DieFish_FX(monster.guid, coinNum, sitPos, isLocal: isSelf);
+ // ⭐ 飞机死亡掉金币(飞向炮台),分数同时加到 Boss 面板(封顶 maxScore)
+ CreateFishManager.Instance.Id_DieFish_FX(monster.guid, coinNum, turretPos, isLocal: isSelf);
+ AddBossPanelScore(coinNum.Amount);
killed++;
}
if (killed > 0)
@@ -1209,6 +1255,17 @@ public class XingJiXunHangEvent : BJEventBase
// 终点:激光缩到 0 长度(隐藏)
UpdateGammaLaserEndpoints(lasers, propObj.transform.position, 0f);
Debug.Log($"[XingJiXunHang] 伽马风暴: 旋转完成 {rotated:0.#}°(45°后激光缩短至消失)炸鱼 {killCount} 条");
+
+ // ⭐ 分不够就直接补齐到 maxScore(旋转杀鱼没杀满时,面板补满)
+ if (!BossScoreFull)
+ {
+ long need = maxScore - _bossPanelScore;
+ if (need > 0)
+ {
+ AddBossPanelScore(need);
+ Debug.Log($"[XingJiXunHang] 伽马风暴: 分不够,直接补齐 {need} → {_bossPanelScore}");
+ }
+ }
}
///
@@ -1282,7 +1339,7 @@ public class XingJiXunHangEvent : BJEventBase
return;
}
- Vector3 sitPos = GetSeatPosition();
+ Vector3 turretPos = GetSeatPosition(); // 金币飞向炮台
foreach (var laser in lasers)
{
if (laser == null) continue;
@@ -1299,6 +1356,12 @@ public class XingJiXunHangEvent : BJEventBase
foreach (var hit in hits)
{
+ // ⭐ 分数加满(=maxScore)后停止杀鱼
+ if (BossScoreFull)
+ {
+ Debug.Log($"[XingJiXunHang] 伽马射线: 面板分已达上限 {maxScore},停止杀鱼");
+ return;
+ }
if (hit.collider == null || !hit.collider.CompareTag("Fish")) continue;
var monster = hit.collider.GetComponentInParent();
if (monster == null) continue;
@@ -1309,7 +1372,9 @@ public class XingJiXunHangEvent : BJEventBase
{
Amount = paoBei * monster.monsterData.fishTypeConfig.fishScore
};
- CreateFishManager.Instance.Id_DieFish_FX(monster.guid, coinNum, sitPos, isLocal: isSelf);
+ // ⭐ 飞机死亡掉金币(飞向炮台),分数同时加到 Boss 面板(封顶 maxScore)
+ CreateFishManager.Instance.Id_DieFish_FX(monster.guid, coinNum, turretPos, isLocal: isSelf);
+ AddBossPanelScore(coinNum.Amount);
killCount++;
}
}
@@ -1363,6 +1428,55 @@ public class XingJiXunHangEvent : BJEventBase
// ==================== 辅助方法 ====================
+ /// 每死亡一个飞机,就往 Boss 分数面板上加一个分(面板独立于 Boss 本体,删除后仍有效)
+ private void AddBossPanelScore(long amount)
+ {
+ if (amount <= 0) return;
+
+ // ⭐ 面板加分不能超过金币上限 maxScore(封顶)
+ long newScore = _bossPanelScore + amount;
+ if (newScore > maxScore)
+ newScore = maxScore;
+ if (newScore == _bossPanelScore) return; // 已封顶,无变化
+
+ _bossPanelScore = newScore;
+ EnsureBossScoreTmp();
+ if (_bossScoreTmp != null)
+ {
+ _bossScoreTmp.text = _bossPanelScore.ToString();
+ Debug.Log($"[XingJiXunHang] Boss分数面板 +{amount} = {_bossPanelScore}(上限{maxScore})");
+ }
+ }
+
+ /// 面板分是否已加满(= maxScore 后停止杀鱼)
+ private bool BossScoreFull => _bossPanelScore >= maxScore;
+
+ /// 确保 Boss 分数面板 TMP 可用(优先用 bossCtrl 已创建的,否则手动创建)
+ private void EnsureBossScoreTmp()
+ {
+ if (_bossScoreTmp != null) return;
+
+ // 1. 从 bossCtrl 拿(Boss 删除前已缓存的面板引用)
+ if (bossCtrl != null && bossCtrl.tMP_CurrBossScore != null)
+ {
+ _bossScoreTmp = bossCtrl.tMP_CurrBossScore;
+ return;
+ }
+
+ // 2. 手动创建分数面板(同 MonsterControl_BossBase.EnsureScorePanel 逻辑)
+ var prefab = CreateFishManager.Instance != null
+ ? CreateFishManager.Instance.dieFXPrefabAwardTmp : null;
+ var parent = CreateFishManager.Instance != null && CreateFishManager.Instance.currGameType != null
+ ? CreateFishManager.Instance.currGameType.subPanelParent : null;
+ if (prefab == null || parent == null) return;
+
+ var board = Instantiate(prefab, parent);
+ // ⭐ 加分面板位置放在座位上方才是正常的
+ board.transform.position = GetSeatPosition() + Vector3.up * 150f;
+
+ _bossScoreTmp = board.transform.GetChild(0).GetComponent();
+ }
+
///
/// 缓存 UI 层父节点 + Canvas:
/// 父节点 = currGameType.subPanelParent.parent(与爆奖预制体同层,随 UI 卸载自动清理)
@@ -1548,6 +1662,25 @@ public class XingJiXunHangEvent : BJEventBase
EffectPool.Instance.Return(gameObject);
}
+ ///
+ /// 加分完成:先走基类(显示 BJEndUI + 加分 + 收尾),
+ /// 然后删除/回收手动创建的 Boss 分数面板(_bossScoreTmp)。
+ ///
+ protected override void OnScoreEnd()
+ {
+ base.OnScoreEnd(); // ⭐ 弹出 BJEndUI
+
+ // ⭐ 弹出 BJEndUI 时回收/删除手动创建的 Boss 分数面板
+ if (_bossScoreTmp != null)
+ {
+ var board = _bossScoreTmp.transform.parent;
+ if (board != null)
+ Destroy(board.gameObject);
+ _bossScoreTmp = null;
+ Debug.Log("[XingJiXunHang] 弹出 BJEndUI:Boss 分数面板已删除");
+ }
+ }
+
private void OnDestroy()
{
StopAllCoroutines();
diff --git a/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/XingJiXunHang_BOSS.cs b/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/XingJiXunHang_BOSS.cs
index 8d7741cb3..709bc4f32 100644
--- a/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/XingJiXunHang_BOSS.cs
+++ b/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/XingJiXunHang_BOSS.cs
@@ -1,5 +1,6 @@
using Assets.MyGame.Scripts.Net.WebResponses;
using Newtonsoft.Json.Linq;
+using Spine.Unity;
using System;
using System.Collections;
using UnityEngine;
@@ -29,6 +30,23 @@ public class XingJiXunHang_BOSS : MonsterControl_BossBase
[Tooltip("非最终死亡后,Boss 恢复游动的延迟(秒)")]
public float resumeMoveDelay = 2f;
+ [Header("星际巡航 - 非最终死亡动画(animId=1)")]
+ [Tooltip("不死时播放的 Spine 动画名(stand02 = 第一种不死亡爆奖动画)")]
+ public string nonFinalDeathAnimationName = "stand02";
+
+ [Tooltip("正常默认动画名(stand01,不死动画播放完恢复游动时切回)")]
+ public string normalAnimationName = "stand01";
+
+ [Tooltip("SkeletonAnimation 所在子对象名(留空=自动 GetComponentInChildren 查找)")]
+ public string skeletonChildName = "";
+
+ [Header("星际巡航 - Hitting 特效")]
+ [Tooltip("Hitting 特效子对象路径(相对 Boss 根,如 body/bone/hitting)")]
+ public string hittingPath = "body/bone/hitting";
+
+ [Tooltip("Hitting 特效激活持续时间(秒,默认2)")]
+ public float hittingDuration = 2f;
+
[Header("星际巡航 - 服务端参数解析")]
[Tooltip("是否从 param 解析 isKill(关闭则用 maxDeathCount 客户端兜底判定)")]
public bool useServerParam = true;
@@ -67,6 +85,9 @@ public class XingJiXunHang_BOSS : MonsterControl_BossBase
/// 爆奖事件是否已 Init(决定特效实例由谁回收)
private bool _awardInitCalled = false;
+ /// 正在运行的 Hitting 特效协程(同一时间只允许一个,防连续触发冲突)
+ private Coroutine _hittingRoutine = null;
+
// ==================== Unity 生命周期 ====================
public override void OnEnable()
@@ -79,7 +100,33 @@ public class XingJiXunHang_BOSS : MonsterControl_BossBase
_removed = false;
_diePosCached = false;
_awardInitCalled = false;
+ _hittingRoutine = null;
currEvent = null;
+
+ // ⭐ 恢复被修改过的激活状态(对象池复用:Hitting 特效强制恢复初始关闭)
+ ResetHittingState();
+ }
+
+ /// 恢复 Hitting 特效的初始激活状态(关闭)
+ private void ResetHittingState()
+ {
+ // 停掉残留的 Hitting 协程
+ if (_hittingRoutine != null)
+ {
+ StopCoroutine(_hittingRoutine);
+ _hittingRoutine = null;
+ }
+
+ Transform hitting = null;
+ if (!string.IsNullOrEmpty(hittingPath))
+ {
+ hitting = transform.Find(hittingPath);
+ if (hitting == null)
+ hitting = FindChildPathIgnoreCase(transform, hittingPath);
+ }
+
+ if (hitting != null)
+ hitting.gameObject.SetActive(false);
}
// ==================== 死亡逻辑 ====================
@@ -142,13 +189,21 @@ public class XingJiXunHang_BOSS : MonsterControl_BossBase
// ==================== 非最终死亡 ====================
- /// 非最终死亡:显示 BJEndUI,Boss 保留,等待下次击杀
+ /// 非最终死亡:显示 BJEndUI + 播放不死动画,Boss 保留,等待下次击杀
private void NonFinalDeath(RoomKillNotice obj, int beishu)
{
_cachedKillNotice = obj;
Debug.Log($"[XingJiXunHang] 非最终死亡:显示 BJEndUI,Boss 保留");
+ // ⭐ 播放不死动画(SkeletonAnimation,从子对象获取)
+ PlayNonFinalDeathAnimation();
+
+ // ⭐ 播放 Hitting 特效:只激活一个协程(连续触发先停旧的,防止特效状态错乱)
+ if (_hittingRoutine != null)
+ StopCoroutine(_hittingRoutine);
+ _hittingRoutine = StartCoroutine(PlayHittingEffect());
+
// 显示 BJEndUI(倍数+分数)
ShowNonFinalDeathBjEndUI(obj, beishu);
@@ -177,6 +232,140 @@ public class XingJiXunHang_BOSS : MonsterControl_BossBase
isMove = true;
Debug.Log("[XingJiXunHang] 非最终死亡后恢复游动");
}
+
+ // ⭐ 不死动画(stand02)播完,切回正常默认动画(stand01)
+ PlaySkeletonAnimation(normalAnimationName);
+ }
+
+ /// 获取 SkeletonAnimation(指定子对象或递归查找)并播放指定动画;动画不存在时回退 fallbackName
+ private void PlaySkeletonAnimation(string animationName, string fallbackName = null)
+ {
+ if (string.IsNullOrEmpty(animationName)) return;
+
+ SkeletonAnimation sa = null;
+
+ // 1. 指定子对象名 → 直接找该子对象上的组件
+ if (!string.IsNullOrEmpty(skeletonChildName))
+ {
+ Transform child = transform.Find(skeletonChildName);
+ if (child != null)
+ {
+ sa = child.GetComponent();
+ if (sa == null)
+ sa = child.GetComponentInChildren(true);
+ }
+ }
+
+ // 2. 递归查找:⭐ 优先选"包含目标动画"的 SkeletonAnimation(避免选错骨架)
+ if (sa == null)
+ {
+ var all = GetComponentsInChildren(true);
+ Debug.Log($"[XingJiXunHang] 找到 {all.Length} 个 SkeletonAnimation,目标动画={animationName}");
+ foreach (var s in all)
+ {
+ // Skeleton.data 是 protected,改用 SkeletonDataAsset 公共 API
+ var sd = s.SkeletonDataAsset != null ? s.SkeletonDataAsset.GetSkeletonData(false) : null;
+ if (sd != null && sd.FindAnimation(animationName) != null)
+ {
+ sa = s;
+ Debug.Log($"[XingJiXunHang] 选择包含动画 {animationName} 的骨架: {s.gameObject.name}");
+ break;
+ }
+ }
+ if (sa == null && all.Length > 0)
+ {
+ sa = all[0];
+ Debug.LogWarning($"[XingJiXunHang] 没有骨架包含动画 {animationName},用第一个 {sa.gameObject.name}");
+ }
+ }
+
+ if (sa == null)
+ {
+ Debug.LogWarning($"[XingJiXunHang] 找不到 SkeletonAnimation(子对象={skeletonChildName}),跳过动画 {animationName}");
+ return;
+ }
+
+ // ⭐ 目标动画在骨架里不存在 → 回退 fallbackName(防预制体存旧动画名如 "hit")
+ var data = sa.SkeletonDataAsset != null ? sa.SkeletonDataAsset.GetSkeletonData(false) : null;
+ if (data != null && data.FindAnimation(animationName) == null)
+ {
+ if (!string.IsNullOrEmpty(fallbackName) && data.FindAnimation(fallbackName) != null)
+ {
+ Debug.LogWarning($"[XingJiXunHang] 动画 {animationName} 不存在,回退 {fallbackName}");
+ animationName = fallbackName;
+ }
+ else
+ {
+ var animNames = new System.Collections.Generic.List();
+ foreach (var a in data.Animations) animNames.Add(a.Name);
+ Debug.LogWarning($"[XingJiXunHang] 骨架 {sa.gameObject.name} 可用动画: {string.Join(", ", animNames)}");
+ }
+ }
+
+ sa.AnimationName = animationName;
+ sa.timeScale = 1f;
+ Debug.Log($"[XingJiXunHang] 播放 Spine 动画: {animationName}(SkeletonAnimation on {sa.gameObject.name})");
+ }
+
+ /// 播放不死动画(stand02 = 第一种不死亡爆奖动画;Inspector 旧值找不到时回退 stand02)
+ private void PlayNonFinalDeathAnimation()
+ {
+ PlaySkeletonAnimation(nonFinalDeathAnimationName, "stand02");
+ }
+
+ ///
+ /// 播放 Hitting 特效:激活子对象(body/bone/hitting),等待 hittingDuration 秒后关闭。
+ /// ⭐ transform.Find 大小写敏感,找不到时用大小写不敏感路径查找兜底(Body/bone/hitting)。
+ ///
+ private IEnumerator PlayHittingEffect()
+ {
+ Transform hitting = null;
+ if (!string.IsNullOrEmpty(hittingPath))
+ {
+ hitting = transform.Find(hittingPath);
+ if (hitting == null)
+ hitting = FindChildPathIgnoreCase(transform, hittingPath);
+ }
+
+ if (hitting == null)
+ {
+ Debug.LogWarning($"[XingJiXunHang] 找不到 Hitting 特效子对象 {hittingPath},跳过");
+ yield break;
+ }
+
+ hitting.gameObject.SetActive(true);
+ Debug.Log($"[XingJiXunHang] Hitting 特效激活({hittingPath} → {hitting.gameObject.name})");
+
+ yield return new WaitForSeconds(hittingDuration);
+
+ if (hitting != null)
+ hitting.gameObject.SetActive(false);
+ _hittingRoutine = null; // 协程结束,允许下一次触发
+ Debug.Log($"[XingJiXunHang] Hitting 特效关闭({hittingDuration}s 后)");
+ }
+
+ /// 按路径逐级查找子对象(忽略大小写)
+ private Transform FindChildPathIgnoreCase(Transform root, string path)
+ {
+ if (root == null || string.IsNullOrEmpty(path)) return null;
+
+ Transform cur = root;
+ string[] parts = path.Split('/');
+ foreach (var p in parts)
+ {
+ Transform found = null;
+ for (int i = 0; i < cur.childCount; i++)
+ {
+ if (string.Equals(cur.GetChild(i).name, p, StringComparison.OrdinalIgnoreCase))
+ {
+ found = cur.GetChild(i);
+ break;
+ }
+ }
+ if (found == null) return null;
+ cur = found;
+ }
+ return cur;
}
/// 非最终死亡:显示 BJEndUI
diff --git a/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/dieFXPrefabAwardTmp.prefab b/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/dieFXPrefabAwardTmp.prefab
index 11402bb53..6a72617a6 100644
--- a/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/dieFXPrefabAwardTmp.prefab
+++ b/Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/dieFXPrefabAwardTmp.prefab
@@ -45,7 +45,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
bjEndUI: {fileID: -382508373279050920, guid: 75a52b8c1537cad49b3d521483fe134e, type: 3}
- useScorePanel: 1
+ useScorePanel: 0
tMP_Score: {fileID: 0}
scorePanelPrefab: {fileID: 0}
currScore: 0
@@ -126,6 +126,8 @@ MonoBehaviour:
serializedVersion: 2
m_Bits: 64
ironFistKillFish: 1
+ ironFistKillTotalTime: 1
+ ironFistAwardDelay: 2
symmetraLockName: Lock
symmetraPropLName: PropL
symmetraPropRName: PropR
@@ -137,6 +139,7 @@ MonoBehaviour:
laser3Name: laser3
laser4Name: laser4
laserExpandSpeed: 0.6
+ symmetraPropHideDelay: 1
netSweepAmplitude: 20
netSweepCycles: 3
netSweepSpeed: 3