1
This commit is contained in:
@@ -122,7 +122,7 @@ MonoBehaviour:
|
||||
cachedCamera: {fileID: 0}
|
||||
cachedUirootRect: {fileID: 0}
|
||||
skeleton: {fileID: 0}
|
||||
isSpine: 1
|
||||
isSpine: 0
|
||||
fishTypeID: 12028
|
||||
currState: 0
|
||||
HP: 5
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
/// <summary>本局电网已炸的鱼 guid(防止扫动中重复炸同一鱼)</summary>
|
||||
private readonly HashSet<string> _netKilledFish = new HashSet<string>();
|
||||
|
||||
/// <summary>Boss 分数面板 TMP(挂在独立 UI 层,Boss 删除后仍有效)</summary>
|
||||
private TMPro.TextMeshProUGUI _bossScoreTmp;
|
||||
|
||||
/// <summary>本局杀鱼累计加到 Boss 面板的分值</summary>
|
||||
private long _bossPanelScore = 0;
|
||||
|
||||
/// <summary>爆奖过程中实例化的所有临时特效(die() 时统一销毁,防止残留)</summary>
|
||||
private readonly System.Collections.Generic.List<GameObject> _spawnedEffects = new System.Collections.Generic.List<GameObject>();
|
||||
|
||||
@@ -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
|
||||
/// <summary>根据武器 ID 选择对应的预制体和标签</summary>
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1010,8 +1038,9 @@ public class XingJiXunHangEvent : BJEventBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 电网扫动:Prop 整体上下移动(幅度 netSweepAmplitude,来回 netSweepCycles 次),
|
||||
/// 电网扫动:Prop 整体上下移动(幅度 netSweepAmplitude,最多 netSweepCycles 次),
|
||||
/// 扫动过程中每帧检测 PropL~PropR 之间的矩形区域,碰到普通鱼 → 爆炸(Id_DieFish_FX)。
|
||||
/// ⭐ 不需要一直按设定的圈数移动:面板分加满(=maxScore)后提前停止扫动。
|
||||
/// </summary>
|
||||
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}");
|
||||
}
|
||||
|
||||
/// <summary>电网从当前位置移动到 dest(逐帧插值 + 途中杀鱼)</summary>
|
||||
@@ -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<MonsterContral>();
|
||||
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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -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<MonsterContral>();
|
||||
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
|
||||
|
||||
// ==================== 辅助方法 ====================
|
||||
|
||||
/// <summary>每死亡一个飞机,就往 Boss 分数面板上加一个分(面板独立于 Boss 本体,删除后仍有效)</summary>
|
||||
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})");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>面板分是否已加满(= maxScore 后停止杀鱼)</summary>
|
||||
private bool BossScoreFull => _bossPanelScore >= maxScore;
|
||||
|
||||
/// <summary>确保 Boss 分数面板 TMP 可用(优先用 bossCtrl 已创建的,否则手动创建)</summary>
|
||||
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<TMPro.TextMeshProUGUI>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缓存 UI 层父节点 + Canvas:
|
||||
/// 父节点 = currGameType.subPanelParent.parent(与爆奖预制体同层,随 UI 卸载自动清理)
|
||||
@@ -1548,6 +1662,25 @@ public class XingJiXunHangEvent : BJEventBase
|
||||
EffectPool.Instance.Return(gameObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加分完成:先走基类(显示 BJEndUI + 加分 + 收尾),
|
||||
/// 然后删除/回收手动创建的 Boss 分数面板(_bossScoreTmp)。
|
||||
/// </summary>
|
||||
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();
|
||||
|
||||
@@ -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
|
||||
/// <summary>爆奖事件是否已 Init(决定特效实例由谁回收)</summary>
|
||||
private bool _awardInitCalled = false;
|
||||
|
||||
/// <summary>正在运行的 Hitting 特效协程(同一时间只允许一个,防连续触发冲突)</summary>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>恢复 Hitting 特效的初始激活状态(关闭)</summary>
|
||||
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
|
||||
|
||||
// ==================== 非最终死亡 ====================
|
||||
|
||||
/// <summary>非最终死亡:显示 BJEndUI,Boss 保留,等待下次击杀</summary>
|
||||
/// <summary>非最终死亡:显示 BJEndUI + 播放不死动画,Boss 保留,等待下次击杀</summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>获取 SkeletonAnimation(指定子对象或递归查找)并播放指定动画;动画不存在时回退 fallbackName</summary>
|
||||
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<SkeletonAnimation>();
|
||||
if (sa == null)
|
||||
sa = child.GetComponentInChildren<SkeletonAnimation>(true);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 递归查找:⭐ 优先选"包含目标动画"的 SkeletonAnimation(避免选错骨架)
|
||||
if (sa == null)
|
||||
{
|
||||
var all = GetComponentsInChildren<SkeletonAnimation>(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<string>();
|
||||
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})");
|
||||
}
|
||||
|
||||
/// <summary>播放不死动画(stand02 = 第一种不死亡爆奖动画;Inspector 旧值找不到时回退 stand02)</summary>
|
||||
private void PlayNonFinalDeathAnimation()
|
||||
{
|
||||
PlaySkeletonAnimation(nonFinalDeathAnimationName, "stand02");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 播放 Hitting 特效:激活子对象(body/bone/hitting),等待 hittingDuration 秒后关闭。
|
||||
/// ⭐ transform.Find 大小写敏感,找不到时用大小写不敏感路径查找兜底(Body/bone/hitting)。
|
||||
/// </summary>
|
||||
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 后)");
|
||||
}
|
||||
|
||||
/// <summary>按路径逐级查找子对象(忽略大小写)</summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>非最终死亡:显示 BJEndUI</summary>
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user