修改鱼线逻辑

This commit is contained in:
2026-03-22 16:25:39 +08:00
parent 6390924d3b
commit 04d6446a76
12 changed files with 15640 additions and 15564 deletions

View File

@@ -117,6 +117,10 @@ namespace NBF
public void SetTargetLength(float value)
{
Log.Error($"SetObiRopeStretch={value}");
if (value > 1)
{
// value -= 0.2f;
}
fishingRope.SetTargetLength(value);
}
}

View File

@@ -64,10 +64,10 @@ public class Rope : MonoBehaviour
[SerializeField, Range(1, 8), Tooltip("每隔多少次FixedUpdate更新一次地面约束")]
private int groundUpdateEvery = 2;
private int _groundFrameCounter;
[Header("Simple Water Float (Cheap)")]
[SerializeField, Tooltip("绳子落到水面以下时,是否把节点约束回水面")]
[Header("Simple Water Float (Cheap)")] [SerializeField, Tooltip("绳子落到水面以下时,是否把节点约束回水面")]
private bool constrainToWaterSurface = true;
[SerializeField, Tooltip("静态水面高度;如果你后面接波浪水面,可改成采样函数")]
@@ -236,7 +236,7 @@ public class Rope : MonoBehaviour
private int ComputeDesiredNodes(float lengthMeters)
{
int desired = Mathf.FloorToInt(Mathf.Max(0f, lengthMeters) / physicsSegmentLen) + 1;
int desired = Mathf.RoundToInt(Mathf.Max(0f, lengthMeters) / physicsSegmentLen) + 1;
desired = Mathf.Clamp(desired, minPhysicsNodes, maxPhysicsNodes);
return desired;
}
@@ -284,7 +284,7 @@ public class Rope : MonoBehaviour
return totalLength;
}
public float GetPhysicsPolylineLength()
{
float total = 0f;
@@ -322,10 +322,13 @@ public class Rope : MonoBehaviour
Simulate_VerletFast();
LockAnchorsHard();
for (int it = 0; it < iterations; it++)
SolveDistanceConstraints_HeadOnly_Fast();
{
SolveDistanceConstraints_FABRIK();
}
LockAnchorsHard();
@@ -349,7 +352,9 @@ public class Rope : MonoBehaviour
// 水面抬升后补几次长度约束,让形状更顺一点
for (int it = 0; it < waterPostConstraintIterations; it++)
SolveDistanceConstraints_HeadOnly_Fast();
{
SolveDistanceConstraints_FABRIK();
}
}
}
@@ -509,6 +514,58 @@ public class Rope : MonoBehaviour
_pPrev[last] = e - endAnchor.linearVelocity * _dt;
}
private void SolveDistanceConstraints_FABRIK()
{
int last = _physicsNodes - 1;
if (last < 1) return;
// 起点固定
_pCurr[0] = _startTr ? _startTr.position : startAnchor.position;
// Forward: from start to end
for (int i = 1; i <= last; i++)
{
float rest = (i == 1) ? _headRestLen : physicsSegmentLen;
Vector3 prev = _pCurr[i - 1];
Vector3 curr = _pCurr[i];
Vector3 dir = curr - prev;
float sq = dir.sqrMagnitude;
if (sq < 1e-12f)
dir = Vector3.down;
else
dir /= Mathf.Sqrt(sq);
_pCurr[i] = prev + dir * rest;
}
// 终点固定
_pCurr[last] = _endTr ? _endTr.position : endAnchor.position;
// Backward: from end to start
for (int i = last - 1; i >= 0; i--)
{
float rest = (i == 0) ? _headRestLen : physicsSegmentLen;
Vector3 next = _pCurr[i + 1];
Vector3 curr = _pCurr[i];
Vector3 dir = curr - next;
float sq = dir.sqrMagnitude;
if (sq < 1e-12f)
dir = Vector3.up;
else
dir /= Mathf.Sqrt(sq);
_pCurr[i] = next + dir * rest;
}
// 再锁一次两端
_pCurr[0] = _startTr ? _startTr.position : startAnchor.position;
_pCurr[last] = _endTr ? _endTr.position : endAnchor.position;
}
private void SolveDistanceConstraints_HeadOnly_Fast()
{
int last = _physicsNodes - 1;
@@ -528,8 +585,23 @@ public class Rope : MonoBehaviour
float diff = (dist - rest) / dist;
Vector3 corr = delta * (diff * stiffness);
if (i != 0) _pCurr[i] = a + corr * 0.5f;
if (i + 1 != last) _pCurr[i + 1] = b - corr * 0.5f;
bool aLocked = (i == 0);
bool bLocked = (i + 1 == last);
if (!aLocked && !bLocked)
{
_pCurr[i] = a + corr * 0.5f;
_pCurr[i + 1] = b - corr * 0.5f;
}
else if (aLocked && !bLocked)
{
_pCurr[i + 1] = b - corr; // 首段node1 吃满
}
else if (!aLocked && bLocked)
{
_pCurr[i] = a + corr; // 尾段last-1 吃满
}
// 两边都锁的情况理论上不会出现
}
}