修改鱼线逻辑

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

File diff suppressed because it is too large Load Diff

View File

@@ -53,7 +53,7 @@ MonoBehaviour:
maxPhysicsNodes: 200 maxPhysicsNodes: 200
gravityStrength: 6 gravityStrength: 6
velocityDampen: 0.95 velocityDampen: 0.95
stiffness: 0.8 stiffness: 1
iterations: 10 iterations: 10
initialLength: 0 initialLength: 0
lengthSmoothTime: 0.15 lengthSmoothTime: 0.15

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1629,8 +1629,8 @@ Camera:
y: 0 y: 0
width: 1 width: 1
height: 1 height: 1
near clip plane: 0.01 near clip plane: 0.1
far clip plane: 5000 far clip plane: 3000
field of view: 60.000004 field of view: 60.000004
orthographic: 0 orthographic: 0
orthographic size: 5 orthographic size: 5

View File

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

View File

@@ -64,10 +64,10 @@ public class Rope : MonoBehaviour
[SerializeField, Range(1, 8), Tooltip("每隔多少次FixedUpdate更新一次地面约束")] [SerializeField, Range(1, 8), Tooltip("每隔多少次FixedUpdate更新一次地面约束")]
private int groundUpdateEvery = 2; private int groundUpdateEvery = 2;
private int _groundFrameCounter; private int _groundFrameCounter;
[Header("Simple Water Float (Cheap)")] [Header("Simple Water Float (Cheap)")] [SerializeField, Tooltip("绳子落到水面以下时,是否把节点约束回水面")]
[SerializeField, Tooltip("绳子落到水面以下时,是否把节点约束回水面")]
private bool constrainToWaterSurface = true; private bool constrainToWaterSurface = true;
[SerializeField, Tooltip("静态水面高度;如果你后面接波浪水面,可改成采样函数")] [SerializeField, Tooltip("静态水面高度;如果你后面接波浪水面,可改成采样函数")]
@@ -236,7 +236,7 @@ public class Rope : MonoBehaviour
private int ComputeDesiredNodes(float lengthMeters) 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); desired = Mathf.Clamp(desired, minPhysicsNodes, maxPhysicsNodes);
return desired; return desired;
} }
@@ -284,7 +284,7 @@ public class Rope : MonoBehaviour
return totalLength; return totalLength;
} }
public float GetPhysicsPolylineLength() public float GetPhysicsPolylineLength()
{ {
float total = 0f; float total = 0f;
@@ -322,10 +322,13 @@ public class Rope : MonoBehaviour
Simulate_VerletFast(); Simulate_VerletFast();
LockAnchorsHard(); LockAnchorsHard();
for (int it = 0; it < iterations; it++) for (int it = 0; it < iterations; it++)
SolveDistanceConstraints_HeadOnly_Fast(); {
SolveDistanceConstraints_FABRIK();
}
LockAnchorsHard(); LockAnchorsHard();
@@ -349,7 +352,9 @@ public class Rope : MonoBehaviour
// 水面抬升后补几次长度约束,让形状更顺一点 // 水面抬升后补几次长度约束,让形状更顺一点
for (int it = 0; it < waterPostConstraintIterations; it++) 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; _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() private void SolveDistanceConstraints_HeadOnly_Fast()
{ {
int last = _physicsNodes - 1; int last = _physicsNodes - 1;
@@ -528,8 +585,23 @@ public class Rope : MonoBehaviour
float diff = (dist - rest) / dist; float diff = (dist - rest) / dist;
Vector3 corr = delta * (diff * stiffness); Vector3 corr = delta * (diff * stiffness);
if (i != 0) _pCurr[i] = a + corr * 0.5f; bool aLocked = (i == 0);
if (i + 1 != last) _pCurr[i + 1] = b - corr * 0.5f; 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 吃满
}
// 两边都锁的情况理论上不会出现
} }
} }

View File

@@ -13,4 +13,4 @@ MonoBehaviour:
m_Name: EditorUndoStackPointer m_Name: EditorUndoStackPointer
m_EditorClassIdentifier: "UMotionEditor.dll::\u0389\u0389\u0389\u0389\u038A\u0389\u0389\u0389\u038A\u038A\u038A\u038A\u038A\u0389\u038A\u038A\u038A\u0389\u038A\u038A\u0389\u0389\u0389\u038A\u038A\u038A\u038A\u038A\u038A\u0389\u038A\u038A\u0389\u038A\u038A\u0389\u038A\u0389\u0389\u0389\u038A\u0389\u0389\u0389\u0389\u0389\u038A" m_EditorClassIdentifier: "UMotionEditor.dll::\u0389\u0389\u0389\u0389\u038A\u0389\u0389\u0389\u038A\u038A\u038A\u038A\u038A\u0389\u038A\u038A\u038A\u0389\u038A\u038A\u0389\u0389\u0389\u038A\u038A\u038A\u038A\u038A\u038A\u0389\u038A\u038A\u0389\u038A\u038A\u0389\u038A\u0389\u0389\u0389\u038A\u0389\u0389\u0389\u0389\u0389\u038A"
"\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u038A\u038A\u038A\u038A\u0389\u038A\u0389\u038A\u0389\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u0389\u038A\u0389\u0389\u038A\u0389\u038A\u038A\u0389\u0389\u038A\u038A\u0389\u0389\u038A\u0389\u038A\u038A\u0389\u038A": 1.29p03 "\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u038A\u038A\u038A\u038A\u0389\u038A\u0389\u038A\u0389\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u0389\u038A\u0389\u0389\u038A\u0389\u038A\u038A\u0389\u0389\u038A\u038A\u0389\u0389\u038A\u0389\u038A\u038A\u0389\u038A": 1.29p03
"\u038A\u038A\u0389\u038A\u038A\u0389\u0389\u0389\u038A\u0389\u038A\u038A\u038A\u0389\u038A\u0389\u0389\u0389\u038A\u0389\u038A\u0389\u038A\u038A\u038A\u038A\u038A\u0389\u0389\u0389\u0389\u0389\u038A\u038A\u0389\u038A\u0389\u0389\u0389\u0389\u038A\u038A\u0389\u038A\u0389\u0389\u0389": 3 "\u038A\u038A\u0389\u038A\u038A\u0389\u0389\u0389\u038A\u0389\u038A\u038A\u038A\u0389\u038A\u0389\u0389\u0389\u038A\u0389\u038A\u0389\u038A\u038A\u038A\u038A\u038A\u0389\u0389\u0389\u0389\u0389\u038A\u038A\u0389\u038A\u0389\u0389\u0389\u0389\u038A\u038A\u0389\u038A\u0389\u0389\u0389": 18

Binary file not shown.

Binary file not shown.