提交线修改
This commit is contained in:
@@ -119,7 +119,7 @@ namespace NBF
|
||||
Log.Error($"SetObiRopeStretch={value}");
|
||||
if (value > 3)
|
||||
{
|
||||
value -= 0.2f;
|
||||
// value -= 0.2f;
|
||||
}
|
||||
fishingRope.SetTargetLength(value);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,9 @@ public class Rope : MonoBehaviour
|
||||
[SerializeField, Range(1, 80), Tooltip("迭代次数。鱼线 10~30 通常够用")]
|
||||
private int iterations = 20;
|
||||
|
||||
[SerializeField, Range(0, 16), Tooltip("主求解后追加的硬长度约束次数。只负责把 poly 拉回到 rest total,不改变可变长度逻辑")]
|
||||
private int hardTightenIterations = 2;
|
||||
|
||||
[Header("Length Control (No Min/Max Clamp)")]
|
||||
[Tooltip("初始总长度(米)。如果为 0,则用 physicsSegmentLen*(minPhysicsNodes-1) 作为初始长度")]
|
||||
[SerializeField, Min(0f)]
|
||||
@@ -65,6 +68,9 @@ public class Rope : MonoBehaviour
|
||||
[SerializeField, Range(1, 8), Tooltip("每隔多少次FixedUpdate更新一次地面约束")]
|
||||
private int groundUpdateEvery = 2;
|
||||
|
||||
[SerializeField, Range(0, 8), Tooltip("地面约束后,再做几次长度约束,减少 poly 被地面抬长")]
|
||||
private int groundPostConstraintIterations = 2;
|
||||
|
||||
private int _groundFrameCounter;
|
||||
|
||||
[Header("Simple Water Float (Cheap)")] [SerializeField, Tooltip("绳子落到水面以下时,是否把节点约束回水面")]
|
||||
@@ -188,6 +194,7 @@ public class Rope : MonoBehaviour
|
||||
renderSubdivisionsIdle = Mathf.Max(renderSubdivisionsIdle, 1);
|
||||
renderSubdivisionsMoving = Mathf.Max(renderSubdivisionsMoving, 1);
|
||||
iterations = Mathf.Clamp(iterations, 1, 80);
|
||||
hardTightenIterations = Mathf.Clamp(hardTightenIterations, 0, 16);
|
||||
groundCastDistance = Mathf.Max(groundCastDistance, 0.01f);
|
||||
groundCastHeight = Mathf.Max(groundCastHeight, 0f);
|
||||
lineWidth = Mathf.Max(lineWidth, 0.0001f);
|
||||
@@ -203,6 +210,7 @@ public class Rope : MonoBehaviour
|
||||
|
||||
groundSampleStep = Mathf.Max(1, groundSampleStep);
|
||||
groundUpdateEvery = Mathf.Max(1, groundUpdateEvery);
|
||||
groundPostConstraintIterations = Mathf.Clamp(groundPostConstraintIterations, 0, 8);
|
||||
|
||||
waterSampleStep = Mathf.Max(1, waterSampleStep);
|
||||
waterUpdateEvery = Mathf.Max(1, waterUpdateEvery);
|
||||
@@ -302,11 +310,27 @@ public class Rope : MonoBehaviour
|
||||
|
||||
public void DebugLength()
|
||||
{
|
||||
float solverRestTotal = (_physicsNodes - 2) * physicsSegmentLen + _headRestLen;
|
||||
float poly = GetPhysicsPolylineLength();
|
||||
float maxSegDelta = 0f;
|
||||
float avgSegDelta = 0f;
|
||||
for (int i = 1; i < _physicsNodes; i++)
|
||||
{
|
||||
float rest = (i == 1) ? _headRestLen : physicsSegmentLen;
|
||||
float segLen = Vector3.Distance(_pCurr[i - 1], _pCurr[i]);
|
||||
float delta = segLen - rest;
|
||||
if (delta > maxSegDelta) maxSegDelta = delta;
|
||||
avgSegDelta += delta;
|
||||
}
|
||||
|
||||
if (_physicsNodes > 1)
|
||||
avgSegDelta /= (_physicsNodes - 1);
|
||||
|
||||
Debug.Log(
|
||||
$"current={_currentLength}, target={_targetLength}, nodes={_physicsNodes}, " +
|
||||
$"seg={physicsSegmentLen}, head={_headRestLen}, headMin={headMinLen}, " +
|
||||
$"solverRestTotal={(_physicsNodes - 2) * physicsSegmentLen + _headRestLen}, " +
|
||||
$"poly={GetPhysicsPolylineLength()}"
|
||||
$"solverRestTotal={solverRestTotal}, poly={poly}, delta={poly - solverRestTotal}, " +
|
||||
$"maxSegDelta={maxSegDelta}, avgSegDelta={avgSegDelta}"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -336,6 +360,7 @@ public class Rope : MonoBehaviour
|
||||
SolveDistanceConstraints_HeadOnly_Fast();
|
||||
}
|
||||
|
||||
SolveHardDistanceConstraints(hardTightenIterations);
|
||||
LockAnchorsHard();
|
||||
|
||||
if (constrainToGround)
|
||||
@@ -345,6 +370,7 @@ public class Rope : MonoBehaviour
|
||||
{
|
||||
_groundFrameCounter = 0;
|
||||
ConstrainToGround();
|
||||
SolveHardDistanceConstraints(groundPostConstraintIterations);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,10 +383,7 @@ public class Rope : MonoBehaviour
|
||||
ConstrainToWaterSurface();
|
||||
|
||||
// 水面抬升后补几次长度约束,让形状更顺一点
|
||||
for (int it = 0; it < waterPostConstraintIterations; it++)
|
||||
{
|
||||
SolveDistanceConstraints_HeadOnly_Fast();
|
||||
}
|
||||
SolveHardDistanceConstraints(waterPostConstraintIterations);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -522,9 +545,37 @@ public class Rope : MonoBehaviour
|
||||
|
||||
private void SolveDistanceConstraints_HeadOnly_Fast()
|
||||
{
|
||||
int last = _physicsNodes - 1;
|
||||
SolveDistanceConstraints_HeadOnly_Bidirectional(stiffness);
|
||||
}
|
||||
|
||||
for (int i = 0; i < last; i++)
|
||||
private void SolveHardDistanceConstraints(int extraIterations)
|
||||
{
|
||||
for (int it = 0; it < extraIterations; it++)
|
||||
{
|
||||
LockAnchorsHard();
|
||||
SolveDistanceConstraints_HeadOnly_Hard();
|
||||
}
|
||||
}
|
||||
|
||||
private void SolveDistanceConstraints_HeadOnly_Hard()
|
||||
{
|
||||
SolveDistanceConstraints_HeadOnly_Bidirectional(1f);
|
||||
}
|
||||
|
||||
private void SolveDistanceConstraints_HeadOnly_Bidirectional(float combinedStiffness)
|
||||
{
|
||||
int last = _physicsNodes - 1;
|
||||
if (last <= 0) return;
|
||||
|
||||
float clamped = Mathf.Clamp01(combinedStiffness);
|
||||
float sweepStiffness = (clamped >= 0.999999f) ? 1f : 1f - Mathf.Sqrt(1f - clamped);
|
||||
SolveDistanceConstraintsSweep_Fast(0, last, 1, last, sweepStiffness);
|
||||
SolveDistanceConstraintsSweep_Fast(last - 1, -1, -1, last, sweepStiffness);
|
||||
}
|
||||
|
||||
private void SolveDistanceConstraintsSweep_Fast(int start, int endExclusive, int step, int last, float sweepStiffness)
|
||||
{
|
||||
for (int i = start; i != endExclusive; i += step)
|
||||
{
|
||||
float rest = (i == 0) ? _headRestLen : physicsSegmentLen;
|
||||
|
||||
@@ -537,7 +588,7 @@ public class Rope : MonoBehaviour
|
||||
|
||||
float dist = Mathf.Sqrt(sq);
|
||||
float diff = (dist - rest) / dist;
|
||||
Vector3 corr = delta * (diff * stiffness);
|
||||
Vector3 corr = delta * (diff * sweepStiffness);
|
||||
|
||||
bool aLocked = (i == 0);
|
||||
bool bLocked = (i + 1 == last);
|
||||
@@ -766,7 +817,8 @@ public class Rope : MonoBehaviour
|
||||
(-p0 + 3f * p1 - 3f * p2 + p3) * t3
|
||||
);
|
||||
|
||||
cr.y = p1.y + (p2.y - p1.y) * t;
|
||||
// y 也使用平滑曲线,再做单调夹紧;避免垂直时因为线性 y 插值导致切线断裂,看起来像折线。
|
||||
cr.y = ClampMonotonic(cr.y, p0.y, p1.y, p2.y, p3.y);
|
||||
|
||||
_rPoints[idx++] = cr;
|
||||
}
|
||||
@@ -778,6 +830,18 @@ public class Rope : MonoBehaviour
|
||||
_lineRenderer.SetPositions(_rPoints);
|
||||
}
|
||||
|
||||
private static float ClampMonotonic(float value, float p0, float p1, float p2, float p3)
|
||||
{
|
||||
bool rising = p0 <= p1 && p1 <= p2 && p2 <= p3;
|
||||
bool falling = p0 >= p1 && p1 >= p2 && p2 >= p3;
|
||||
if (!rising && !falling)
|
||||
return value;
|
||||
|
||||
float min = Mathf.Min(p1, p2);
|
||||
float max = Mathf.Max(p1, p2);
|
||||
return Mathf.Clamp(value, min, max);
|
||||
}
|
||||
|
||||
private int PickRenderSubdivisions_Fast()
|
||||
{
|
||||
int idle = Mathf.Max(1, renderSubdivisionsIdle);
|
||||
|
||||
Reference in New Issue
Block a user