diff --git a/Assets/Art/FengLei/Boss/1594/1594_PT.prefab.meta b/Assets/Art/FengLei/Boss/1594/1594_PT.prefab.meta new file mode 100644 index 000000000..a411ecd4d --- /dev/null +++ b/Assets/Art/FengLei/Boss/1594/1594_PT.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8c5a0a74fb5ddcd47abbdfe715e47e3f +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MyGame/Scripts/Items/Bullits/BullitMove.cs b/Assets/MyGame/Scripts/Items/Bullits/BullitMove.cs index d3eb2d94c..59651fd38 100644 --- a/Assets/MyGame/Scripts/Items/Bullits/BullitMove.cs +++ b/Assets/MyGame/Scripts/Items/Bullits/BullitMove.cs @@ -27,6 +27,14 @@ public class BullitMove : MonoBehaviour public float distanceForMaxTurn = 1f; // 在此距离内达到最大转向速度 float hitDistance = 2f; // 命中判定距离 + // ⭐ 三合一抛物线(正常炮台散射+锁定时,上下两颗子弹的弧线飞行) + // 出膛偏移0 → 中段鼓出到 parabolaAmplitude(弧线最高点)→ 命中前归零(三发收敛到同一条鱼) + Vector2 parabolaAxis = Vector2.right; // 横向鼓出方向(垂直于炮口→目标连线) + float parabolaAmplitude = 0f; // 最高点横向鼓出幅度(<=0 关闭抛物线) + float parabolaInitialDistance = 1f; // 开火时到目标的距离(进度基准) + float parabolaPrevLateral = 0f; // 上一帧横向偏移(子弹是增量移动,偏移按帧差叠加) + float parabolaBaseSpeed = 0f; // 降速前的原始速度(清理时恢复,防池化复用残留慢速) + // ---------------------------------------------------------------- // ⭐ 渲染层级:sortingOrder 优先于 z 深度排序, // 2D 鱼/飞机设置了 sortingOrder 后会把默认 0 的子弹压在下面, @@ -84,6 +92,41 @@ public class BullitMove : MonoBehaviour vector3_startPosition = transform.position; vector3_startPosition.z = -400; currShowTime = 0f; + // 解锁同时清除抛物线,防止直线飞行时残留横向偏移 + ClearParabola(); + } + + /// + /// ⭐ 三合一抛物线:子弹在追踪目标的轨迹上叠加横向正弦偏移—— + /// 出膛偏移0 → 中段鼓出到 amplitude(弧线最高点)→ 命中前归零(和另外两发收敛到同一条鱼)。 + /// lateralAxis=横向鼓出方向(垂直于炮口→目标连线),totalDistance=开火时到目标的距离。 + /// bulletSpeed>0 时给这发子弹降速:子弹默认速度太快(如100)时全程飞行仅零点几秒,弧线根本看不清。 + /// + public void SetParabola(Vector2 lateralAxis, float amplitude, float totalDistance, float bulletSpeed = 0f) + { + parabolaAxis = lateralAxis.sqrMagnitude > 0.0001f ? lateralAxis.normalized : Vector2.right; + parabolaAmplitude = amplitude; + parabolaInitialDistance = Mathf.Max(0.01f, totalDistance); + parabolaPrevLateral = 0f; + // ⭐ 降速拉长飞行时间,弧线才看得清;记录原始速度,清理时恢复 + if (bulletSpeed > 0f) + { + if (parabolaBaseSpeed <= 0f) + parabolaBaseSpeed = moveSpeed; + moveSpeed = bulletSpeed; + } + } + + /// 清除抛物线状态(解锁/回池时调用):关偏移 + 恢复原速度 + void ClearParabola() + { + parabolaAmplitude = 0f; + parabolaPrevLateral = 0f; + if (parabolaBaseSpeed > 0f) + { + moveSpeed = parabolaBaseSpeed; + parabolaBaseSpeed = 0f; + } } public void Init() @@ -159,6 +202,19 @@ public class BullitMove : MonoBehaviour // 沿当前方向移动 transform.position += transform.up * moveSpeed * Time.deltaTime; + + // ⭐ 三合一抛物线:在追踪轨迹上叠加横向正弦偏移 + // 进度按剩余距离算(dist=初始距离→0,dist=命中距离→1),命中前偏移正好归零,三发收敛到目标身上 + if (parabolaAmplitude > 0f) + { + float range = parabolaInitialDistance - hitDistance; + float progress = range > 0.1f + ? Mathf.Clamp01(1f - (distance - hitDistance) / range) + : 1f; + float lateralNow = parabolaAmplitude * Mathf.Sin(progress * Mathf.PI); + transform.position += (Vector3)parabolaAxis * (lateralNow - parabolaPrevLateral); + parabolaPrevLateral = lateralNow; + } } else { diff --git a/Assets/MyGame/aa/UI/Game/FLZY/GameMainPanel_FLZY.prefab b/Assets/MyGame/aa/UI/Game/FLZY/GameMainPanel_FLZY.prefab index 75f5e985b..1354cf5ed 100644 --- a/Assets/MyGame/aa/UI/Game/FLZY/GameMainPanel_FLZY.prefab +++ b/Assets/MyGame/aa/UI/Game/FLZY/GameMainPanel_FLZY.prefab @@ -3213,6 +3213,11 @@ MonoBehaviour: JinDuTiao: {fileID: 6293566698206718061} isFrenzy: 0 laserHitDelay: 0.2 + sanSheNearDistance: 10 + sanSheFarDistance: 35 + sanSheMaxBulge: 6 + sanSheMinBulge: 4 + sanSheSideBulletSpeed: 50 sitBulletMaxCount: 100 --- !u!1 &5910028015393800118 GameObject: diff --git a/Assets/MyGame/aa/UI/Game/GameMainPanel_FishBase.cs b/Assets/MyGame/aa/UI/Game/GameMainPanel_FishBase.cs index ee108ac9c..03c81b599 100644 --- a/Assets/MyGame/aa/UI/Game/GameMainPanel_FishBase.cs +++ b/Assets/MyGame/aa/UI/Game/GameMainPanel_FishBase.cs @@ -1934,9 +1934,21 @@ public class GameMainPanel_FishBase : GameMainPanel_Base } /// 战神激光命中延迟(秒):不开实体子弹,开火后延迟此时间直接发 KillFish 给后端(模拟弹道飞行) - [Tooltip("战神激光命中延迟(秒):不开实体子弹,开火后延迟此时间直接发 KillFish 给后端")] + [Tooltip("战神激光命中延迟(秒):不开实体子弹,开火后延迟此时间直接发 KillFish 给后端(模拟弹道飞行)")] public float laserHitDelay = 0.2f; + [Header("三合一抛物线(正常炮台散射+锁定,上下两颗子弹的弧线)")] + [Tooltip("近距离阈值:目标距离小于此值时弧线鼓出封顶(防止目标太近子弹乱飘)")] + public float sanSheNearDistance = 10f; + [Tooltip("远距离阈值:目标距离大于此值时弧线鼓出保底(很远时仍有弧线感)")] + public float sanSheFarDistance = 35f; + [Tooltip("弧线最高点横向鼓出最大值(目标距离≤近距离阈值时,世界单位)")] + public float sanSheMaxBulge = 6f; + [Tooltip("弧线最高点横向鼓出最小值(目标距离≥远距离阈值时,世界单位)")] + public float sanSheMinBulge = 4f; + [Tooltip("三合一侧弹飞行速度(世界单位/秒,0=用子弹默认速度):子弹默认速度太快全程仅零点几秒,弧线看不清,降速拉长飞行时间")] + public float sanSheSideBulletSpeed = 50f; + private void FireBullet(SitPosData sit, float angle, bool isSanShe, bool isDouble, bool isLock, List bullitIDs, List fireTargetMonsterIDs = null, List bulletGolds = null) { @@ -1972,18 +1984,60 @@ public class GameMainPanel_FishBase : GameMainPanel_Base // 必须保证三发子弹都创建,否则金币消耗和后端对不上 if (isSanShe && isLock) { - // 三发出膛角度:左 -20,中 0,右 +20(锁定子弹会追踪转向主锁目标) + // 三发出膛角度:右 -20,中 0,左 +20(锁定子弹会追踪转向主锁目标) float[] defaultAngles = { angle - 20, angle, angle + 20 }; + // ⭐ 三合一抛物线:主锁目标有效时,上下两颗子弹走弧线包抄 + // 鼓出幅度随目标距离变化:近→大,远→小(最高点离中线越近), + // 用近距离/远距离两个阈值钳制:很近时封顶不乱飘,很远时保底仍有弧线感 + bool hasLockTarget = sit.monCotl_Lock != null && sit.monCotl_Lock_Position != null + && sit.monCotl_Lock_Position.gameObject.activeInHierarchy; + Vector2 toTarget = Vector2.zero; + float targetDist = 0f; + if (hasLockTarget) + { + toTarget = (Vector2)sit.monCotl_Lock_Position.position - startPos; + targetDist = toTarget.magnitude; + hasLockTarget = targetDist > 0.01f; + } + + // ⭐ 诊断日志(定位三合一抛物线不生效用,问题解决后删除) + if (sit.user == GameManager.Instance.user.id) + { + float tDiag = Mathf.InverseLerp(sanSheFarDistance, sanSheNearDistance, targetDist); + float bulgeDiag = Mathf.Lerp(sanSheMinBulge, sanSheMaxBulge, tDiag); + Debug.Log($"[三合一诊断] 进入三合一分支: 主锁目标={(sit.monCotl_Lock != null ? sit.monCotl_Lock.name : "无")} " + + $"锁定点={(sit.monCotl_Lock_Position != null ? "有" : "无")} hasLockTarget={hasLockTarget} " + + $"目标距离={targetDist:F2} 鼓出={bulgeDiag:F2} 侧弹速度={sanSheSideBulletSpeed} " + + $"阈值(近{sanSheNearDistance}/远{sanSheFarDistance}) 幅度(小{sanSheMinBulge}/大{sanSheMaxBulge})"); + } + for (int i = 0; i < 3; i++) { // lockTarget 传 null:CreateBullet 内部兜底会 Lock(sit.monCotl_Lock, sit.monCotl_Lock_Position), // 三发全部锁定同一条主锁目标;主锁目标为空时按普通子弹发射(不锁定) - CreateBullet(sit, startPos, defaultAngles[i], isDouble, true, SafeBid(i), null, null, GetBulletGold(i)); + var bullet = CreateBullet(sit, startPos, defaultAngles[i], isDouble, true, SafeBid(i), null, null, GetBulletGold(i)); + + // ⭐ 上下两颗(i=0/2)挂抛物线,中间(i=1)直线: + // 鼓出方向垂直于炮口→目标连线,两颗各往自己外侧鼓,形成弧线包抄汇聚 + // 侧弹同时降速(子弹默认100太快,零点几秒飞完,弧线看不清) + if (bullet != null && hasLockTarget && i != 1) + { + // 近距离阈值内→最大鼓出,远距离阈值外→最小鼓出,中间线性过渡 + float t = Mathf.InverseLerp(sanSheFarDistance, sanSheNearDistance, targetDist); + float bulge = Mathf.Lerp(sanSheMinBulge, sanSheMaxBulge, t); + Vector2 axisRight = new Vector2(toTarget.y, -toTarget.x).normalized; + bullet.SetParabola(i == 0 ? axisRight : -axisRight, bulge, targetDist, sanSheSideBulletSpeed); + } } } else if (isSanShe) { + // ⭐ 诊断日志(定位三合一抛物线不生效用,问题解决后删除) + if (sit.user == GameManager.Instance.user.id) + Debug.LogWarning($"[三合一诊断] 走了【散射不锁定】直飞分支: 锁定开关={isLock} → 三发直飞无终点无弧线。" + + $"三合一抛物线需要: 散射+锁定都开 且 锁定到一条鱼"); + CreateBullet(sit, startPos, angle - 20, isDouble, isLock, SafeBid(0), null, null, GetBulletGold(0)); CreateBullet(sit, startPos, angle, isDouble, isLock, SafeBid(1), null, null, GetBulletGold(1)); CreateBullet(sit, startPos, angle + 20, isDouble, isLock, SafeBid(2), null, null, GetBulletGold(2));