diff --git a/Assets/Art/FengLei/PaoTai/DaQiao/shot_14053_0_kb_effect.prefab b/Assets/Art/FengLei/PaoTai/DaQiao/shot_14053_0_kb_effect.prefab
index 212cf4e15..8c0415b68 100644
--- a/Assets/Art/FengLei/PaoTai/DaQiao/shot_14053_0_kb_effect.prefab
+++ b/Assets/Art/FengLei/PaoTai/DaQiao/shot_14053_0_kb_effect.prefab
@@ -28292,7 +28292,7 @@ Transform:
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
+ m_LocalScale: {x: 1, y: 1, z: 21.722227}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 454631387865839470}
@@ -44926,6 +44926,11 @@ PrefabInstance:
propertyPath: m_Layer
value: 7
objectReference: {fileID: 0}
+ - target: {fileID: 5897679978818280078, guid: f968506c49fa41842bb684eb1e7016ac,
+ type: 3}
+ propertyPath: m_IsActive
+ value: 1
+ objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
diff --git a/Assets/Art/JABY/Fish/JiGuangControl.cs b/Assets/Art/JABY/Fish/JiGuangControl.cs
index e1a4ce8a1..b49f91ef6 100644
--- a/Assets/Art/JABY/Fish/JiGuangControl.cs
+++ b/Assets/Art/JABY/Fish/JiGuangControl.cs
@@ -1,56 +1,98 @@
using System.Collections.Generic;
using UnityEngine;
-public class JiGuangControl : MonoBehaviour
+///
+/// 激光静态工具类:激光实例的创建/朝向/长度计算,不依赖组件实例。
+/// 调用方自行持有激光实例列表(fxList)、基准缩放(fxBaseScale)和长度校正值(lengthCorrect),
+/// 创建后每帧调用 JiGuangDirection/JiGuangLength 刷新。
+/// 起点支持 Transform / Vector3 两种;Z 轴重载:
+/// - 不带 z 参数 → 直接读取起点/目标对象自身的 Z
+/// - 带 z 参数 → 强制起点和终点都使用指定 Z(如战神激光统一压到 -50 显示层)
+///
+public static class JiGuangControl
{
- [Header("起点")]
- public Transform posShanDianYu;
+ // ==================== 创建 ====================
- [Header("激光预制体")]
- public GameObject jiGuangPrefab;
-
- [Header("目标列表")]
- public List posTargets = new List();
- public float lengthCorrect=1f;//用于校正激光的长度,不同的激光设置不同的值
-
- List _fxList = new List();
- private Vector3 fxBaseScale;
-
- void Start()
+ /// 按目标数量创建激光实例(克隆预制体,挂到 parent 下)。生成位置读取起点对象自身的 Z
+ public static void JiGuangCreate(GameObject prefab, Transform start, List targets, List fxList, Transform parent = null)
{
- JiGuangCreate(jiGuangPrefab, posShanDianYu, posTargets, _fxList);
- fxBaseScale = jiGuangPrefab.transform.localScale;
+ if (start == null) return;
+ JiGuangCreateCore(prefab, start.position, targets, fxList, parent, null);
}
- void Update()
+ /// 同上,但生成位置强制使用指定 Z
+ public static void JiGuangCreate(GameObject prefab, Transform start, List targets, List fxList, Transform parent, float z)
{
- JiGuangDirection(posShanDianYu, posTargets, _fxList);
- JiGuangLength(posShanDianYu, posTargets, _fxList, fxBaseScale);
+ if (start == null) return;
+ JiGuangCreateCore(prefab, start.position, targets, fxList, parent, z);
}
- void JiGuangCreate(GameObject prefab, Transform start, List targets, List fxList)
+ /// 起点直接给坐标(如战神激光的动态炮口位置)。生成位置读取 startPos 自身的 Z
+ public static void JiGuangCreate(GameObject prefab, Vector3 startPos, List targets, List fxList, Transform parent = null)
{
- if (prefab == null || start == null || targets == null || fxList == null)
+ JiGuangCreateCore(prefab, startPos, targets, fxList, parent, null);
+ }
+
+ /// 同上,但生成位置强制使用指定 Z
+ public static void JiGuangCreate(GameObject prefab, Vector3 startPos, List targets, List fxList, Transform parent, float z)
+ {
+ JiGuangCreateCore(prefab, startPos, targets, fxList, parent, z);
+ }
+
+ private static void JiGuangCreateCore(GameObject prefab, Vector3 startPos, List targets, List fxList, Transform parent, float? forcedZ)
+ {
+ if (prefab == null || targets == null || fxList == null)
return;
for (int i = 0; i < fxList.Count; i++)
if (fxList[i] != null)
- Destroy(fxList[i].gameObject);
+ Object.Destroy(fxList[i].gameObject);
fxList.Clear();
for (int i = 0; i < targets.Count; i++)
{
if (targets[i] == null) continue;
- GameObject go = Instantiate(prefab, start.position, Quaternion.identity, transform);
+ Vector3 spawnPos = startPos;
+ if (forcedZ.HasValue)
+ spawnPos.z = forcedZ.Value;
+ GameObject go = Object.Instantiate(prefab, spawnPos, Quaternion.identity, parent);
go.name = prefab.name + "_" + i;
fxList.Add(go.transform);
}
}
- void JiGuangDirection(Transform start, List targets, List fxList)
+ // ==================== 朝向 ====================
+
+ /// 刷新激光朝向:直接读取起点/目标对象自身的 Z
+ public static void JiGuangDirection(Transform start, List targets, List fxList)
{
- if (start == null || targets == null || fxList == null || fxList.Count == 0)
+ if (start == null) return;
+ JiGuangDirectionCore(start.position, targets, fxList, null);
+ }
+
+ /// 刷新激光朝向:起点和终点强制使用指定 Z(同层)
+ public static void JiGuangDirection(Transform start, List targets, List fxList, float z)
+ {
+ if (start == null) return;
+ JiGuangDirectionCore(start.position, targets, fxList, z);
+ }
+
+ /// 刷新激光朝向(起点为坐标):直接使用 startPos 自身的 Z
+ public static void JiGuangDirection(Vector3 startPos, List targets, List fxList)
+ {
+ JiGuangDirectionCore(startPos, targets, fxList, null);
+ }
+
+ /// 刷新激光朝向(起点为坐标):起点和终点强制使用指定 Z(同层)
+ public static void JiGuangDirection(Vector3 startPos, List targets, List fxList, float z)
+ {
+ JiGuangDirectionCore(startPos, targets, fxList, z);
+ }
+
+ private static void JiGuangDirectionCore(Vector3 startPos, List targets, List fxList, float? forcedZ)
+ {
+ if (targets == null || fxList == null || fxList.Count == 0)
return;
int fxIndex = 0;
@@ -59,8 +101,13 @@ public class JiGuangControl : MonoBehaviour
if (targets[i] == null) continue;
if (fxIndex >= fxList.Count) break;
- Vector3 dir = targets[i].position - start.position;
- dir.z = 0f;
+ Vector3 endPos = targets[i].position;
+ if (forcedZ.HasValue)
+ {
+ startPos.z = forcedZ.Value;
+ endPos.z = forcedZ.Value;
+ }
+ Vector3 dir = endPos - startPos;
if (dir.sqrMagnitude > 0.0001f)
fxList[fxIndex].rotation = Quaternion.LookRotation(dir);
@@ -69,9 +116,37 @@ public class JiGuangControl : MonoBehaviour
}
}
- void JiGuangLength(Transform start, List targets, List fxList, Vector3 fxBaseScale)
+ // ==================== 长度 ====================
+
+ /// 刷新激光长度(按基准缩放拉伸 Z 轴):直接读取起点/目标对象自身的 Z
+ public static void JiGuangLength(Transform start, List targets, List fxList, Vector3 fxBaseScale, float lengthCorrect = 1f)
{
- if (start == null || targets == null || fxList == null || fxList.Count == 0)
+ if (start == null) return;
+ JiGuangLengthCore(start.position, targets, fxList, fxBaseScale, lengthCorrect, null);
+ }
+
+ /// 刷新激光长度:起点和终点强制使用指定 Z(同层)
+ public static void JiGuangLength(Transform start, List targets, List fxList, Vector3 fxBaseScale, float lengthCorrect, float z)
+ {
+ if (start == null) return;
+ JiGuangLengthCore(start.position, targets, fxList, fxBaseScale, lengthCorrect, z);
+ }
+
+ /// 刷新激光长度(起点为坐标):直接使用 startPos 自身的 Z
+ public static void JiGuangLength(Vector3 startPos, List targets, List fxList, Vector3 fxBaseScale, float lengthCorrect = 1f)
+ {
+ JiGuangLengthCore(startPos, targets, fxList, fxBaseScale, lengthCorrect, null);
+ }
+
+ /// 刷新激光长度(起点为坐标):起点和终点强制使用指定 Z(同层)
+ public static void JiGuangLength(Vector3 startPos, List targets, List fxList, Vector3 fxBaseScale, float lengthCorrect, float z)
+ {
+ JiGuangLengthCore(startPos, targets, fxList, fxBaseScale, lengthCorrect, z);
+ }
+
+ private static void JiGuangLengthCore(Vector3 startPos, List targets, List fxList, Vector3 fxBaseScale, float lengthCorrect, float? forcedZ)
+ {
+ if (targets == null || fxList == null || fxList.Count == 0)
return;
int fxIndex = 0;
@@ -80,11 +155,15 @@ public class JiGuangControl : MonoBehaviour
if (targets[i] == null) continue;
if (fxIndex >= fxList.Count) break;
- Vector3 delta = targets[i].position - start.position;
- delta.z = 0f;
- float distance = delta.magnitude;
+ Vector3 endPos = targets[i].position;
+ if (forcedZ.HasValue)
+ {
+ startPos.z = forcedZ.Value;
+ endPos.z = forcedZ.Value;
+ }
+ float distance = (endPos - startPos).magnitude;
Vector3 scale = fxBaseScale;
- scale.z = distance * fxBaseScale.z * lengthCorrect;
+ scale.z = distance * fxBaseScale.z * lengthCorrect;
fxList[fxIndex].localScale = scale;
fxIndex++;
diff --git a/Assets/Art/JABY/ResJABY/assetspackage/fishes/fish_4003/prefab/fx_fish_4003_die_lighting_01_zise.prefab b/Assets/Art/JABY/ResJABY/assetspackage/fishes/fish_4003/prefab/fx_fish_4003_die_lighting_01_zise.prefab
index 18ad66ac1..a384e3b8e 100644
--- a/Assets/Art/JABY/ResJABY/assetspackage/fishes/fish_4003/prefab/fx_fish_4003_die_lighting_01_zise.prefab
+++ b/Assets/Art/JABY/ResJABY/assetspackage/fishes/fish_4003/prefab/fx_fish_4003_die_lighting_01_zise.prefab
@@ -9,7 +9,7 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 4985305603660343}
- m_Layer: 13
+ m_Layer: 7
m_Name: GameObject
m_TagString: Untagged
m_Icon: {fileID: 0}
@@ -43,7 +43,7 @@ GameObject:
- component: {fileID: 198884547391421755}
- component: {fileID: 199099118695303065}
- component: {fileID: 210061268324235159}
- m_Layer: 13
+ m_Layer: 7
m_Name: fx_fish_4003_die_lighting_01_zise
m_TagString: Untagged
m_Icon: {fileID: 0}
@@ -2348,7 +2348,7 @@ GameObject:
- component: {fileID: 4589667821646929}
- component: {fileID: 198372920208702427}
- component: {fileID: 199025901758691103}
- m_Layer: 13
+ m_Layer: 7
m_Name: lighting_01
m_TagString: Untagged
m_Icon: {fileID: 0}
@@ -4680,7 +4680,7 @@ GameObject:
- component: {fileID: 4587765826080250}
- component: {fileID: 198709867586078768}
- component: {fileID: 199044625135789424}
- m_Layer: 13
+ m_Layer: 7
m_Name: fx_fish_4003_die_lighting_01
m_TagString: Untagged
m_Icon: {fileID: 0}
diff --git a/Assets/MyGame/Scripts/Turret/SitPosData.cs b/Assets/MyGame/Scripts/Turret/SitPosData.cs
index 6761e7e34..eaae714af 100644
--- a/Assets/MyGame/Scripts/Turret/SitPosData.cs
+++ b/Assets/MyGame/Scripts/Turret/SitPosData.cs
@@ -88,10 +88,16 @@ public class SitPosData : MonoBehaviour
public TurretData currentZhanShenData;
// -------------------------
- // 战神激光(锁定时显示)
+ // 战神激光(锁定时显示):两种形态
+ // - laserPrefab 非空 → 预制体形态:JiGuangControl 工具类驱动(克隆激光预制体,方向/长度每帧刷新)
+ // - laserPrefab 为空 → LineRenderer 兜底形态:直接新建 GameObject + LineRenderer
// -------------------------
- /// 战神激光对象列表(世界空间 LineRenderer,起点=子弹创建位置,终点=锁定鱼的位置)。三发锁定=3条
+ /// LineRenderer 形态激光列表(起点=子弹创建位置,终点=锁定鱼的位置)。三发锁定=3条
private readonly List _zhanShenLasers = new List();
+ /// 预制体形态激光实例列表(世界空间,由 JiGuangControl.JiGuangCreate 按目标数量重建)
+ private readonly List _laserFx = new List();
+ /// 预制体形态激光的基准缩放(重建时取自 laserPrefab.transform.localScale)
+ private Vector3 _laserFxBaseScale = Vector3.one;
// -------------------------
// XJMH 炮台列表(星际迷航专用)
@@ -234,8 +240,9 @@ public class SitPosData : MonoBehaviour
// ==================== 战神激光(锁定时显示) ====================
///
- /// 战神锁定时显示激光(LineRenderer):起点=创建子弹的位置(GetBulletStartPos),终点=锁定鱼的位置。
- /// ⭐ 一个锁定点一条线:单发锁定=1条,三发锁定=3条(主目标+2个三发目标)。
+ /// 战神锁定时显示激光:起点=创建子弹的位置(GetBulletStartPos),终点=锁定鱼的位置,Z 统一压到 -50 显示层。
+ /// ⭐ 一个锁定点一条激光:单发锁定=1条,三发锁定=3条(主目标+2个三发目标)。
+ /// ⭐ 两种形态:laserPrefab 非空 → 预制体形态(JiGuangControl 工具类);为空 → LineRenderer 兜底形态。
/// ⭐ 只是视觉表现:打中鱼仍按正常攻击频率由子弹完成(HandleAutoFire 以 attackTime 发射锁定子弹)。
/// 普通炮台没有此效果(currentZhanShenData 为 null 时不显示)。
///
@@ -248,7 +255,7 @@ public class SitPosData : MonoBehaviour
if (monCotl_Lock_Position != null && monCotl_Lock_Position.gameObject.activeInHierarchy)
_laserTargets.Add(monCotl_Lock_Position);
- // 三发锁定:每个有效目标一条线(主目标已在上面,这里只补额外的)
+ // 三发锁定:每个有效目标一条激光(主目标已在上面,这里只补额外的)
if (tripleLockTargets.Count > 0)
{
for (int i = 0; i < tripleLockTargets.Count && i < tripleLockPositions.Count; i++)
@@ -266,14 +273,68 @@ public class SitPosData : MonoBehaviour
// 没有锁定点:隐藏所有激光
if (_laserTargets.Count == 0)
{
- for (int i = 0; i < _zhanShenLasers.Count; i++)
- {
- if (_zhanShenLasers[i] != null && _zhanShenLasers[i].gameObject.activeSelf)
- _zhanShenLasers[i].gameObject.SetActive(false);
- }
+ HideZhanShenLasers();
return;
}
+ // 按配置走对应形态:laserPrefab 非空=预制体形态,为空=LineRenderer 兜底
+ if (currentZhanShenData.laserPrefab != null)
+ UpdateZhanShenLaserFx();
+ else
+ UpdateZhanShenLaserLine();
+ }
+
+ /// 隐藏全部战神激光(两种形态都处理)
+ private void HideZhanShenLasers()
+ {
+ for (int i = 0; i < _zhanShenLasers.Count; i++)
+ {
+ if (_zhanShenLasers[i] != null && _zhanShenLasers[i].gameObject.activeSelf)
+ _zhanShenLasers[i].gameObject.SetActive(false);
+ }
+ for (int i = 0; i < _laserFx.Count; i++)
+ {
+ if (_laserFx[i] != null && _laserFx[i].gameObject.activeSelf)
+ _laserFx[i].gameObject.SetActive(false);
+ }
+ }
+
+ ///
+ /// 预制体形态(laserPrefab 非空):JiGuangControl 工具类驱动。
+ /// 目标数量变化时全量重建(JiGuangCreate),每帧刷新位置/朝向/长度(JiGuangDirection/JiGuangLength,Z 强制 -50)。
+ ///
+ private void UpdateZhanShenLaserFx()
+ {
+ var zsData = currentZhanShenData;
+
+ // 起点:创建子弹的位置(Z=-50,战神激光显示层,和 FireBullet 的 startPos 同源仅 Z 不同)
+ Vector3 startPos = GetBulletStartPos();
+ startPos.z = -50f;
+
+ // 目标数量变化时全量重建(锁定建立/解除/三发目标增减时触发),并刷新基准缩放
+ if (_laserFx.Count != _laserTargets.Count)
+ {
+ _laserFxBaseScale = zsData.laserPrefab.transform.localScale;
+ JiGuangControl.JiGuangCreate(zsData.laserPrefab, startPos, _laserTargets, _laserFx, null, -50f);
+ }
+
+ // 炮口随炮台旋转会移动,位置需每帧同步;隐藏中的重新激活
+ for (int i = 0; i < _laserFx.Count; i++)
+ {
+ if (_laserFx[i] == null) continue;
+ if (!_laserFx[i].gameObject.activeSelf)
+ _laserFx[i].gameObject.SetActive(true);
+ _laserFx[i].position = startPos;
+ }
+
+ // 朝向 + 长度(指定 Z=-50 的重载:起终点同层)
+ JiGuangControl.JiGuangDirection(startPos, _laserTargets, _laserFx, -50f);
+ JiGuangControl.JiGuangLength(startPos, _laserTargets, _laserFx, _laserFxBaseScale, zsData.laserLengthCorrect, -50f);
+ }
+
+ /// LineRenderer 兜底形态(laserPrefab 为空):按需创建、多余的隐藏
+ private void UpdateZhanShenLaserLine()
+ {
// 起点:创建子弹的位置(Z=-50,战神激光显示层,和 FireBullet 的 startPos 同源仅 Z 不同)
Vector3 start = GetBulletStartPos();
start.z = -50f;
@@ -303,53 +364,33 @@ public class SitPosData : MonoBehaviour
private readonly List _laserTargets = new List();
///
- /// 创建一条战神激光(第 index 条):
- /// - laserPrefab 非空 → 克隆预制体(LineRenderer 配置以预制体为准);
- /// - laserPrefab 为空 → 直接创建一个新 GameObject 并加上 LineRenderer(用 TurretData 上的宽度/颜色)。
+ /// 创建一条 LineRenderer 形态的战神激光(第 index 条)。
+ /// 仅 laserPrefab 为空时使用:直接创建一个新 GameObject 并加上 LineRenderer(用 TurretData 上的宽度/颜色)。
///
private LineRenderer CreateZhanShenLaser(int index)
{
var zsData = currentZhanShenData;
- GameObject laserGo;
- LineRenderer line;
- if (zsData.laserPrefab != null)
- {
- laserGo = Instantiate(zsData.laserPrefab);
- laserGo.name = $"ZhanShenLaser_{index}";
- line = laserGo.GetComponent();
- if (line == null)
- line = laserGo.AddComponent();
- }
- else
- {
- // ⭐ prefab 为空:直接新建对象 + LineRenderer
- laserGo = new GameObject($"ZhanShenLaser_{index}");
- line = laserGo.AddComponent();
- }
-
- // 公共配置:两个端点
+ GameObject laserGo = new GameObject($"ZhanShenLaser_{index}");
+ LineRenderer line = laserGo.AddComponent();
line.positionCount = Mathf.Max(line.positionCount, 2);
laserGo.transform.SetParent(null); // 世界空间,不随座位/炮台旋转
- if (zsData.laserPrefab == null)
- {
- // 自动创建时应用 TurretData 上的宽度/颜色/材质
- line.startWidth = zsData.laserWidth;
- line.endWidth = zsData.laserWidth;
- line.startColor = zsData.laserColor;
- line.endColor = zsData.laserColor;
- var shader = Shader.Find("Sprites/Default");
- if (shader != null)
- line.material = new Material(shader) { color = Color.white };
- line.useWorldSpace = true;
- }
+ // 应用 TurretData 上的宽度/颜色/材质
+ line.startWidth = zsData.laserWidth;
+ line.endWidth = zsData.laserWidth;
+ line.startColor = zsData.laserColor;
+ line.endColor = zsData.laserColor;
+ var shader = Shader.Find("Sprites/Default");
+ if (shader != null)
+ line.material = new Material(shader) { color = Color.white };
+ line.useWorldSpace = true;
_zhanShenLasers.Add(line);
return line;
}
- /// 销毁所有战神激光对象(清战神/座位禁用时调用)
+ /// 销毁所有战神激光对象(两种形态都清,清战神/座位禁用时调用)
private void DestroyZhanShenLaser()
{
for (int i = 0; i < _zhanShenLasers.Count; i++)
@@ -358,6 +399,13 @@ public class SitPosData : MonoBehaviour
Destroy(_zhanShenLasers[i].gameObject);
}
_zhanShenLasers.Clear();
+
+ for (int i = 0; i < _laserFx.Count; i++)
+ {
+ if (_laserFx[i] != null)
+ Destroy(_laserFx[i].gameObject);
+ }
+ _laserFx.Clear();
}
///
diff --git a/Assets/MyGame/Scripts/Turret/TurretData.cs b/Assets/MyGame/Scripts/Turret/TurretData.cs
index 56a8e62da..dca1f4d17 100644
--- a/Assets/MyGame/Scripts/Turret/TurretData.cs
+++ b/Assets/MyGame/Scripts/Turret/TurretData.cs
@@ -35,12 +35,14 @@ public class TurretData : MonoBehaviour
public GameObject bulletPrefab;
[Header("战神激光(锁定时显示,普通炮台不配置即无此效果)")]
- [Tooltip("激光预制体(带 LineRenderer)。为空时自动创建一个 GameObject 并加 LineRenderer")]
+ [Tooltip("激光预制体。非空=预制体形态(JiGuangControl 工具类驱动);为空=LineRenderer 兜底形态(自动创建)")]
public GameObject laserPrefab;
- [Tooltip("自动创建激光时的线宽")]
+ [Tooltip("LineRenderer 兜底形态的线宽")]
public float laserWidth = 0.3f;
- [Tooltip("自动创建激光时的颜色")]
+ [Tooltip("LineRenderer 兜底形态的颜色")]
public Color laserColor = new Color(1f, 0.3f, 0.3f, 0.9f);
+ [Tooltip("预制体形态激光的长度校正值(不同激光预制体设置不同值)")]
+ public float laserLengthCorrect = 1f;
[Header("UI面板属性")]
[Tooltip("炮台编号,对应 TurretResourcesData.turretNumber")]
diff --git a/Assets/MyGame/aa/Game/FLZY/TSY/ShanDian/ShanDian_DieEvent.cs b/Assets/MyGame/aa/Game/FLZY/TSY/ShanDian/ShanDian_DieEvent.cs
index 90cbd270e..6484861b3 100644
--- a/Assets/MyGame/aa/Game/FLZY/TSY/ShanDian/ShanDian_DieEvent.cs
+++ b/Assets/MyGame/aa/Game/FLZY/TSY/ShanDian/ShanDian_DieEvent.cs
@@ -19,6 +19,10 @@ using UnityEngine;
public class ShanDian_DieEvent : DieEffect_TSY
{
[Header("闪电表现")]
+ [Tooltip("激光预制体(配了则用 JiGuangControl 锁定鱼:激光跟随游动的鱼;不配则走 LineRenderer 折线闪电兜底)")]
+ public GameObject laserPrefab;
+ [Tooltip("激光长度校正值(JiGuangControl.JiGuangLength 用)")]
+ public float laserLengthCorrect = 1f;
[Tooltip("闪电材质(空则自动用 Additive 发光材质,效果更亮更明显)")]
public Material lightningMaterial;
[Tooltip("闪电颜色")]
@@ -54,6 +58,13 @@ public class ShanDian_DieEvent : DieEffect_TSY
[Tooltip("杀鱼的物理层(默认 Fish 层)")]
public LayerMask fishLayer;
+ // 激光锁定实例 / 折线闪电实例(收尾统一清理)
+ private readonly List _laserFx = new List();
+ private readonly List _lightningObjects = new List();
+ private Vector3 _laserFxBaseScale = Vector3.one;
+ // 运行时选鱼中心(供 Gizmos 画圈用)
+ private Vector3 _gizmoCenter;
+
public override void SetCoinCount()
{
}
@@ -67,6 +78,7 @@ public class ShanDian_DieEvent : DieEffect_TSY
{
Vector3 startPos = startPoint != Vector3.zero ? startPoint : transform.position;
startPos.z = 0;
+ _gizmoCenter = startPos;
if (fishLayer.value == 0) fishLayer = LayerMask.GetMask("Fish");
@@ -100,32 +112,54 @@ public class ShanDian_DieEvent : DieEffect_TSY
var fishPositions = new List();
var addedGuids = new HashSet();
- void Collect(float radius)
+ // nearestFirst=true:按离死亡位置的距离升序收集(身边的鱼优先遭殃);false:按物理检测原始顺序(近似随机,全屏补鱼分布更自然)
+ void Collect(float radius, bool nearestFirst, string tag)
{
var hits = Physics2D.OverlapCircleAll(startPos, radius, fishLayer);
+ var candidates = new List>();
+ int noCtrl = 0, skipType = 0, skipDup = 0;
foreach (var hit in hits)
{
- if (fishList.Count >= lightningCount) break; // 收集到目标数量即停
var control = hit.GetComponentInParent();
- if (control == null) continue;
- if (control.fishenum != FishTypeEnum.普通鱼) continue; // ⭐ 只杀小鱼
- if (addedGuids.Contains(control.guid)) continue;
+ if (control == null) { noCtrl++; continue; }
+ if (control.fishenum != FishTypeEnum.普通鱼) { skipType++; continue; } // ⭐ 只杀小鱼
+ if (addedGuids.Contains(control.guid)) { skipDup++; continue; }
+ candidates.Add(new KeyValuePair(
+ Vector2.Distance(startPos, control.transform.position), control));
+ }
+ // 圈内模式:距离排序后从最近的开始取,保证"身边的鱼先被电"
+ if (nearestFirst) candidates.Sort((a, b) => a.Key.CompareTo(b.Key));
+
+ int before = fishList.Count;
+ var picked = new System.Text.StringBuilder();
+ foreach (var kv in candidates)
+ {
+ if (fishList.Count >= lightningCount) break; // 收集到目标数量即停
+ var control = kv.Value;
addedGuids.Add(control.guid);
fishList.Add(control);
var pos = control.transform.position;
pos.z = 0;
fishPositions.Add(pos);
+ picked.Append($" {control.name}(d={kv.Key:F1})");
}
+
+ Debug.Log($"[闪电][{tag}] 中心={startPos} 半径={radius:F1} 命中={hits.Length} " +
+ $"候选={candidates.Count}(无脚本={noCtrl} 非小鱼={skipType} 重复={skipDup}) " +
+ $"选中={fishList.Count - before}{(fishList.Count > before ? ":" + picked : "(无)")}");
}
- // 第一段:圈内优先(身边的先遭殃)
- if (circleRange > 0f) Collect(circleRange);
- // 第二段:圈内不够 → 全屏补足
+ Debug.Log($"[闪电] 选鱼开始 startPoint={startPoint} 本体={transform.position} 中心={startPos} " +
+ $"circleRange={circleRange} fillRange={fillRange} 目标={lightningCount} 层=[{LayerMaskNames(fishLayer)}]");
+
+ // 第一段:圈内按距离取最近的(身边的先遭殃)
+ if (circleRange > 0f) Collect(circleRange, true, "圈内");
+ // 第二段:圈内不够 → 全屏补足(随机分布)
if (fishList.Count < lightningCount)
{
float fill = fillRange > 0f ? fillRange : ScreenDiagonal();
- Collect(fill);
+ Collect(fill, false, "全屏补");
}
int count = Mathf.Min(lightningCount, fishList.Count);
@@ -137,41 +171,71 @@ public class ShanDian_DieEvent : DieEffect_TSY
yield break;
}
- // ====== 2. 随机选 count 条鱼,画闪电 ======
- var lightningObjects = new List();
+ // ====== 2. 按选鱼结果锁定(圈内最近优先 / 全屏补足,激光锁定 / 折线闪电两种表现)======
var explodePoints = new List();
-
- var indices = new List(fishList.Count);
- for (int i = 0; i < fishList.Count; i++) indices.Add(i);
- for (int i = 0; i < count; i++)
- {
- int r = Random.Range(i, indices.Count);
- (indices[i], indices[r]) = (indices[r], indices[i]);
- }
+ var lockedFish = new List();
+ var frozen = new List();
for (int i = 0; i < count; i++)
{
- Vector3 endPos = fishPositions[indices[i]];
- explodePoints.Add(endPos);
+ explodePoints.Add(fishPositions[i]);
+ lockedFish.Add(fishList[i]);
+ frozen.Add(false);
- var lrObj = CreateLightningBolt(startPos, endPos);
- if (lrObj != null) lightningObjects.Add(lrObj);
-
- // 雷电命中点特效:闪电打到鱼身上时在命中点播,强化打击感(没配跳过)
+ // 雷电命中点特效:命中鱼身时播,强化打击感(没配跳过)
if (hitFxPrefab != null)
{
- var hit = Instantiate(hitFxPrefab, endPos, Quaternion.identity, CreateFishManager.Instance.bjEffectRoot);
+ var hit = Instantiate(hitFxPrefab, fishPositions[i], Quaternion.identity, CreateFishManager.Instance.bjEffectRoot);
Destroy(hit, lightningWait);
}
}
- // ====== 3. 等待 → 清除闪电 → 释放爆炸特效 ======
- yield return new WaitForSeconds(lightningWait);
-
- foreach (var obj in lightningObjects)
+ bool useLaser = laserPrefab != null;
+ if (useLaser)
{
- if (obj != null) Destroy(obj);
+ // 激光锁定形态:JiGuangControl 按目标数量创建激光实例,持续期间跟随游动的鱼
+ var laserTargets = new List();
+ for (int i = 0; i < lockedFish.Count; i++) laserTargets.Add(lockedFish[i].transform);
+ _laserFxBaseScale = laserPrefab.transform.localScale;
+ JiGuangControl.JiGuangCreate(laserPrefab, startPos, laserTargets, _laserFx,
+ CreateFishManager.Instance.bjEffectRoot);
+
+ float elapsed = 0f;
+ while (elapsed < lightningWait)
+ {
+ elapsed += Time.deltaTime;
+ // 死鱼冻结爆炸点并隐藏激光;活鱼更新爆炸点 + 刷新激光朝向/长度(跟随移动)
+ for (int i = 0; i < lockedFish.Count; i++)
+ {
+ var ctrl = lockedFish[i];
+ if (!frozen[i] && (ctrl == null || ctrl.isDead || !ctrl.gameObject.activeInHierarchy))
+ {
+ frozen[i] = true;
+ if (i < _laserFx.Count && _laserFx[i] != null) _laserFx[i].gameObject.SetActive(false);
+ }
+ if (frozen[i]) continue;
+ Vector3 p = ctrl.transform.position;
+ p.z = 0;
+ explodePoints[i] = p;
+ }
+ JiGuangControl.JiGuangDirection(startPos, laserTargets, _laserFx);
+ JiGuangControl.JiGuangLength(startPos, laserTargets, _laserFx, _laserFxBaseScale, laserLengthCorrect);
+ yield return null;
+ }
}
+ else
+ {
+ // LineRenderer 折线闪电兜底
+ for (int i = 0; i < lockedFish.Count; i++)
+ {
+ var lrObj = CreateLightningBolt(startPos, explodePoints[i]);
+ if (lrObj != null) _lightningObjects.Add(lrObj);
+ }
+ yield return new WaitForSeconds(lightningWait);
+ }
+
+ // ====== 3. 清除闪电/激光 → 释放爆炸特效 ======
+ ClearLightningFx();
foreach (var ep in explodePoints)
{
@@ -210,6 +274,26 @@ public class ShanDian_DieEvent : DieEffect_TSY
EffectPool.Instance.Return(gameObject);
}
+ ///
+ /// 清理激光/闪电表现(两种形态都清),在爆炸杀鱼前调用。
+ ///
+ private void ClearLightningFx()
+ {
+ // 激光实例:JiGuangCreate 克隆出来的销毁掉
+ for (int i = 0; i < _laserFx.Count; i++)
+ {
+ if (_laserFx[i] != null) Destroy(_laserFx[i].gameObject);
+ }
+ _laserFx.Clear();
+
+ // 折线闪电对象
+ for (int i = 0; i < _lightningObjects.Count; i++)
+ {
+ if (_lightningObjects[i] != null) Destroy(_lightningObjects[i]);
+ }
+ _lightningObjects.Clear();
+ }
+
///
/// 创建一根闪电(主线折线 + 持续抖动闪烁)。
/// ⭐ 效果增强:Additive 发光材质、粗主线、细分段随机折线、持续期间高频闪烁。
@@ -276,21 +360,58 @@ public class ShanDian_DieEvent : DieEffect_TSY
}
}
-/// 屏幕对角线长度:选鱼范围 0=全屏时用它,保证电鳗能劈到全场鱼
+ /// LayerMask 转层名串:日志用,一眼看出 fishLayer 配没配对
+ private static string LayerMaskNames(LayerMask mask)
+ {
+ var sb = new System.Text.StringBuilder();
+ for (int i = 0; i < 32; i++)
+ {
+ if ((mask.value & (1 << i)) == 0) continue;
+ string n = LayerMask.LayerToName(i);
+ if (!string.IsNullOrEmpty(n)) sb.Append(n).Append(",");
+ }
+ return sb.ToString();
+ }
+
+/// 屏幕(z=0 平面)对角线长度:选鱼范围 0=全屏时用它,保证电鳗能劈到全场鱼。兼容透视相机
private float ScreenDiagonal()
{
Camera cam = Camera.main;
- if (cam == null || !cam.orthographic) return 50f;
- float h = cam.orthographicSize * 2f;
+ if (cam == null) return 50f;
+
+ float h;
+ if (cam.orthographic)
+ {
+ h = cam.orthographicSize * 2f;
+ }
+ else
+ {
+ // 透视相机:按相机到 z=0 平面的距离换算该平面的可视高度(鱼都在 z=0)
+ float dist = Mathf.Abs(cam.transform.position.z);
+ h = 2f * dist * Mathf.Tan(cam.fieldOfView * 0.5f * Mathf.Deg2Rad);
+ }
float w = h * cam.aspect;
return Mathf.Sqrt(h * h + w * w);
}
#if UNITY_EDITOR
- private void OnDrawGizmosSelected()
+ // 改用 OnDrawGizmos:不用选中物体就常显(OnDrawGizmosSelected 只有选中才画,物体隐藏/回池时不调用)
+ // 黄圈=circleRange 圈内优先范围;青圈=fillRange 全屏补鱼范围;红圈=explosionRadius 爆炸伤害半径
+ private void OnDrawGizmos()
{
- Gizmos.color = new Color(1, 1, 0, 0.3f);
- Gizmos.DrawWireSphere(transform.position, circleRange > 0f ? circleRange : 5f);
+ Vector3 center = Application.isPlaying && _gizmoCenter != Vector3.zero ? _gizmoCenter : transform.position;
+
+ Gizmos.color = new Color(1f, 1f, 0f, 0.35f);
+ Gizmos.DrawWireSphere(center, circleRange > 0f ? circleRange : 5f);
+
+ if (fillRange > 0f)
+ {
+ Gizmos.color = new Color(0f, 1f, 1f, 0.35f);
+ Gizmos.DrawWireSphere(center, fillRange);
+ }
+
+ Gizmos.color = new Color(1f, 0f, 0f, 0.35f);
+ Gizmos.DrawWireSphere(center, explosionRadius);
}
#endif
}
diff --git a/Assets/MyGame/aa/Game/FLZY/TSY/ShanDian/dianman.prefab b/Assets/MyGame/aa/Game/FLZY/TSY/ShanDian/dianman.prefab
index e9319c54d..2a6a6fd5e 100644
--- a/Assets/MyGame/aa/Game/FLZY/TSY/ShanDian/dianman.prefab
+++ b/Assets/MyGame/aa/Game/FLZY/TSY/ShanDian/dianman.prefab
@@ -90,6 +90,9 @@ MonoBehaviour:
dieEffectTesyNum: 0
minBJCount: 10
maxBJCount: 15
+ laserPrefab: {fileID: 1709254077376921, guid: fdbfa7c8291331a4d838237be97893de,
+ type: 3}
+ laserLengthCorrect: 1
lightningMaterial: {fileID: 2100000, guid: a023113e8eb8bf245b8ba10c3e9788d1, type: 2}
lightningColor: {r: 1, g: 0.92156863, b: 0.015686275, a: 1}
lightningWidth: 10
@@ -101,9 +104,10 @@ MonoBehaviour:
explosionRadius: 2
hitFxPrefab: {fileID: 0}
lightningCount: 5
- detectRange: 0
- lightningWait: 0.5
+ circleRange: 20
+ fillRange: 10
+ lightningWait: 5
killDelay: 0.3
fishLayer:
serializedVersion: 2
- m_Bits: 0
+ m_Bits: 64
diff --git a/Assets/MyGame/aa/Game/ZhanShen/DaQiao/display_wargod_in_14053_0_dev.prefab b/Assets/MyGame/aa/Game/ZhanShen/DaQiao/display_wargod_in_14053_0_dev.prefab
index 8d3024fe6..df6c17c5f 100644
--- a/Assets/MyGame/aa/Game/ZhanShen/DaQiao/display_wargod_in_14053_0_dev.prefab
+++ b/Assets/MyGame/aa/Game/ZhanShen/DaQiao/display_wargod_in_14053_0_dev.prefab
@@ -2868,6 +2868,11 @@ MonoBehaviour:
tra_RotationPivot: {fileID: 0}
bulletPrefab_Two: {fileID: 0}
bulletPrefab: {fileID: 0}
+ laserPrefab: {fileID: 5307749005136556621, guid: 631875e9f9d12204c92185be2ea23965,
+ type: 3}
+ laserWidth: 0.3
+ laserColor: {r: 1, g: 0.3, b: 0.3, a: 0.9}
+ laserLengthCorrect: 1
turretNumber: 0
turretType: 1
displayName:
@@ -2886,3 +2891,8 @@ MonoBehaviour:
laserStartAnim:
laserLoopAnim:
laserEndAnim:
+ playFireParam: PlayFire
+ fireIndexParam: FireIndex
+ idleIndexParam: IdleIndex
+ fireIndex: 0
+ idleIndex: 0
diff --git a/Assets/MyGame/aa/Game/ZhanShen/Game/display_wargod_in_14053_0_dev.prefab b/Assets/MyGame/aa/Game/ZhanShen/Game/display_wargod_in_14053_0_dev.prefab
index e56816ba9..ddc645faa 100644
--- a/Assets/MyGame/aa/Game/ZhanShen/Game/display_wargod_in_14053_0_dev.prefab
+++ b/Assets/MyGame/aa/Game/ZhanShen/Game/display_wargod_in_14053_0_dev.prefab
@@ -937,6 +937,7 @@ MonoBehaviour:
type: 3}
laserWidth: 3
laserColor: {r: 1, g: 0.3, b: 0.3, a: 0.9}
+ laserLengthCorrect: 1
turretNumber: 0
turretType: 1
displayName: