This commit is contained in:
2026-08-18 21:36:11 +08:00
parent c637e8c0f2
commit d495c0a1fb
12 changed files with 1454 additions and 1450 deletions
@@ -117,7 +117,25 @@ MonoBehaviour:
m_BlendOutDuration: -1
m_MixInCurve:
serializedVersion: 2
m_Curve: []
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
@@ -183,25 +201,7 @@ MonoBehaviour:
m_BlendOutDuration: -1
m_MixInCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
@@ -501,7 +501,25 @@ MonoBehaviour:
m_BlendOutDuration: -1
m_MixInCurve:
serializedVersion: 2
m_Curve: []
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
@@ -1177,7 +1195,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 15c38f6fa1940124db1ab7f6fe7268d1, type: 3}
m_Name: Signal Emitter
m_EditorClassIdentifier:
m_Time: 11.033333333333333
m_Time: 4.7
m_Retroactive: 0
m_EmitOnce: 0
m_Asset: {fileID: 11400000, guid: 344d1087c2077664ebcfebc51d6cf167, type: 2}
@@ -243,8 +243,7 @@ AnimatorState:
m_CycleOffset: 0
m_Transitions:
- {fileID: 1101022412963193632}
m_StateMachineBehaviours:
- {fileID: 114460380814660115}
m_StateMachineBehaviours: []
m_Position: {x: 0, y: 0, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
@@ -272,8 +271,7 @@ AnimatorState:
m_Transitions:
- {fileID: 1101548376488700370}
- {fileID: 1101789666915644063}
m_StateMachineBehaviours:
- {fileID: 114111788291824224}
m_StateMachineBehaviours: []
m_Position: {x: 0, y: 0, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
@@ -299,8 +297,7 @@ AnimatorState:
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours:
- {fileID: 114603736864793662}
m_StateMachineBehaviours: []
m_Position: {x: 0, y: 0, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
@@ -328,8 +325,7 @@ AnimatorState:
m_Transitions:
- {fileID: 1101279710798771084}
- {fileID: 1101152711422040747}
m_StateMachineBehaviours:
- {fileID: 114736320092198403}
m_StateMachineBehaviours: []
m_Position: {x: 0, y: 0, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
@@ -392,7 +388,7 @@ AnimatorStateMachine:
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: 1102078394765988923}
m_Position: {x: 0, y: 0, z: 0}
m_Position: {x: 0, y: -10, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
+1 -1
View File
@@ -6398,7 +6398,7 @@ MonoBehaviour:
spawnList: []
isCreateFish: 0
isFrozen: 0
debugSpawnFishNumber: 12029
debugSpawnFishNumber: 12034
fishList_All: []
fishList_Small: []
fishList_Boss: []
@@ -44,6 +44,9 @@ public class BaoLieJinShaEvent : BJEventBase
base.Init(goldCount, posID, paobei, fishScore, beishu, action, action1);
// ⭐ 关闭加金币飘字特效(dieFXPrefabAwardTmp_AddScore),只加分不飘字
showAddScoreFX = false;
// ⭐ 取消 base 的报奖后停留(showDelay=3s,会拖慢收尾),
// 由重写的 MoveToSit 统一"加完分后等 1 秒直接显示 bjEndUI"
showDelay = 0f;
// 不在此处启动协程,等待 Boss 通知(TriggerExplosion)
}
@@ -146,6 +149,21 @@ public class BaoLieJinShaEvent : BJEventBase
return v;
}
/// <summary>
/// 加分完成后等 1 秒直接显示结束 UI(不飞回座位、不做多余停留)。
/// 爆炸/掉金币本身已展示爆奖效果,加分完成后无需再长时间等待。
/// </summary>
public override void MoveToSit()
{
StartCoroutine(WaitOneSecondThenEnd());
}
private IEnumerator WaitOneSecondThenEnd()
{
yield return new WaitForSeconds(1f);
OnScoreEnd();
}
/// <summary>
/// 重写 OnScoreEnd:bjEndUI 直接用 _totalCoin(long 精确值)显示。
/// maxScore 是 int,可能截断 long 总金币,所以用 _totalCoin 传给 bjEndUI。
@@ -158,25 +176,12 @@ public class BaoLieJinShaEvent : BJEventBase
// 回加金币到玩家
JiaFen?.Invoke();
// BJEndUI:直接用 _totalCoin(long)传给 Init
// BJEndUI:直接定位在座位上方(分数面板不飞回座位,省去移动等待)
if (bjEndUI != null)
{
Vector3 uiPos;
if (useScorePanel)
{
if (_scoreBoard != null)
uiPos = _scoreBoard.transform.position;
else if (tMP_Score != null)
uiPos = tMP_Score.transform.position;
else
uiPos = transform.position;
}
else
{
float y = bjEndUIOffsetY;
if (posID == 2 || posID == 3) y *= -1f;
uiPos = GetSeatPosition() + Vector3.up * y;
}
float y = bjEndUIOffsetY;
if (posID == 2 || posID == 3) y *= -1f;
Vector3 uiPos = GetSeatPosition() + Vector3.up * y;
var endUI = Instantiate(bjEndUI, uiPos, Quaternion.identity, CreateFishManager.Instance.bjEffectRoot);
long displayScore = _totalCoin > 0 ? _totalCoin : maxScore;
@@ -431,7 +431,7 @@ MonoBehaviour:
paoBei: 0
fishScore: 0
bJbeishu: 0
showDelay: 3
showDelay: 0
moveDuration: 0.5
moveEase: 6
startOffset: {x: 0, y: 0, z: -100}
@@ -0,0 +1,63 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class JiJiaLeiTingEvent : BJEventBase
{
public Text number_BeiShu;
[Header("倍数滚动")]
[Tooltip("倍数从1涨到最终倍数(bJbeishu)所需时间(秒)")]
public float beiShuRollDuration = 2f;
/// <summary>倍数滚动协程(防重复启动)</summary>
private Coroutine _beiShuCoroutine;
public void BJ()
{
CallBJ();
}
public void TimeLineEnd()
{
// 最后不发金币红包,直接结束:回加金币 + 显示 bjEndUI + 删分数面板 + 回收
OnScoreEnd();
}
/// <summary>
/// 动画事件调用:开始滚动倍数。
/// 从 1 慢慢往上涨,经过 beiShuRollDuration 秒后到达最终倍数 bJbeishu(服务端下发)。
/// </summary>
public void StartBeiShuRoll()
{
if (number_BeiShu == null) return;
// 防重复触发:先停掉上一次滚动
if (_beiShuCoroutine != null)
StopCoroutine(_beiShuCoroutine);
_beiShuCoroutine = StartCoroutine(BeiShuRollRoutine(1, bJbeishu, beiShuRollDuration));
}
private IEnumerator BeiShuRollRoutine(int from, int to, float duration)
{
if (duration <= 0f || to <= from)
{
number_BeiShu.text = to.ToString();
_beiShuCoroutine = null;
yield break;
}
float elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float t = Mathf.Clamp01(elapsed / duration);
number_BeiShu.text = Mathf.RoundToInt(Mathf.Lerp(from, to, t)).ToString();
yield return null;
}
// 确保最终精确落在最终倍数
number_BeiShu.text = to.ToString();
_beiShuCoroutine = null;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 51ecae76f52b23a47b0f8fd8cfc05fef
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
@@ -1,173 +1,90 @@
using Assets.MyGame.Scripts.Net.APIResponses.Enum;
using System;
using System.Collections;
using UnityEngine;
using Random = UnityEngine.Random;
/// <summary>
/// 烈焰风暴 Boss 爆奖事件(双重爆炸模式)。
/// 烈焰风暴 Boss 爆奖事件(精简版)。
///
/// 与通用爆奖不同:爆炸杀鱼 + 爆奖红包各执行 explodeCount 次(默认 2 次)。
/// 流程:
/// Boss 死亡 → Init → 等待 explosionDelay
/// → 第 1 次爆炸杀鱼 + CallBJ 发红包
/// → 等待 explosionDuration
/// → 第 2 次爆炸杀鱼 + CallBJ 发红包
/// → CallBJ 内部检测 currBJCount >= totalBJCount 自动 EffEnd
/// → DelayThenScore → StartAddScore → MoveToSit → OnScoreEnd → JiaFen → die
///
/// ⭐ die() 时回收 Boss 本体(从鱼列表移除)。
/// 第一次死亡时【不从鱼列表删除 Boss】,等爆奖流程全部结束(die 被调用)才回收,
/// 避免爆奖过程中 Boss 被提前移除导致后续逻辑(锁定、显示等)找不到。
/// 无死鱼、无红包、无滚分,流程只有:
/// 炸一下(播放爆炸特效,不死任何鱼)→ 等特效播完 → 显示 bjEndUI + 回加金币 → 回收。
/// 死亡/未死亡由 Boss 解析服务端 param 决定,Event 不关心。
/// </summary>
public class LieYanFengBaoEvent : BJEventBase
{
[Header("爆炸配置")]
[Tooltip("爆炸检测半径(世界单位)")]
public float explosionRadius = 5f;
[Tooltip("鱼层(Inspector 设 Fish)")]
public LayerMask fishLayer;
[Tooltip("爆炸延迟(Boss 死亡后到第一次爆炸的等待)")]
public float explosionDelay = 0.5f;
[Tooltip("每次爆炸特效持续时间(也是两次爆炸之间的间隔)")]
[Tooltip("爆炸特效播放时长(播完后显示 bjEndUI)")]
public float explosionDuration = 2f;
[Header("双重爆奖")]
[Tooltip("爆炸+爆奖次数(默认 2 次)")]
public int explodeCount = 2;
/// <summary>爆炸中心(世界坐标,由 Boss 传入=死亡位置)</summary>
[HideInInspector]
public Vector3 explosionCenter = Vector3.zero;
/// <summary>Boss 引用(爆奖结束时通知 Boss 回收)</summary>
/// <summary>Boss 引用(爆奖结束时通知恢复游动)</summary>
[System.NonSerialized]
public LieYanFengBao_BOSS bossCtrl;
public override void Init(long goldCount, int posID, long paobei, long fishScore, int beishu,
Action<int> action, Action action1 = null)
{
// 不需要分数面板/滚分/红包,纯特效 + bjEndUI
useScorePanel = false;
base.Init(goldCount, posID, paobei, fishScore, beishu, action, action1);
// ApplySeatOffset 已重写为空,这里恢复到 Boss 传入的爆炸中心(死亡位置)
// ApplySeatOffset 已重写为空;恢复到死亡位置
transform.position = explosionCenter;
// ⭐ 设置爆奖总次数:CallBJ 调用 explodeCount 次后,CoinArrivalRoutine 自动触发 EffEnd
scoreCount = explodeCount;
totalBJCount = explodeCount;
StartCoroutine(ExplodeThenScore());
StartCoroutine(PlayExplosionThenEnd());
}
/// <summary>重写:不移动到屏幕中心,但缓存座位引用(供 isSelf 判断使用)</summary>
/// <summary>重写:不移动到屏幕中心,只缓存座位引用(供 isSelf 判断和 bjEndUI 定位)</summary>
protected override void ApplySeatOffset()
{
// 不调用 base.ApplySeatOffset(),避免位置被移到屏幕中心 (0,0,-100)
// 但需要设置 _targetSit,否则 Init 里 isSelf 判断会失败
GetSeatPosition();
}
/// <summary>多次爆炸杀鱼 + 多次爆奖红包</summary>
private IEnumerator ExplodeThenScore()
/// <summary>炸一下 + 立即显示 bjEndUI;爆炸特效后台自己播,播完后静默回池</summary>
private IEnumerator PlayExplosionThenEnd()
{
// 等待 Boss 死亡动画结束
yield return new WaitForSeconds(explosionDelay);
// 重播粒子/动画(对象池复用后需手动重播)
ReplayExplosionEffect();
Debug.Log($"[LieYanFengBao] 开始双重爆奖 explodeCount={explodeCount} maxScore={maxScore} scoreCount={scoreCount} totalBJCount={totalBJCount}");
// ===== 无延迟立即执行 =====
// 回加金币
JiaFen?.Invoke();
for (int i = 0; i < explodeCount; i++)
// 显示 bjEndUI(座位上方)
if (bjEndUI != null)
{
Debug.Log($"[LieYanFengBao] 第 {i + 1}/{explodeCount} 次爆炸 位置={explosionCenter} maxScore={maxScore} layeredPool={layeredPool != null}");
// 0. 第一次爆炸播放相机震动+死亡音效(替代 base.DieFish 里的效果)
if (i == 0)
{
GameManager.Instance.cameraShake.ShakePresets.Explosion2D(3f, 4f, 1f);
if (bossCtrl != null)
{
var res = FishResourcesData.fishResourcesDatasDic.ContainsKey(bossCtrl.fishTypeID)
? FishResourcesData.fishResourcesDatasDic[bossCtrl.fishTypeID]
: null;
if (res != null && res.dieAudio != null && res.dieAudio.Count > 0)
AudioManager.Instance.PlayerFX(res.dieAudio[Random.Range(0, res.dieAudio.Count)]);
}
}
// 1. 重新播放爆炸特效(粒子系统只在首次激活时播放,后续循环需手动重播)
if (i > 0) ReplayExplosionEffect();
// 2. 范围杀鱼(每次爆炸独立检测,可炸到新出现的鱼)
ExplodeAt(explosionCenter);
// 3. 爆奖红包(CallBJ 内部启动 CoinArrivalRoutine 逐个累分)
// 最后一次 CallBJ 后,CoinArrivalRoutine 检测 currBJCount >= totalBJCount 自动 EffEnd
CallBJ();
// 等待爆炸特效播放(最后一次也等,让红包飞完再进入加分滚动)
yield return new WaitForSeconds(explosionDuration);
float y = bjEndUIOffsetY;
if (posID == 2 || posID == 3) y *= -1f;
Vector3 uiPos = GetSeatPosition() + Vector3.up * y;
var endUI = Instantiate(bjEndUI, uiPos, Quaternion.identity, CreateFishManager.Instance.bjEffectRoot);
endUI.Init(bJbeishu, maxScore, isSelf);
}
Debug.Log($"[LieYanFengBao] 循环结束 isEffEnd={isEffEnd} isScoreEnd={isScoreEnd} currBJCount={currBJCount} totalBJCount={totalBJCount} _activeCoinRoutines={_activeCoinRoutines}");
// ⭐ 安全兜底:如果 BigPrize 没返回红包记录(maxScore=0 或 layeredPool 已分完),
// CallBJ 不会启动 CoinArrivalRoutine,自动结束检测(在 CoinArrivalRoutine 末尾)永远不触发。
// 这里等所有金币协程跑完后,手动检查是否需要触发 EffEnd。
if (_activeCoinRoutines > 0)
yield return new WaitUntil(() => _activeCoinRoutines <= 0);
if (!isEffEnd && !isScoreEnd && currBJCount >= totalBJCount)
// 通知 Boss 爆奖结束(非死亡时恢复游动)
if (bossCtrl != null)
{
Debug.Log("[LieYanFengBao] 兜底触发 EffEnd(CoinArrivalRoutine 未自动触发)");
isGoldEffectStart = false;
EffEnd();
}
else
{
Debug.Log($"[LieYanFengBao] 兜底未触发 isEffEnd={isEffEnd} isScoreEnd={isScoreEnd}");
bossCtrl.OnAwardFinished();
bossCtrl = null;
}
// 爆炸特效播完后才回池(Return 会 SetActive(false),立即回池爆炸就看不到了)
yield return new WaitForSeconds(explosionDuration);
EffectPool.Instance.Return(gameObject);
}
/// <summary>在指定中心爆炸:范围内普通鱼死亡</summary>
private void ExplodeAt(Vector3 center)
{
Vector3 sitPos = GetSeatPosition();
var hits = Physics2D.OverlapCircleAll(center, explosionRadius, fishLayer);
int killCount = 0;
foreach (var hit in hits)
{
if (!hit.CompareTag("Fish")) continue;
var monster = hit.GetComponentInParent<MonsterContral>();
if (monster == null) continue;
if (monster.fishenum != FishTypeEnum.普通鱼) continue;
// 每条鱼的金币 = 炮倍 × 鱼底分
var coinNum = new RedPacketRecord
{
Amount = paoBei * monster.monsterData.fishTypeConfig.fishScore
};
CreateFishManager.Instance.Id_DieFish_FX(monster.guid, coinNum, sitPos, isSelf);
killCount++;
}
Debug.Log($"[LieYanFengBao] 爆炸炸死 {killCount} 条鱼");
}
/// <summary>
/// 重新播放爆炸特效(粒子系统 + Animator)。
/// 爆奖预制体激活时粒子只播一次,第二次爆炸需手动重播才能看到特效。
/// </summary>
/// <summary>重播爆炸特效(粒子 + Animator)</summary>
private void ReplayExplosionEffect()
{
// 重播所有粒子系统
var particleSystems = GetComponentsInChildren<ParticleSystem>(true);
int psCount = 0;
foreach (var ps in particleSystems)
{
if (ps == null) continue;
var main = ps.main;
main.loop = false; // 强制关闭循环,防止永生
main.loop = false;
ps.Clear(true);
ps.Play(true);
psCount++;
}
// 重播所有 Animator 动画
var animators = GetComponentsInChildren<Animator>(true);
foreach (var anim in animators)
{
@@ -175,28 +92,6 @@ public class LieYanFengBaoEvent : BJEventBase
anim.Rebind();
anim.Play(0, 0, 0f);
}
Debug.Log($"[LieYanFengBao] 重播爆炸特效: ParticleSystems={psCount} Animators={animators.Length}");
}
/// <summary>
/// 回收爆奖预制体到对象池 + 回收 Boss 本体。
/// ⭐ 爆奖流程完全结束(OnScoreEnd → JiaFen)后才调用此方法,
/// 此时从鱼列表移除 Boss 是安全的,不会影响爆奖过程中的任何逻辑。
/// </summary>
public override void die()
{
CleanupBeforeDie();
// ⭐ 回收 Boss 本体:爆奖全部结束,现在可以安全从鱼列表移除
if (bossCtrl != null && bossCtrl.gameObject != null)
{
Debug.Log($"[LieYanFengBao] 爆奖结束,回收 Boss 本体 guid={bossCtrl.guid}");
CreateFishManager.Instance.Id_DieFish_NotFX(bossCtrl.guid);
bossCtrl = null;
}
EffectPool.Instance.Return(gameObject);
}
private void OnDestroy()
@@ -1,197 +1,175 @@
using Assets.MyGame.Scripts.Net.APIResponses.Enum;
using Assets.MyGame.Scripts.Net.WebResponses;
using UnityEngine;
/// <summary>
/// 烈焰风暴 Boss。
/// 死亡流程(两阶段):
/// 第一次打死 → 显示 bjEndUI 即可,Boss 不消失,不触发爆炸
/// 第二次打死 → 触发爆炸杀鱼 + 爆奖红包,完整死亡流程
/// 烈焰风暴 Boss(精简版:只根据服务端 param 判定死亡/未死亡)。
///
/// ⭐ 第一次死亡时不从鱼列表删除 Boss,等第二次死亡爆奖流程结束后,
/// 由 LieYanFengBaoEvent 通知 Boss 回收。
/// param: { "isKill": bool, "beishu": int, "fishId": "...", "animId": int }
/// animId==1 / isKill=false → 未死亡:炸一下 + bjEndUI,Boss 不消失,爆奖结束恢复游动
/// animId>=2 / isKill=true → 死亡:炸一下 + bjEndUI,Boss 消失
///
/// 无死鱼、无红包、无中间过程。
/// </summary>
public class LieYanFengBao_BOSS : MonsterControl_BossBase
{
[Header("两阶段死亡")]
[Tooltip("第一阶段死亡后,自动触发第二阶段的延迟(秒)")]
public float secondDeathDelay = 1.5f;
[Tooltip("第一阶段显示的 bjEndUI 预制体")]
public BJEndUI firstDeathBjEndUI;
[Header("服务端参数解析")]
[Tooltip("是否从 param 解析 isKill/animId(关闭则每次死亡都按死亡处理)")]
public bool useServerParam = true;
/// <summary>爆奖事件引用(死亡时赋值,供外部检查爆奖是否结束)</summary>
/// <summary>爆奖事件引用</summary>
[System.NonSerialized]
public LieYanFengBaoEvent currEvent;
/// <summary>第一次死亡已完成</summary>
private bool _firstDeathDone = false;
/// <summary>缓存第一次死亡的击杀数据(供第二阶段使用)</summary>
private RoomKillNotice _cachedKillNotice;
/// <summary>当前死亡次数(仅日志用)</summary>
private int _deathCount = 0;
/// <summary>缓存死亡位置(删除 Boss 后 transform 不可靠)</summary>
private Vector3 _diePos;
private bool _diePosCached = false;
/// <summary>Boss 是否已从鱼列表回收(防重复回收)</summary>
private bool _removed = false;
/// <summary>爆奖事件是否已 Init(决定特效实例由谁回收)</summary>
private bool _awardInitCalled = false;
public override void OnEnable()
{
base.OnEnable();
_firstDeathDone = false;
_cachedKillNotice = null;
_deathCount = 0;
_diePosCached = false;
_removed = false;
_awardInitCalled = false;
currEvent = null;
}
public override void DieFish(RoomKillNotice obj = null)
{
if (!_firstDeathDone)
_deathCount++;
// ===== 解析服务端 param:animId 优先于 isKill =====
bool isKill;
int beishu;
if (useServerParam && obj?.param != null)
{
// ===== 第一次死亡:只显示 bjEndUI,Boss 不消失 =====
_firstDeathDone = true;
_cachedKillNotice = obj;
Debug.Log($"[LieYanFengBao] 第一次死亡:显示 bjEndUI,Boss 保留");
// 显示 bjEndUI
ShowFirstDeathBjEndUI(obj);
// ⭐ 不设置 isDieFish,不调用 base.DieFish,不从鱼列表删除
// 把 action_effect_DieAward 设为空操作(因为 CreateFishManager 仍会创建 effect_DieAward)
action_effect_DieAward = (o) =>
var p = BossKillParamParser.ParseMultiDeath(obj.param);
if (p != null)
{
Debug.Log("[LieYanFengBao] 第一次死亡:跳过爆奖特效初始化");
// 销毁 CreateFishManager 创建的空 effect(它没有被初始化)
if (o != null) Destroy(o);
};
// 延迟触发第二次死亡
StartCoroutine(DelayedSecondDeath());
isKill = p.isKill;
beishu = p.beishu > 0 ? p.beishu : (obj.beishu > 0 ? (int)obj.beishu : 1);
if (p.animId >= 1)
isKill = p.animId >= 2;
Debug.Log($"[LieYanFengBao] DieFish 第{_deathCount}次(服务端) animId={p.animId} isKill={isKill} beishu={beishu} gold={obj.gold}");
}
else
{
// param 解析失败:按死亡处理
isKill = true;
beishu = obj.beishu > 0 ? (int)obj.beishu : 1;
Debug.LogWarning($"[LieYanFengBao] param 解析失败,按死亡处理 beishu={beishu}");
}
}
else
{
// ===== 第二次死亡:完整爆炸 + 爆奖流程 =====
// 老消息无 param:按死亡处理
isKill = true;
beishu = obj?.beishu > 0 ? (int)obj.beishu : 1;
Debug.Log($"[LieYanFengBao] DieFish 第{_deathCount}次(无param,按死亡) beishu={beishu}");
}
// 缓存死亡位置(供爆奖特效定位)
_diePos = transform.position;
_diePosCached = true;
// 炸一下 + bjEndUI(爆奖特效初始化回调,死亡/未死亡都播)
action_effect_DieAward = (o) => InitAwardEffect(o, obj, beishu);
if (isKill)
{
// ===== 死亡:Boss 消失 =====
isDieFish = true;
if (obj != null)
poolNum = (int)obj.gold;
Debug.Log($"[LieYanFengBao] 第二次死亡:触发完整爆炸 + 爆奖");
action_effect_DieAward = (o) =>
{
Vector3 diePos = transform.position;
Debug.Log($"[LieYanFengBao] action_effect_DieAward(第二阶段): 鱼位置={diePos}");
if (_cachedKillNotice == null) return;
foreach (var item in CreateFishManager.Instance.currGameType.list_Sits)
{
if (item.user == _cachedKillNotice.userId)
{
var v = o.GetComponent<BJEventBase>();
var evt = v as LieYanFengBaoEvent;
if (evt != null)
{
evt.explosionCenter = diePos;
evt.bossCtrl = this;
currEvent = evt;
Debug.Log($"[LieYanFengBao] 设置爆炸中心(死亡位置)={diePos}");
}
v.Init(
_cachedKillNotice.gold,
item.posID,
_cachedKillNotice.skillsGold,
_cachedKillNotice.fishScore,
_cachedKillNotice.beishu,
JiaFen,
() => { v.obj = _cachedKillNotice.param; }
);
}
}
};
StartCoroutine(RemoveBossNextFrame());
}
// 未死亡:不删除,等爆奖结束 OnAwardFinished 恢复游动
}
/// <summary>第一次死亡:显示 bjEndUI(只显示倍数+分数,不触发爆炸)</summary>
private void ShowFirstDeathBjEndUI(RoomKillNotice obj)
/// <summary>初始化爆奖事件(炸一下 + bjEndUI)</summary>
private void InitAwardEffect(GameObject o, RoomKillNotice obj, int beishu)
{
if (firstDeathBjEndUI == null || obj == null) return;
Vector3 diePos = _diePosCached ? _diePos : transform.position;
if (obj == null) return;
// 计算位置(座位上方)
int posID = 0;
Vector3 seatPos = transform.position;
foreach (var item in CreateFishManager.Instance.currGameType.list_Sits)
{
if (item.user == obj.userId)
{
posID = item.posID;
if (item.currentTurret != null)
seatPos = item.currentTurret.transform.position;
else
seatPos = item.transform.position;
break;
}
}
_awardInitCalled = true;
float y = 150f; // 默认 bjEndUIOffsetY
if (posID == 2 || posID == 3) y *= -1f;
Vector3 uiPos = seatPos + Vector3.up * y;
bool isMine = obj.userId == GameManager.Instance.user.id;
var endUI = Instantiate(firstDeathBjEndUI, uiPos, Quaternion.identity, CreateFishManager.Instance.bjEffectRoot);
endUI.Init(obj.beishu, (int)obj.gold, isMine);
Debug.Log($"[LieYanFengBao] 第一次死亡: bjEndUI 显示 倍数={obj.beishu} 分数={obj.gold} isMine={isMine}");
}
/// <summary>延迟触发第二次死亡</summary>
private System.Collections.IEnumerator DelayedSecondDeath()
{
yield return new WaitForSeconds(secondDeathDelay);
if (_cachedKillNotice == null) yield break;
// ===== 第二阶段:手动创建 effect_DieAward 并触发完整爆炸+爆奖流程 =====
isDieFish = true;
poolNum = (int)_cachedKillNotice.gold;
Debug.Log("[LieYanFengBao] 触发第二次死亡流程");
// 1. 创建爆奖特效(通过 EffectPool)
var cfm = CreateFishManager.Instance;
var awardPrefab = effect_DieAward != null ? effect_DieAward : (cfm != null ? cfm.dieFXPrefabAwardTmp : null);
if (awardPrefab == null)
{
Debug.LogWarning("[LieYanFengBao] effect_DieAward 预制体为 null,跳过第二次死亡");
yield break;
}
var effectObj = EffectPool.Instance.Get(
awardPrefab,
transform.position, Quaternion.identity,
cfm != null ? cfm.bjEffectRoot : transform,
autoReturn: false);
// 2. 初始化爆奖事件
foreach (var item in CreateFishManager.Instance.currGameType.list_Sits)
{
if (item.user == _cachedKillNotice.userId)
{
var v = effectObj.GetComponent<BJEventBase>();
var v = o.GetComponent<BJEventBase>();
var evt = v as LieYanFengBaoEvent;
if (evt != null)
{
evt.explosionCenter = transform.position;
evt.explosionCenter = diePos;
evt.bossCtrl = this;
currEvent = evt;
Debug.Log($"[LieYanFengBao] 设置爆炸中心={transform.position}");
}
v.Init(
_cachedKillNotice.gold,
obj.gold,
item.posID,
_cachedKillNotice.skillsGold,
_cachedKillNotice.fishScore,
_cachedKillNotice.beishu,
obj.skillsGold,
obj.fishScore,
beishu,
JiaFen,
() => { v.obj = _cachedKillNotice.param; }
() => { v.obj = obj.param; }
);
break;
}
}
}
/// <summary>
/// 下一帧删除 Boss:Ws_DieFish 在 DieFish 返回后同帧会实例化爆奖特效并触发回调。
/// 等到下一帧:Boss 被删除;爆奖事件没初始化(座位没找到)则把特效实例回池。
/// </summary>
private System.Collections.IEnumerator RemoveBossNextFrame()
{
yield return null;
if (!_removed)
{
_removed = true;
if (!_awardInitCalled && currEffect_DieAward != null)
{
var effect = currEffect_DieAward;
currEffect_DieAward = null;
EffectPool.Instance.Return(effect);
}
CreateFishManager.Instance.Id_DieFish_NotFX(guid);
Debug.Log($"[LieYanFengBao] Boss 已删除 guid={guid}");
}
}
/// <summary>爆奖流程结束回调(Event 调用):未死亡时恢复游动</summary>
public void OnAwardFinished()
{
if (!isDieFish && isInitialized)
{
ChangeState(CharacterStateType.move);
isMove = true;
Debug.Log("[LieYanFengBao] 未死亡爆奖结束,恢复游动");
}
currEvent = null;
}
private void OnDestroy()
{
StopAllCoroutines();
}
}
@@ -18,6 +18,18 @@ PrefabInstance:
propertyPath: m_Name
value: PW_Enemy_115
objectReference: {fileID: 0}
- target: {fileID: 4896170711943738, guid: f489072a59ee7124cacd935b8dccef7b, type: 3}
propertyPath: m_LocalScale.x
value: -5
objectReference: {fileID: 0}
- target: {fileID: 4896170711943738, guid: f489072a59ee7124cacd935b8dccef7b, type: 3}
propertyPath: m_LocalScale.y
value: -5
objectReference: {fileID: 0}
- target: {fileID: 4896170711943738, guid: f489072a59ee7124cacd935b8dccef7b, type: 3}
propertyPath: m_LocalScale.z
value: -5
objectReference: {fileID: 0}
- target: {fileID: 4896170711943738, guid: f489072a59ee7124cacd935b8dccef7b, type: 3}
propertyPath: m_LocalPosition.x
value: 2.54
@@ -152,3 +164,5 @@ MonoBehaviour:
v3: {x: 0, y: 0, z: 0}
isLocalCoin: 0
killerSitPos: -1
secondDeathDelay: 1.5
firstDeathBjEndUI: {fileID: 0}
File diff suppressed because it is too large Load Diff