From d7028a56644ea64570071e55eb7235e3d053efb9 Mon Sep 17 00:00:00 2001 From: "Bob.Song" <605277374@qq.com> Date: Fri, 17 Apr 2026 00:21:55 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Scenes/RopeTest.unity | 27 +++++- .../New/View/FishingLine/FishingLineNode.cs | 35 +++++++- .../New/View/FishingLine/FishingLineSolver.cs | 83 +++++++++++++++++-- .../FishingLine/FishingLineTestController.cs | 4 +- 4 files changed, 137 insertions(+), 12 deletions(-) diff --git a/Assets/Scenes/RopeTest.unity b/Assets/Scenes/RopeTest.unity index 3f97e72fc..35aef6f1e 100644 --- a/Assets/Scenes/RopeTest.unity +++ b/Assets/Scenes/RopeTest.unity @@ -119,6 +119,17 @@ NavMeshSettings: debug: m_Flags: 0 m_NavMeshData: {fileID: 0} +--- !u!114 &145783537 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 6741752443570310990, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + m_PrefabInstance: {fileID: 1672280511} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78dc478e56ff48849761861244c93535, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::NBF.FishingLineSolver --- !u!1 &203844586 GameObject: m_ObjectHideFlags: 0 @@ -582,7 +593,7 @@ Transform: m_GameObject: {fileID: 1181671545} serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -21.88, y: -1, z: -16.13} + m_LocalPosition: {x: -21.88, y: 0, z: -16.13} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] @@ -611,7 +622,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 4162208118158024875, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} propertyPath: m_LocalPosition.y - value: -1 + value: 1 objectReference: {fileID: 0} - target: {fileID: 4162208118158024875, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} propertyPath: m_LocalPosition.z @@ -649,6 +660,14 @@ PrefabInstance: propertyPath: anchorTransform value: objectReference: {fileID: 2055159199} + - target: {fileID: 6741752443570310990, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: breakLimitDuration + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 6741752443570310990, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: breakStretchThreshold + value: 0.08 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: @@ -695,7 +714,7 @@ Transform: m_GameObject: {fileID: 2055159198} serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalPosition: {x: 0, y: 1, z: 0} m_LocalScale: {x: 0.01, y: 0.01, z: 0.01} m_ConstrainProportionsScale: 0 m_Children: [] @@ -818,7 +837,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 5382d66f55f6463cb469c5094b0e7a6b, type: 3} m_Name: m_EditorClassIdentifier: Assembly-CSharp::NBF.FishingLineTestController - solver: {fileID: 0} + solver: {fileID: 145783537} initialFirstSegmentLength: 1.2 minFirstSegmentLength: 0.1 maxFirstSegmentLength: 5 diff --git a/Assets/Scripts/Fishing/New/View/FishingLine/FishingLineNode.cs b/Assets/Scripts/Fishing/New/View/FishingLine/FishingLineNode.cs index eef56bd4d..e15820b41 100644 --- a/Assets/Scripts/Fishing/New/View/FishingLine/FishingLineNode.cs +++ b/Assets/Scripts/Fishing/New/View/FishingLine/FishingLineNode.cs @@ -44,7 +44,17 @@ namespace NBF set => nodeType = value; } - public float Lenght => _joint != null ? _joint.linearLimit.limit : 0f; + public float Lenght { get; private set; } + + /// + /// 真实实际长度 + /// + public float RealLength { get; private set; } + + /// + /// 当前逻辑链总长度超出配置总长度的部分,小于等于零时记为 0。 + /// + public float StretchLength { get; private set; } public Rigidbody Body => body; @@ -77,6 +87,7 @@ namespace NBF { EnsureFeatureCache(); UpdateMotionControl(Time.fixedDeltaTime); + UpdateLenght(); } private void OnValidate() @@ -87,6 +98,28 @@ namespace NBF } segmentLengthToNext = Mathf.Max(0f, segmentLengthToNext); + + } + + private void UpdateLenght() + { + //更新长度 + Lenght = 0; + RealLength = 0; + StretchLength = 0; + if (_joint) + { + Lenght = _joint.linearLimit.limit; + if (_joint && _joint.connectedBody) + { + RealLength = Vector3.Distance(transform.position, _joint.connectedBody.transform.position); + } + } + + if (RealLength > Lenght) + { + StretchLength = RealLength - Lenght; + } } #region Line diff --git a/Assets/Scripts/Fishing/New/View/FishingLine/FishingLineSolver.cs b/Assets/Scripts/Fishing/New/View/FishingLine/FishingLineSolver.cs index 7818ab78b..e856b8b1e 100644 --- a/Assets/Scripts/Fishing/New/View/FishingLine/FishingLineSolver.cs +++ b/Assets/Scripts/Fishing/New/View/FishingLine/FishingLineSolver.cs @@ -53,7 +53,7 @@ namespace NBF private void FixedUpdate() { UpdateAnchorNode(); - UpdateStretchLength(); + UpdateBreakCountdown(Time.fixedDeltaTime); } #region Start Node @@ -221,7 +221,7 @@ namespace NBF /// [Header("Limit Detection")] public float CurrentStretchLength { get; private set; } - + [Min(0f)] // 极限判定的长度容差,允许链路在总长或单段长度上存在少量误差。 [SerializeField] @@ -230,7 +230,12 @@ namespace NBF [Min(0f)] // 达到极限后,只有当前超长值大于该阈值时,才开始进入断线候选计时。 [SerializeField] - private float breakStretchThreshold = 0.05f; + private float breakStretchThreshold = 0.08f; + + [Min(0f)] + // 断线候选状态允许持续的最大时间;超过后会发出一次断线消息。 + [SerializeField] + private float breakLimitDuration = 3f; /// /// 当鱼线达到断线条件时发出的一次性消息。 @@ -238,12 +243,24 @@ namespace NBF /// public event Action OnLineBreakRequested; + /// + /// 当前是否处于极限状态。 + /// 只要整链超出总长度容差,或任一逻辑段超出单段容差,即认为到达极限。 + /// + public bool IsAtLimit { get; private set; } + /// /// 当前断线候选状态的累计时间。 /// 只有在处于极限状态,且 CurrentStretchLength 大于断线阈值时才会累加;否则重置为 0。 /// public float LimitStateTime { get; private set; } + /// + /// 当前极限断线消息是否已经发出过。 + /// 在退出断线候选状态前只会发一次,避免重复通知。 + /// + public bool HasBreakNotificationSent { get; private set; } + /// /// 当前拉力极限百分比。 /// 当超长值小于等于 lengthLimitTolerance 时为 0; @@ -252,6 +269,10 @@ namespace NBF /// public float CurrentBreakStretchPercent => EvaluateBreakStretchPercent(CurrentStretchLength); + /// + /// 当前是否正在进行断线候选计时。 + /// + public bool IsBreakCountdownActive => IsAtLimit && CurrentStretchLength > breakStretchThreshold; private float EvaluateBreakStretchPercent(float stretchLength) { @@ -273,9 +294,61 @@ namespace NBF return Mathf.InverseLerp(lengthLimitTolerance, breakStretchThreshold, stretchLength) * 100f; } - private void UpdateStretchLength() + private void SetLimitState(bool isAtLimit) { - + IsAtLimit = isAtLimit; + } + + private void UpdateBreakCountdown(float deltaTime) + { + if (logicalNodes == null || logicalNodes.Length == 0) + { + SetLimitState(false); + ResetLimitState(); + return; + } + + CurrentStretchLength = 0; + //计算长度 + foreach (var node in logicalNodes) + { + CurrentStretchLength += node.StretchLength; + } + + SetLimitState(CurrentStretchLength > lengthLimitTolerance); + + if (!IsBreakCountdownActive) + { + LimitStateTime = 0f; + HasBreakNotificationSent = false; + return; + } + + LimitStateTime += Mathf.Max(0f, deltaTime); + if (HasBreakNotificationSent || LimitStateTime < breakLimitDuration) + { + return; + } + + HasBreakNotificationSent = true; + NotifyLineBreakRequested(); + } + + /// + /// 发出鱼线达到断线条件的消息。 + /// 这里预留给外部订阅,当前不在求解器内部直接执行断线逻辑。 + /// + private void NotifyLineBreakRequested() + { + OnLineBreakRequested?.Invoke(this); + } + + private void ResetLimitState() + { + CurrentStretchLength = 0f; + IsAtLimit = false; + LimitStateTime = 0f; + HasBreakNotificationSent = false; } #endregion diff --git a/Assets/Scripts/Fishing/New/View/FishingLine/FishingLineTestController.cs b/Assets/Scripts/Fishing/New/View/FishingLine/FishingLineTestController.cs index 5211bc17f..5ebb9b67c 100644 --- a/Assets/Scripts/Fishing/New/View/FishingLine/FishingLineTestController.cs +++ b/Assets/Scripts/Fishing/New/View/FishingLine/FishingLineTestController.cs @@ -79,9 +79,9 @@ namespace NBF solver.SetLenght(targetFirstSegmentLength); } - if (solver.CurrentBreakStretchPercent > 0) + if (solver.CurrentBreakStretchPercent > 10) { - // Debug.LogError(solver.CurrentBreakStretchPercent); + Debug.LogError($"当前极限情况,CurrentBreakStretchPercent={solver.CurrentBreakStretchPercent} CurrentStretchLength={solver.CurrentStretchLength} LimitStateTime={solver.LimitStateTime}"); } } }