修改浮漂和绳子逻辑
This commit is contained in:
@@ -85,6 +85,12 @@ public class Rope : MonoBehaviour
|
||||
[SerializeField, Range(1, 8), Tooltip("每隔多少次FixedUpdate更新一次水面约束")]
|
||||
private int waterUpdateEvery = 1;
|
||||
|
||||
[SerializeField, Range(0f, 1f), Tooltip("水面约束抬升强度(每次更新的插值强度),越小越渐进")]
|
||||
private float waterLiftStrength = 0.25f;
|
||||
|
||||
[SerializeField, Tooltip("startAnchor 在水下时,让其相邻端节点强制跟随 startAnchor,避免被抬到水面导致脱离")]
|
||||
private bool keepStartAdjacentNodeFollow = true;
|
||||
|
||||
[SerializeField, Range(0, 8), Tooltip("水面约束后,再做几次长度约束,减少局部折角")]
|
||||
private int waterPostConstraintIterations = 2;
|
||||
|
||||
@@ -201,6 +207,7 @@ public class Rope : MonoBehaviour
|
||||
waterSampleStep = Mathf.Max(1, waterSampleStep);
|
||||
waterUpdateEvery = Mathf.Max(1, waterUpdateEvery);
|
||||
waterSurfaceOffset = Mathf.Max(0f, waterSurfaceOffset);
|
||||
waterLiftStrength = Mathf.Clamp01(waterLiftStrength);
|
||||
waterPostConstraintIterations = Mathf.Clamp(waterPostConstraintIterations, 0, 8);
|
||||
}
|
||||
|
||||
@@ -630,16 +637,18 @@ public class Rope : MonoBehaviour
|
||||
|
||||
int step = Mathf.Max(1, waterSampleStep);
|
||||
float surfaceY = waterLevelY + waterSurfaceOffset;
|
||||
bool startUnderWater = _pCurr[0].y < surfaceY;
|
||||
int startAdjacentIdx = GetStartAdjacentNodeIndex(last);
|
||||
|
||||
int prevSampleIdx = 1;
|
||||
float prevSurfaceY = surfaceY;
|
||||
|
||||
ApplyWaterSurface(prevSampleIdx, prevSurfaceY);
|
||||
ApplyWaterSurface(prevSampleIdx, prevSurfaceY, startUnderWater, startAdjacentIdx);
|
||||
|
||||
for (int i = 1 + step; i < last; i += step)
|
||||
{
|
||||
float nextSurfaceY = surfaceY;
|
||||
ApplyWaterSurface(i, nextSurfaceY);
|
||||
ApplyWaterSurface(i, nextSurfaceY, startUnderWater, startAdjacentIdx);
|
||||
|
||||
if (waterInterpolate)
|
||||
{
|
||||
@@ -651,13 +660,13 @@ public class Rope : MonoBehaviour
|
||||
int idx = a + j;
|
||||
float t = j / (float)span;
|
||||
float y = Mathf.Lerp(prevSurfaceY, nextSurfaceY, t);
|
||||
ApplyWaterSurface(idx, y);
|
||||
ApplyWaterSurface(idx, y, startUnderWater, startAdjacentIdx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int idx = prevSampleIdx + 1; idx < i; idx++)
|
||||
ApplyWaterSurface(idx, prevSurfaceY);
|
||||
ApplyWaterSurface(idx, prevSurfaceY, startUnderWater, startAdjacentIdx);
|
||||
}
|
||||
|
||||
prevSampleIdx = i;
|
||||
@@ -665,20 +674,38 @@ public class Rope : MonoBehaviour
|
||||
}
|
||||
|
||||
for (int i = prevSampleIdx + 1; i < last; i++)
|
||||
ApplyWaterSurface(i, prevSurfaceY);
|
||||
ApplyWaterSurface(i, prevSurfaceY, startUnderWater, startAdjacentIdx);
|
||||
}
|
||||
|
||||
private void ApplyWaterSurface(int i, float surfaceY)
|
||||
private int GetStartAdjacentNodeIndex(int last)
|
||||
{
|
||||
if (last <= 1) return 1;
|
||||
|
||||
Vector3 s = _pCurr[0];
|
||||
float d1 = (_pCurr[1] - s).sqrMagnitude;
|
||||
float d2 = (_pCurr[last - 1] - s).sqrMagnitude;
|
||||
return d1 <= d2 ? 1 : last - 1;
|
||||
}
|
||||
|
||||
private void ApplyWaterSurface(int i, float surfaceY, bool startUnderWater, int startAdjacentIdx)
|
||||
{
|
||||
if (keepStartAdjacentNodeFollow && startUnderWater && i == startAdjacentIdx)
|
||||
{
|
||||
Vector3 s = _pCurr[0];
|
||||
_pCurr[i] = s;
|
||||
_pPrev[i] = s;
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 p = _pCurr[i];
|
||||
if (p.y < surfaceY)
|
||||
{
|
||||
p.y = surfaceY;
|
||||
p.y = Mathf.Lerp(p.y, surfaceY, waterLiftStrength);
|
||||
_pCurr[i] = p;
|
||||
|
||||
// 同步 prev,杀掉向下惯性,避免反复穿透水面
|
||||
// 渐进同步 prev,削弱向下惯性,避免反复穿透水面
|
||||
Vector3 prev = _pPrev[i];
|
||||
if (prev.y < surfaceY) prev.y = surfaceY;
|
||||
if (prev.y < p.y) prev.y = Mathf.Lerp(prev.y, p.y, waterLiftStrength);
|
||||
_pPrev[i] = prev;
|
||||
}
|
||||
}
|
||||
@@ -798,4 +825,4 @@ public class Rope : MonoBehaviour
|
||||
for (int i = 0; i < _physicsNodes; i++)
|
||||
Gizmos.DrawSphere(_pCurr[i], 0.01f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user