@@ -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.0 f;
[Header("Damping")] [ Tooltip ( "上浮方向速度阻尼(越大越不弹)。本版本: 只在“浮力中心”施加一次, 不再在每个采样点施加, 避免90°附近转不动。 " ) ]
public float verticalDamping = 0.6 f;
[Tooltip("整体角速度阻尼(只施加一次,不要太大)。")] public float angularDamping = 0.6f ;
@@ -31,11 +31,17 @@ public class CapsuleBuoyancyStable : MonoBehaviour
[Header("Water Drag")] public float extraDragInWater = 0.8f ;
public float extraAngularDragInWater = 0.8f ;
[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 Transform Wat er;
private WaterRenderer _waterRenderer ;
public WaterRenderer _waterRender er;
[Tooltip("要瞄准哪一层水的碰撞层。")] [ SerializeField ]
CollisionLayer _Layer = CollisionLayer . AfterAnimatedWaves ;
@@ -45,11 +51,7 @@ public class CapsuleBuoyancyStable : MonoBehaviour
readonly SampleFlowHelper _SampleFlowHelper = new ( ) ;
/// <summary>
/// 查询水面信息点位
/// </summary>
Vector3 [ ] _QueryPoints ;
Vector3 [ ] _QueryResultDisplacements ;
Vector3 [ ] _QueryResultVelocities ;
Vector3 [ ] _QueryResultNormal ;
@@ -62,113 +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 ] ;
if ( Water )
_waterRenderer = Water . GetComponent < WaterRenderer > ( ) ;
}
public void InitBobber ( )
{
if ( _waterRenderer = = null & & SceneSettings . Instance )
{
_waterRenderer = SceneSettings . Instance . Water ;
}
_cap = GetComponentInChildren < CapsuleCollider > ( ) ;
_init = true ;
}
void FixedUpdate ( )
{
if ( Water )
{
}
if ( ! _init ) return ;
if ( ! _waterRenderer ) 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 ;
@@ -176,7 +212,6 @@ public class CapsuleBuoyancyStable : MonoBehaviour
{
errorAxis / = errorMag ;
// “弹簧”力矩 + 阻尼(防止在两个角度间抽动)
Vector3 springTorque = errorAxis * ( uprightSpring * errorMag * _rb . mass ) ;
Vector3 dampTorque = - _rb . angularVelocity * ( uprightDamping * _rb . mass ) ;
@@ -184,7 +219,7 @@ public class CapsuleBuoyancyStable : MonoBehaviour
}
}
// 入水整体 drag
// 5) 入水 drag
if ( subAvg > 0.001f )
{
_rb . linearDamping = _baseDrag + extraDragInWater * subAvg ;
@@ -210,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 ) ;
@@ -232,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 ) ;
}
}