测试修改提交

This commit is contained in:
2026-03-04 09:18:04 +08:00
parent 441f12b616
commit 0de35591e7
9 changed files with 256 additions and 174 deletions

View File

@@ -24,5 +24,6 @@ namespace NBF
/// 水线
/// </summary>
public Transform waterline;
}
}

View File

@@ -9,6 +9,8 @@ namespace NBF
// transform.position = Rod.lineHandler.LineConnector_1.transform.position;
SetParent(Rod.Line.Bobber.transform);
transform.localPosition = Vector3.zero;
var buoyancy = GetComponentInParent<CapsuleBuoyancyStable>();
buoyancy.InitBobber();
}
}
}

View File

@@ -4,7 +4,7 @@ using UnityEngine;
using WaveHarmonic.Crest;
[DisallowMultipleComponent]
[RequireComponent(typeof(Rigidbody), typeof(CapsuleCollider))]
[RequireComponent(typeof(Rigidbody))]
public class CapsuleBuoyancyStable : MonoBehaviour
{
[Header("Buoyancy")] [Tooltip("完全浸没时总浮力 = mass*g*buoyancyScale。>1 更浮。")]
@@ -15,8 +15,8 @@ public class CapsuleBuoyancyStable : MonoBehaviour
[Tooltip("浸没比例曲线0=刚碰水, 1=充分在水下)。")] public AnimationCurve submergenceCurve = AnimationCurve.Linear(0, 0, 1, 1);
[Header("Damping")] [Tooltip("上浮方向速度阻尼(越大越不弹)。")]
public float verticalDamping = 3.0f;
[Header("Damping")] [Tooltip("上浮方向速度阻尼(越大越不弹)。本版本只在“浮力中心”施加一次不再在每个采样点施加避免90°附近转不动。")]
public float verticalDamping = 0.6f;
[Tooltip("整体角速度阻尼(只施加一次,不要太大)。")] public float angularDamping = 0.6f;
@@ -31,8 +31,15 @@ public class CapsuleBuoyancyStable : MonoBehaviour
[Header("Water Drag")] public float extraDragInWater = 0.8f;
public float extraAngularDragInWater = 0.8f;
#region Crest5相关信息
[Header("Anti-stiction near upright")]
[Tooltip("在接近竖直(例如90->80度附近)时降低vertical damping避免“粘住”。0=关闭。")]
[Range(0f, 1f)]
public float nearUprightDampingReduce = 0.6f;
[Tooltip("接近竖直的判定角度(度)。例如 12 表示在 |angle| < 12° 附近逐步降低阻尼。")] [Range(1f, 30f)]
public float nearUprightAngleDeg = 12f;
#region Crest5相关信息
public WaterRenderer _waterRenderer;
@@ -44,11 +51,7 @@ public class CapsuleBuoyancyStable : MonoBehaviour
readonly SampleFlowHelper _SampleFlowHelper = new();
/// <summary>
/// 查询水面信息点位
/// </summary>
Vector3[] _QueryPoints;
Vector3[] _QueryResultDisplacements;
Vector3[] _QueryResultVelocities;
Vector3[] _QueryResultNormal;
@@ -61,106 +64,147 @@ public class CapsuleBuoyancyStable : MonoBehaviour
CapsuleCollider _cap;
float _baseDrag, _baseAngularDrag;
[SerializeField] private bool _init = false;
void Awake()
{
_rb = GetComponent<Rigidbody>();
_cap = GetComponent<CapsuleCollider>();
_baseDrag = _rb.linearDamping;
_baseAngularDrag = _rb.angularDamping;
}
private void Start()
void Start()
{
int length = Mathf.Max(3, samplePoints);
_QueryPoints = new Vector3[length];
_QueryResultDisplacements = new Vector3[length];
_QueryResultVelocities = new Vector3[length];
_QueryResultNormal = new Vector3[length];
}
public void InitBobber()
{
if (_waterRenderer == null && SceneSettings.Instance)
{
_waterRenderer = SceneSettings.Instance.Water;
}
_cap = GetComponentInChildren<CapsuleCollider>();
_init = true;
}
void FixedUpdate()
{
if (!_waterRenderer)
{
return;
}
if (!_init) return;
if (!_waterRenderer) return;
GetWorldCapsule(out Vector3 a, out Vector3 b, out float radius);
int n = Mathf.Max(3, samplePoints);
if (_QueryPoints == null || _QueryPoints.Length != n)
{
_QueryPoints = new Vector3[n];
_QueryResultDisplacements = new Vector3[n];
_QueryResultVelocities = new Vector3[n];
_QueryResultNormal = new Vector3[n];
}
float fullBuoyancy = _rb.mass * Physics.gravity.magnitude * buoyancyScale;
float perPointMax = fullBuoyancy / n;
float subSum = 0f;
int wetCount = 0;
for (int i = 0; i < _QueryPoints.Length; i++)
// 采样点
for (int i = 0; i < n; i++)
{
float t = (float)i / (n - 1);
Vector3 p = Vector3.Lerp(a, b, t);
_QueryPoints[i] = p;
_QueryPoints[i] = Vector3.Lerp(a, b, t);
}
// 查询
// Crest 查询
var collisions = _waterRenderer.AnimatedWavesLod.Provider;
collisions.Query(GetHashCode(), _ObjectWidth, _QueryPoints, _QueryResultDisplacements,
_QueryResultNormal, _QueryResultVelocities, _Layer);
float subSum = 0f;
int wetCount = 0;
// 用于计算“浮力中心”(Center of Buoyancy)与水流速度平均
Vector3 cobSum = Vector3.zero;
Vector3 wvSum = Vector3.zero;
float cobW = 0f;
// 1) 多点只加浮力不再在每点加vertical damping
for (int i = 0; i < n; i++)
{
float t = (float)i / (n - 1);
Vector3 p = Vector3.Lerp(a, b, t);
Vector3 p = _QueryPoints[i];
float waterH =
_QueryResultDisplacements[i].y + _waterRenderer.SeaLevel; //GaiaConstants.Water.GetWaterHeight(p);
float depth = waterH - p.y; // >0 在水下
float waterH = _QueryResultDisplacements[i].y + _waterRenderer.SeaLevel;
float depth = waterH - p.y;
float sub = Mathf.InverseLerp(-radius, radius, depth); // 0..1
float sub = Mathf.InverseLerp(-radius, radius, depth);
if (sub <= 0f) continue;
sub = Mathf.Clamp01(submergenceCurve.Evaluate(sub));
subSum += sub;
wetCount++;
Vector3 buoyDir = Vector3.up;
cobSum += p * sub;
wvSum += _QueryResultVelocities[i] * sub;
cobW += sub;
// Vector3 waterVel = GaiaConstants.Water.GetWaterVelocity(p);
Vector3 waterVel = _QueryResultVelocities[i];
Vector3 pointVel = _rb.GetPointVelocity(p);
Vector3 relVel = pointVel - waterVel;
// 浮力
Vector3 buoyForce = buoyDir * (perPointMax * sub);
// 只阻尼上浮方向速度分量(防弹跳)
float vUp = Vector3.Dot(relVel, buoyDir);
Vector3 dampForce = -buoyDir * (vUp * verticalDamping * _rb.mass * sub);
_rb.AddForceAtPosition(buoyForce + dampForce, p, ForceMode.Force);
Vector3 buoyForce = Vector3.up * (perPointMax * sub);
_rb.AddForceAtPosition(buoyForce, p, ForceMode.Force);
if (drawDebug)
{
Debug.DrawLine(p, p + buoyForce / (_rb.mass * 10f), Color.cyan, 0f, false);
Debug.DrawLine(p, p + dampForce / (_rb.mass * 10f), Color.yellow, 0f, false);
}
}
float subAvg = (wetCount > 0) ? (subSum / wetCount) : 0f;
// 角阻尼:只加一次(关键修复点
// 2) vertical damping只在“浮力中心”施加一次关键修复不再产生抑制旋转的力矩
if (subAvg > 0f && cobW > 1e-6f)
{
Vector3 cob = cobSum / cobW;
Vector3 waterVelAvg = wvSum / cobW;
// 接近竖直时降低vertical damping避免90->80度“粘住”
float vdScale = 1f;
if (nearUprightDampingReduce > 0f)
{
Vector3 axisWorld = GetAxisWorld(uprightAxis);
float angleFromUp = Vector3.Angle(axisWorld, Vector3.up); // 0=竖直
float t = Mathf.Clamp01(angleFromUp / Mathf.Max(0.001f, nearUprightAngleDeg));
// t=0(很竖直) -> 1(离开竖直)
vdScale = Mathf.Lerp(1f - nearUprightDampingReduce, 1f, t);
}
Vector3 pointVel = _rb.GetPointVelocity(cob);
Vector3 relVel = pointVel - waterVelAvg;
float vUp = Vector3.Dot(relVel, Vector3.up);
Vector3 dampForce = -Vector3.up * (vUp * verticalDamping * _rb.mass * subAvg * vdScale);
_rb.AddForceAtPosition(dampForce, cob, ForceMode.Force);
if (drawDebug)
{
Debug.DrawLine(cob, cob + dampForce / (_rb.mass * 10f), Color.yellow, 0f, false);
}
}
// 3) 角阻尼:只加一次
if (subAvg > 0f)
{
_rb.AddTorque(-_rb.angularVelocity * (angularDamping * _rb.mass * subAvg), ForceMode.Force);
}
// 可选:upright 稳定器(更像“浮漂自动立起来”
// 4) upright(保持你原逻辑
if (subAvg > 0f && uprightSpring > 0f)
{
Vector3 axisWorld = GetAxisWorld(uprightAxis);
Vector3 targetUp = Vector3.up;
// 误差轴axisWorld 需要对齐 targetUp也可反过来按你浮漂模型选
Vector3 errorAxis = Vector3.Cross(axisWorld, targetUp);
float errorMag = errorAxis.magnitude;
@@ -168,7 +212,6 @@ public class CapsuleBuoyancyStable : MonoBehaviour
{
errorAxis /= errorMag;
// “弹簧”力矩 + 阻尼(防止在两个角度间抽动)
Vector3 springTorque = errorAxis * (uprightSpring * errorMag * _rb.mass);
Vector3 dampTorque = -_rb.angularVelocity * (uprightDamping * _rb.mass);
@@ -176,7 +219,7 @@ public class CapsuleBuoyancyStable : MonoBehaviour
}
}
// 入水整体 drag
// 5) 入水 drag
if (subAvg > 0.001f)
{
_rb.linearDamping = _baseDrag + extraDragInWater * subAvg;
@@ -202,7 +245,7 @@ public class CapsuleBuoyancyStable : MonoBehaviour
void GetWorldCapsule(out Vector3 a, out Vector3 b, out float radius)
{
Vector3 lossy = transform.lossyScale;
int dir = _cap.direction; // 0=X,1=Y,2=Z
int dir = _cap.direction;
float scaleAlong = (dir == 0) ? Mathf.Abs(lossy.x) : (dir == 1) ? Mathf.Abs(lossy.y) : Mathf.Abs(lossy.z);
@@ -224,16 +267,14 @@ public class CapsuleBuoyancyStable : MonoBehaviour
b = center + half;
}
private void OnDrawGizmosSelected()
void OnDrawGizmosSelected()
{
if (drawDebug)
{
// 绘制 Rigidbody 的重心点位
Vector3 centerOfMassWorld = transform.TransformPoint(_rb != null ? _rb.centerOfMass : Vector3.zero);
Gizmos.color = Color.cyan;
Gizmos.DrawSphere(centerOfMassWorld, 0.1f);
Gizmos.DrawLine(centerOfMassWorld, centerOfMassWorld + Vector3.up * 0.5f);
}
if (!drawDebug) return;
if (_rb == null) _rb = GetComponent<Rigidbody>();
Vector3 centerOfMassWorld = transform.TransformPoint(_rb != null ? _rb.centerOfMass : Vector3.zero);
Gizmos.color = Color.cyan;
Gizmos.DrawSphere(centerOfMassWorld, 0.1f);
Gizmos.DrawLine(centerOfMassWorld, centerOfMassWorld + Vector3.up * 0.5f);
}
}