1
This commit is contained in:
@@ -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: []
|
||||
|
||||
@@ -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;
|
||||
|
||||
+1
-1
@@ -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
Reference in New Issue
Block a user