This commit is contained in:
2026-07-30 12:54:22 +08:00
parent 523dc168c9
commit b08e37baa0
@@ -1370,32 +1370,44 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
{
Vector2 startPos = sit.GetBulletStartPos();
// ⭐ 三发 + 锁定 + 有多目标:每发子弹瞄准不同的目标
if (isSanShe && isLock && fireTargetMonsterIDs != null && fireTargetMonsterIDs.Count > 0)
// ⭐ 三发 + 锁定:每发子弹优先瞄准对应目标,目标不足或失效则按默认角度发射
// 必须保证三发子弹都创建,否则金币消耗和后端对不上
if (isSanShe && isLock)
{
for (int i = 0; i < 3 && i < fireTargetMonsterIDs.Count; i++)
// 三发默认角度(无目标时用):左 -20,中 0,右 +20
float[] defaultAngles = { angle - 20, angle, angle + 20 };
for (int i = 0; i < 3; i++)
{
// 按 GUID 查找目标
string bulletId = i < bullitIDs.Count ? bullitIDs[i] : bullitIDs[0];
MonsterContral targetMonster = null;
Transform targetHitPos = null;
if (CreateFishManager.Instance.fishDatas_hashCodekey.TryGetValue(fireTargetMonsterIDs[i], out var m)
&& m != null && m.gameObject.activeInHierarchy)
// 尝试按 GUID 查找目标
if (fireTargetMonsterIDs != null && i < fireTargetMonsterIDs.Count)
{
targetMonster = m;
// ⭐ 优先用 lockPoint(锁定锚点),其次 collider,兜底 transform
targetHitPos = ResolveLockTransform(m);
if (CreateFishManager.Instance.fishDatas_hashCodekey.TryGetValue(fireTargetMonsterIDs[i], out var m)
&& m != null && m.gameObject.activeInHierarchy
&& IsFishPathLockable(m))
{
targetMonster = m;
targetHitPos = ResolveLockTransform(m);
}
}
if (targetMonster != null)
{
// 计算朝目标的角度
// 朝目标发射
Vector3 targetWorldPos = targetHitPos.position;
Vector2 dir = ((Vector2)targetWorldPos - startPos).normalized;
float targetAngle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg - 90f;
string bulletId = i < bullitIDs.Count ? bullitIDs[i] : bullitIDs[0];
CreateBullet(sit, startPos, targetAngle, isDouble, true, bulletId, targetMonster, targetHitPos);
}
else
{
// 目标不足或失效 → 按默认角度发射(不锁定)
CreateBullet(sit, startPos, defaultAngles[i], isDouble, isLock, bulletId);
}
}
}
else if (isSanShe)
@@ -1603,9 +1615,10 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
if (CreateFishManager.Instance == null) return result;
// ① 主锁目标排第一(打哪锁哪)
// ① 主锁目标排第一(打哪锁哪)—— 必须也满足路径可锁定,否则三发列表会被它污染
if (currSitData.isLock && currSitData.monCotl_Lock != null &&
currSitData.monCotl_Lock.gameObject.activeInHierarchy)
currSitData.monCotl_Lock.gameObject.activeInHierarchy &&
IsFishPathLockable(currSitData.monCotl_Lock))
{
Transform pos = currSitData.monCotl_Lock_Position != null && currSitData.monCotl_Lock_Position.gameObject.activeInHierarchy
? currSitData.monCotl_Lock_Position
@@ -1616,12 +1629,15 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
}
// ② 按优先级从分类字典补满剩余位置
// ⭐ 修复:之前漏了 fishDatas_hashCodekey_Small(普通鱼),
// 导致场上只有普通鱼时三发只找到1个目标
var dicts = new Dictionary<string, MonsterContral>[]
{
CreateFishManager.Instance.fishDatas_hashCodekey_TS_Boss,
CreateFishManager.Instance.fishDatas_hashCodekey_Boss,
CreateFishManager.Instance.fishDatas_hashCodekey_TS,
CreateFishManager.Instance.fishDatas_hashCodekey_HJ,
CreateFishManager.Instance.fishDatas_hashCodekey_Small,
};
foreach (var dict in dicts)
@@ -1745,12 +1761,16 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
UpdateSingleLockFX(sit, sit.monCotl_Lock, sit.monCotl_Lock_Position, sit.lockFX);
// 更新三发锁定额外图标
for (int i = 0; i < sit.lockFX_Triple.Count && i < sit.tripleLockTargets.Count; i++)
// ⭐ tripleLockTargets[0] 是主目标(已在主 lockFX 显示),
// lockFX_Triple[0] 应对应 tripleLockTargets[1],以此类推
for (int i = 0; i < sit.lockFX_Triple.Count; i++)
{
int targetIdx = i + 1; // 跳过索引0(主目标)
if (targetIdx >= sit.tripleLockTargets.Count) break;
var icon = sit.lockFX_Triple[i];
var monster = sit.tripleLockTargets[i];
var hitPos = sit.tripleLockPositions[i];
if (icon == null || monster == null || hitPos == null) continue;
var monster = sit.tripleLockTargets[targetIdx];
var hitPos = sit.tripleLockPositions[targetIdx];
if (icon == null || monster == null) continue;
UpdateSingleLockFX(sit, monster, hitPos, icon);
}
}
@@ -1787,8 +1807,13 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
var monster = currSitData.monCotl_Lock;
// 目标无效:被对象池回收 / 不激活 / 被销毁
if (monster == null || !monster.gameObject.activeInHierarchy)
// ⭐ 目标无效判定:被回收/销毁 OR 路径离场(progress > 0.8)
// 离场的鱼仍 active,但不应该继续锁定
bool mainInvalid = monster == null
|| !monster.gameObject.activeInHierarchy
|| !IsFishPathLockable(monster);
if (mainInvalid)
{
currSitData.ClearLock(); // 清除锁定
SyncTurretState(TurretState.Idle);
@@ -1797,6 +1822,29 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
// ⭐⭐⭐ 关键:怪死了 → 动画回到 Idle ⭐⭐⭐
currSitData.ChangeState(TurretState.Idle);
SyncTurretState(TurretState.Idle);
return;
}
// ⭐ 检查三发锁定目标:移除已死亡或已离场的额外目标
if (currSitData.tripleLockTargets.Count > 0)
{
bool changed = false;
for (int i = currSitData.tripleLockTargets.Count - 1; i >= 1; i--)
{
var t = currSitData.tripleLockTargets[i];
// 失效判定:被回收/销毁 OR 路径离场
if (t == null || !t.gameObject.activeInHierarchy || !IsFishPathLockable(t))
{
currSitData.tripleLockTargets.RemoveAt(i);
currSitData.tripleLockPositions.RemoveAt(i);
changed = true;
}
}
// 有目标失效 → 清空三发列表,让 RefreshTripleLockIcons 重新找满3个
if (changed)
{
currSitData.HideTripleLockIcons();
}
}
}
@@ -1812,10 +1860,11 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
// 激活后,当锁定的鱼死亡,自动转换到下一个目标
if (!_autoLockActivated) return;
// 已经有锁定目标并且还活着,就不重复找
// 已经有锁定目标并且还活着且未离场,就不重复找
if (currSitData.isLock &&
currSitData.monCotl_Lock != null &&
currSitData.monCotl_Lock.gameObject.activeInHierarchy)
currSitData.monCotl_Lock.gameObject.activeInHierarchy &&
IsFishPathLockable(currSitData.monCotl_Lock))
{
return;
}