diff --git a/Assets/Scenes/BobberTest.unity b/Assets/Scenes/BobberTest.unity
index a019c98e1..33c187fc4 100644
--- a/Assets/Scenes/BobberTest.unity
+++ b/Assets/Scenes/BobberTest.unity
@@ -863,6 +863,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 06d107cece7c4cbb9825557923be567f, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::BuoyancyWaterProvider
+ Water: {fileID: 0}
waterLevel: 0
--- !u!4 &820800910
Transform:
@@ -3748,7 +3749,7 @@ RectTransform:
m_Father: {fileID: 2256579932936496278}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 0.2, y: 1}
+ m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
@@ -4552,7 +4553,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
- m_IsActive: 0
+ m_IsActive: 1
--- !u!1 &2575899344989503316
GameObject:
m_ObjectHideFlags: 0
@@ -5308,8 +5309,8 @@ RectTransform:
m_Children: []
m_Father: {fileID: 4262266657851529727}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0.2, y: 0}
- m_AnchorMax: {x: 0.2, y: 1}
+ m_AnchorMin: {x: 0, y: 0}
+ m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 20, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
@@ -6492,7 +6493,6 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: f91c9d873c83492ca6d5e3e3a67c1760, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::CapsuleBuoyancyStable
- WaterBehaviour: {fileID: 820800909}
buoyancyScale: 1.6
samplePoints: 9
submergenceCurve:
@@ -6526,6 +6526,9 @@ MonoBehaviour:
uprightAxis: 1
extraDragInWater: 0.8
extraAngularDragInWater: 0.8
+ Water: {fileID: 0}
+ _Layer: 1
+ _ObjectWidth: 3
drawDebug: 0
--- !u!114 &7647511515837834160
MonoBehaviour:
@@ -7303,7 +7306,6 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: f91c9d873c83492ca6d5e3e3a67c1760, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::CapsuleBuoyancyStable
- WaterBehaviour: {fileID: 820800909}
buoyancyScale: 1.6
samplePoints: 9
submergenceCurve:
@@ -7337,6 +7339,9 @@ MonoBehaviour:
uprightAxis: 1
extraDragInWater: 0.8
extraAngularDragInWater: 0.8
+ Water: {fileID: 2531380344179187550}
+ _Layer: 1
+ _ObjectWidth: 0.2
drawDebug: 0
--- !u!153 &8264839114692736908
ConfigurableJoint:
diff --git a/Assets/Scripts/Test/BuoyancyCapsuleSphere.cs b/Assets/Scripts/Test/BuoyancyCapsuleSphere.cs
index fb75698f1..661d43614 100644
--- a/Assets/Scripts/Test/BuoyancyCapsuleSphere.cs
+++ b/Assets/Scripts/Test/BuoyancyCapsuleSphere.cs
@@ -6,219 +6,204 @@ public interface IWaterProvider
Vector3 GetWaterNormal(Vector3 worldPos);
Vector3 GetWaterVelocity(Vector3 worldPos);
}
-
-///
-/// 稳定优先的浮力(只支持 CapsuleCollider / SphereCollider)
-/// - 竖直方向:目标吃水深度 + PD 控制(稳定,不抖、不弹飞)
-/// - 姿态:Righting Torque 扶正(受 Rigidbody.centerOfMass 影响)
-/// - 入水比例:带平滑(避免水面附近开关抖动)
-///
-[DisallowMultipleComponent]
-[RequireComponent(typeof(Rigidbody))]
-public class BuoyancyCapsuleSphere : MonoBehaviour
-{
- [Header("Collider (choose one)")]
- public CapsuleCollider capsule;
- public SphereCollider sphere;
-
- [Header("Water")]
- public MonoBehaviour waterProviderBehaviour; // 可选
- private IWaterProvider waterProvider;
-
- [Tooltip("没有 provider 时的水面高度")]
- public float waterLevel = 0f;
-
- [Header("Density -> Draft")]
- [Tooltip("水密度 kg/m^3(淡水约1000)")]
- public float waterDensity = 1000f;
-
- [Tooltip("物体等效密度 kg/m^3。越小越浮。浮漂可 80~400 之间调")]
- public float objectDensity = 250f;
-
- [Tooltip("额外浮力比例(手感调整)。1=按密度算")]
- public float buoyancyScale = 1f;
-
- [Header("Vertical PD (Stability key)")]
- [Tooltip("竖直弹簧强度(越大越“顶住”目标吃水)")]
- public float verticalKp = 35f;
-
- [Tooltip("竖直阻尼(越大越不弹、不抖)")]
- public float verticalKd = 12f;
-
- [Tooltip("最大向上加速度 m/s^2(防止从高处落下入水被顶飞)")]
- public float maxUpAccel = 25f;
-
- [Tooltip("最大向下加速度 m/s^2(防止强行拉下去造成抖动)")]
- public float maxDownAccel = 10f;
-
- [Header("Submergence smoothing")]
- [Tooltip("入水比例变化速度(1/s)。越大越快响应,越小越稳")]
- public float submergenceSpeed = 8f;
-
- [Tooltip("水面外的缓冲(m),让浮力更平滑接管")]
- public float surfaceMargin = 0.01f;
-
- [Header("Righting (Rotation)")]
- [Tooltip("扶正强度(把 transform.up 拉向水面法线/世界上)")]
- public float rightingKp = 8f;
-
- [Tooltip("扶正阻尼(抑制旋转抖动)")]
- public float rightingKd = 3f;
-
- [Header("Water drag (optional but helpful)")]
- [Tooltip("入水时额外线阻尼(通过 rb.drag 混合)")]
- public float extraLinearDragInWater = 2.5f;
-
- [Tooltip("入水时额外角阻尼(通过 rb.angularDrag 混合)")]
- public float extraAngularDragInWater = 2.0f;
-
- [Header("Center of Mass")]
- [Tooltip("本地重心偏移:例如 (0,-0.02,0) 让底部更重、更容易站漂")]
- public Vector3 centerOfMassOffset = Vector3.zero;
-
- private Rigidbody rb;
- private float baseDrag, baseAngularDrag;
-
- // 关键:入水比例必须有“记忆”(滤波),否则水面边界必抖
- private float subFiltered = 0f;
-
- void Reset()
- {
- rb = GetComponent();
- rb.useGravity = true;
- rb.interpolation = RigidbodyInterpolation.Interpolate;
- rb.collisionDetectionMode = CollisionDetectionMode.Continuous;
-
- capsule = GetComponent();
- sphere = GetComponent();
- }
-
- void Awake()
- {
- rb = GetComponent();
- rb.centerOfMass = centerOfMassOffset;
-
- baseDrag = rb.linearDamping;
- baseAngularDrag = rb.angularDamping;
-
- waterProvider = waterProviderBehaviour as IWaterProvider;
-
- // 只允许一个
- if (capsule != null && sphere != null)
- sphere = null;
- }
-
- void OnValidate()
- {
- objectDensity = Mathf.Max(1e-3f, objectDensity);
- waterDensity = Mathf.Max(1e-3f, waterDensity);
- submergenceSpeed = Mathf.Max(0.1f, submergenceSpeed);
- surfaceMargin = Mathf.Max(0f, surfaceMargin);
- maxUpAccel = Mathf.Max(0f, maxUpAccel);
- maxDownAccel = Mathf.Max(0f, maxDownAccel);
- }
-
- void FixedUpdate()
- {
- if (!capsule && !sphere) return;
-
- waterProvider = waterProviderBehaviour as IWaterProvider;
-
- // 取“浮体中心点”作为控制点(稳定,不戳点)
- Vector3 centerWorld;
- float shapeHeight; // 近似“高度”(sphere=直径,capsule=高度)
- GetCenterAndHeight(out centerWorld, out shapeHeight);
-
- // 水面信息
- float waterH = (waterProvider != null) ? waterProvider.GetWaterHeight(centerWorld) : waterLevel;
- Vector3 waterN = (waterProvider != null) ? waterProvider.GetWaterNormal(centerWorld) : Vector3.up;
- if (waterN.sqrMagnitude < 1e-6f) waterN = Vector3.up;
- waterN.Normalize();
-
- // 当前中心“浸没深度”(>0 表示中心在水下)
- float centerDepth = waterH - centerWorld.y;
-
- // 近似入水比例:centerDepth = -H/2 -> 0; centerDepth = +H/2 -> 1
- float rawSub = Mathf.Clamp01((centerDepth + (shapeHeight * 0.5f) + surfaceMargin) / (shapeHeight + 2f * surfaceMargin));
-
- // 入水比例滤波(非常关键)
- float dt = Time.fixedDeltaTime;
- subFiltered = Mathf.MoveTowards(subFiltered, rawSub, submergenceSpeed * dt);
-
- // 混合拖拽(让水中更稳)
- rb.linearDamping = Mathf.Lerp(baseDrag, baseDrag + extraLinearDragInWater, subFiltered);
- rb.angularDamping = Mathf.Lerp(baseAngularDrag, baseAngularDrag + extraAngularDragInWater, subFiltered);
-
- if (subFiltered <= 1e-4f)
- return; // 基本没入水,不做任何浮力/扶正
-
- // 目标吃水比例:理想静态平衡 ≈ objectDensity / waterDensity(<1 才会浮)
- float desiredSub = Mathf.Clamp01((objectDensity / waterDensity) * buoyancyScale);
-
- // 把 desiredSub 转成目标中心深度
- // desiredSub=0 -> centerDepthTarget = -H/2(完全出水)
- // desiredSub=1 -> centerDepthTarget = +H/2(完全入水)
- float centerDepthTarget = desiredSub * shapeHeight - shapeHeight * 0.5f;
-
- // 竖直 PD:只沿“世界上/重力反方向”控制,最稳
- Vector3 up = (-Physics.gravity).sqrMagnitude > 1e-6f ? (-Physics.gravity).normalized : Vector3.up;
- float vUp = Vector3.Dot(rb.linearVelocity, up);
-
- float error = centerDepth - centerDepthTarget; // 深了为正 -> 需要向上推
- float accelUp = (-verticalKp * error) - (verticalKd * vUp);
-
- // 限制上下加速度,避免顶飞或强拉抖动
- accelUp = Mathf.Clamp(accelUp, -maxDownAccel, maxUpAccel);
-
- // 随入水比例渐入(避免水面边界突然接管)
- accelUp *= subFiltered;
-
- // 施加竖直加速度(Acceleration 不受质量影响,更稳定)
- rb.AddForce(up * accelUp, ForceMode.Acceleration);
-
- // 扶正力矩:把物体 up 拉向 waterN(平静水就是 Vector3.up)
- // 注意:这个扶正与重心偏移一起工作,会形成“站漂/躺漂”的稳定姿态
- Vector3 currentUp = transform.up;
- Vector3 axis = Vector3.Cross(currentUp, waterN);
-
- // 小角度近似:axis 的大小约等于 sin(theta)
- // 扶正加速度型扭矩(同样用 Acceleration,减少质量/惯量差带来的抖动)
- Vector3 angVel = rb.angularVelocity;
- Vector3 torqueAccel = axis * rightingKp - angVel * rightingKd;
-
- torqueAccel *= subFiltered;
-
- rb.AddTorque(torqueAccel, ForceMode.Acceleration);
- }
-
- private void GetCenterAndHeight(out Vector3 centerWorld, out float heightWorld)
- {
- if (sphere)
- {
- // sphere:center + 半径*缩放(近似取最大缩放)
- Transform t = sphere.transform;
- centerWorld = t.TransformPoint(sphere.center);
-
- Vector3 s = t.lossyScale;
- float r = sphere.radius * Mathf.Max(Mathf.Abs(s.x), Mathf.Abs(s.y), Mathf.Abs(s.z));
- heightWorld = Mathf.Max(1e-6f, r * 2f);
- return;
- }
-
- // capsule
- Transform ct = capsule.transform;
- centerWorld = ct.TransformPoint(capsule.center);
-
- Vector3 ls = ct.lossyScale;
- float sx = Mathf.Abs(ls.x), sy = Mathf.Abs(ls.y), sz = Mathf.Abs(ls.z);
-
- float heightScale = capsule.direction switch
- {
- 0 => sx,
- 1 => sy,
- _ => sz,
- };
-
- heightWorld = Mathf.Max(1e-6f, capsule.height * heightScale);
- }
-}
\ No newline at end of file
+//
+// ///
+// /// 稳定优先的浮力(只支持 CapsuleCollider / SphereCollider)
+// /// - 竖直方向:目标吃水深度 + PD 控制(稳定,不抖、不弹飞)
+// /// - 姿态:Righting Torque 扶正(受 Rigidbody.centerOfMass 影响)
+// /// - 入水比例:带平滑(避免水面附近开关抖动)
+// ///
+// [DisallowMultipleComponent]
+// [RequireComponent(typeof(Rigidbody))]
+// public class BuoyancyCapsuleSphere : MonoBehaviour
+// {
+// [Header("Collider (choose one)")] public CapsuleCollider capsule;
+// public SphereCollider sphere;
+//
+// [Header("Water")] public MonoBehaviour waterProviderBehaviour; // 可选
+// private IWaterProvider waterProvider;
+//
+// [Tooltip("没有 provider 时的水面高度")] public float waterLevel = 0f;
+//
+// [Header("Density -> Draft")] [Tooltip("水密度 kg/m^3(淡水约1000)")]
+// public float waterDensity = 1000f;
+//
+// [Tooltip("物体等效密度 kg/m^3。越小越浮。浮漂可 80~400 之间调")]
+// public float objectDensity = 250f;
+//
+// [Tooltip("额外浮力比例(手感调整)。1=按密度算")] public float buoyancyScale = 1f;
+//
+// [Header("Vertical PD (Stability key)")] [Tooltip("竖直弹簧强度(越大越“顶住”目标吃水)")]
+// public float verticalKp = 35f;
+//
+// [Tooltip("竖直阻尼(越大越不弹、不抖)")] public float verticalKd = 12f;
+//
+// [Tooltip("最大向上加速度 m/s^2(防止从高处落下入水被顶飞)")]
+// public float maxUpAccel = 25f;
+//
+// [Tooltip("最大向下加速度 m/s^2(防止强行拉下去造成抖动)")]
+// public float maxDownAccel = 10f;
+//
+// [Header("Submergence smoothing")] [Tooltip("入水比例变化速度(1/s)。越大越快响应,越小越稳")]
+// public float submergenceSpeed = 8f;
+//
+// [Tooltip("水面外的缓冲(m),让浮力更平滑接管")] public float surfaceMargin = 0.01f;
+//
+// [Header("Righting (Rotation)")] [Tooltip("扶正强度(把 transform.up 拉向水面法线/世界上)")]
+// public float rightingKp = 8f;
+//
+// [Tooltip("扶正阻尼(抑制旋转抖动)")] public float rightingKd = 3f;
+//
+// [Header("Water drag (optional but helpful)")] [Tooltip("入水时额外线阻尼(通过 rb.drag 混合)")]
+// public float extraLinearDragInWater = 2.5f;
+//
+// [Tooltip("入水时额外角阻尼(通过 rb.angularDrag 混合)")]
+// public float extraAngularDragInWater = 2.0f;
+//
+// [Header("Center of Mass")] [Tooltip("本地重心偏移:例如 (0,-0.02,0) 让底部更重、更容易站漂")]
+// public Vector3 centerOfMassOffset = Vector3.zero;
+//
+// private Rigidbody rb;
+// private float baseDrag, baseAngularDrag;
+//
+// // 关键:入水比例必须有“记忆”(滤波),否则水面边界必抖
+// private float subFiltered = 0f;
+//
+// void Reset()
+// {
+// rb = GetComponent();
+// rb.useGravity = true;
+// rb.interpolation = RigidbodyInterpolation.Interpolate;
+// rb.collisionDetectionMode = CollisionDetectionMode.Continuous;
+//
+// capsule = GetComponent();
+// sphere = GetComponent();
+// }
+//
+// void Awake()
+// {
+// rb = GetComponent();
+// rb.centerOfMass = centerOfMassOffset;
+//
+// baseDrag = rb.linearDamping;
+// baseAngularDrag = rb.angularDamping;
+//
+// waterProvider = waterProviderBehaviour as IWaterProvider;
+//
+// // 只允许一个
+// if (capsule != null && sphere != null)
+// sphere = null;
+// }
+//
+// void OnValidate()
+// {
+// objectDensity = Mathf.Max(1e-3f, objectDensity);
+// waterDensity = Mathf.Max(1e-3f, waterDensity);
+// submergenceSpeed = Mathf.Max(0.1f, submergenceSpeed);
+// surfaceMargin = Mathf.Max(0f, surfaceMargin);
+// maxUpAccel = Mathf.Max(0f, maxUpAccel);
+// maxDownAccel = Mathf.Max(0f, maxDownAccel);
+// }
+//
+// void FixedUpdate()
+// {
+// if (!capsule && !sphere) return;
+//
+// waterProvider = waterProviderBehaviour as IWaterProvider;
+//
+// GetCenterAndHeight(out var centerWorld, out var shapeHeight);
+//
+// // 水面信息
+// float waterH = waterProvider?.GetWaterHeight(centerWorld) ?? waterLevel;
+// Vector3 waterN = waterProvider?.GetWaterNormal(centerWorld) ?? Vector3.up;
+// if (waterN.sqrMagnitude < 1e-6f) waterN = Vector3.up;
+// waterN.Normalize();
+//
+// // 当前中心“浸没深度”(>0 表示中心在水下)
+// float centerDepth = waterH - centerWorld.y;
+//
+// // 近似入水比例:centerDepth = -H/2 -> 0; centerDepth = +H/2 -> 1
+// float rawSub = Mathf.Clamp01((centerDepth + (shapeHeight * 0.5f) + surfaceMargin) /
+// (shapeHeight + 2f * surfaceMargin));
+//
+// // 入水比例滤波(非常关键)
+// float dt = Time.fixedDeltaTime;
+// subFiltered = Mathf.MoveTowards(subFiltered, rawSub, submergenceSpeed * dt);
+//
+// // 混合拖拽(让水中更稳)
+// rb.linearDamping = Mathf.Lerp(baseDrag, baseDrag + extraLinearDragInWater, subFiltered);
+// rb.angularDamping = Mathf.Lerp(baseAngularDrag, baseAngularDrag + extraAngularDragInWater, subFiltered);
+//
+// if (subFiltered <= 1e-4f)
+// return; // 基本没入水,不做任何浮力/扶正
+//
+// // 目标吃水比例:理想静态平衡 ≈ objectDensity / waterDensity(<1 才会浮)
+// float desiredSub = Mathf.Clamp01((objectDensity / waterDensity) * buoyancyScale);
+//
+// // 把 desiredSub 转成目标中心深度
+// // desiredSub=0 -> centerDepthTarget = -H/2(完全出水)
+// // desiredSub=1 -> centerDepthTarget = +H/2(完全入水)
+// float centerDepthTarget = desiredSub * shapeHeight - shapeHeight * 0.5f;
+//
+// // 竖直 PD:只沿“世界上/重力反方向”控制,最稳
+// Vector3 up = (-Physics.gravity).sqrMagnitude > 1e-6f ? (-Physics.gravity).normalized : Vector3.up;
+// float vUp = Vector3.Dot(rb.linearVelocity, up);
+//
+// float error = centerDepth - centerDepthTarget; // 深了为正 -> 需要向上推
+// float accelUp = (-verticalKp * error) - (verticalKd * vUp);
+//
+// // 限制上下加速度,避免顶飞或强拉抖动
+// accelUp = Mathf.Clamp(accelUp, -maxDownAccel, maxUpAccel);
+//
+// // 随入水比例渐入(避免水面边界突然接管)
+// accelUp *= subFiltered;
+//
+// // 施加竖直加速度(Acceleration 不受质量影响,更稳定)
+// rb.AddForce(up * accelUp, ForceMode.Acceleration);
+//
+// // 扶正力矩:把物体 up 拉向 waterN(平静水就是 Vector3.up)
+// // 注意:这个扶正与重心偏移一起工作,会形成“站漂/躺漂”的稳定姿态
+// Vector3 currentUp = transform.up;
+// Vector3 axis = Vector3.Cross(currentUp, waterN);
+//
+// // 小角度近似:axis 的大小约等于 sin(theta)
+// // 扶正加速度型扭矩(同样用 Acceleration,减少质量/惯量差带来的抖动)
+// Vector3 angVel = rb.angularVelocity;
+// Vector3 torqueAccel = axis * rightingKp - angVel * rightingKd;
+//
+// torqueAccel *= subFiltered;
+//
+// rb.AddTorque(torqueAccel, ForceMode.Acceleration);
+// }
+//
+// private void GetCenterAndHeight(out Vector3 centerWorld, out float heightWorld)
+// {
+// if (sphere)
+// {
+// // sphere:center + 半径*缩放(近似取最大缩放)
+// Transform t = sphere.transform;
+// centerWorld = t.TransformPoint(sphere.center);
+//
+// Vector3 s = t.lossyScale;
+// float r = sphere.radius * Mathf.Max(Mathf.Abs(s.x), Mathf.Abs(s.y), Mathf.Abs(s.z));
+// heightWorld = Mathf.Max(1e-6f, r * 2f);
+// return;
+// }
+//
+// // capsule
+// Transform ct = capsule.transform;
+// centerWorld = ct.TransformPoint(capsule.center);
+//
+// Vector3 ls = ct.lossyScale;
+// float sx = Mathf.Abs(ls.x), sy = Mathf.Abs(ls.y), sz = Mathf.Abs(ls.z);
+//
+// float heightScale = capsule.direction switch
+// {
+// 0 => sx,
+// 1 => sy,
+// _ => sz,
+// };
+//
+// heightWorld = Mathf.Max(1e-6f, capsule.height * heightScale);
+// }
+// }
\ No newline at end of file
diff --git a/Assets/Scripts/Test/BuoyancyWaterProvider.cs b/Assets/Scripts/Test/BuoyancyWaterProvider.cs
index 0d41fd8f6..f4af21b5f 100644
--- a/Assets/Scripts/Test/BuoyancyWaterProvider.cs
+++ b/Assets/Scripts/Test/BuoyancyWaterProvider.cs
@@ -1,7 +1,10 @@
using UnityEngine;
+using WaveHarmonic.Crest;
public class BuoyancyWaterProvider : MonoBehaviour, IWaterProvider
{
+ public WaterRenderer Water;
+ readonly SampleFlowHelper _SampleFlowHelper = new();
public float waterLevel = 0f;
public float GetWaterHeight(Vector3 worldPos)
diff --git a/Assets/Scripts/Test/CapsuleBuoyancyStable.cs b/Assets/Scripts/Test/CapsuleBuoyancyStable.cs
index 5f8cb469c..a5d152043 100644
--- a/Assets/Scripts/Test/CapsuleBuoyancyStable.cs
+++ b/Assets/Scripts/Test/CapsuleBuoyancyStable.cs
@@ -1,46 +1,62 @@
-using UnityEngine;
+using System;
+using Gaia;
+using UnityEngine;
+using WaveHarmonic.Crest;
[DisallowMultipleComponent]
[RequireComponent(typeof(Rigidbody), typeof(CapsuleCollider))]
public class CapsuleBuoyancyStable : MonoBehaviour
{
- [Header("References")]
- public MonoBehaviour WaterBehaviour; // 实现 IWaterProvider
- private IWaterProvider Water => WaterBehaviour as IWaterProvider;
-
- [Header("Buoyancy")]
- [Tooltip("完全浸没时总浮力 = mass*g*buoyancyScale。>1 更浮。")]
+ [Header("Buoyancy")] [Tooltip("完全浸没时总浮力 = mass*g*buoyancyScale。>1 更浮。")]
public float buoyancyScale = 1.6f;
- [Tooltip("沿胶囊轴向采样点数量(建议 7~11)。")]
- [Range(3, 15)] public int samplePoints = 9;
+ [Tooltip("沿胶囊轴向采样点数量(建议 7~11)。")] [Range(3, 15)]
+ public int samplePoints = 9;
- [Tooltip("浸没比例曲线(0=刚碰水, 1=充分在水下)。")]
- public AnimationCurve submergenceCurve = AnimationCurve.Linear(0, 0, 1, 1);
+ [Tooltip("浸没比例曲线(0=刚碰水, 1=充分在水下)。")] public AnimationCurve submergenceCurve = AnimationCurve.Linear(0, 0, 1, 1);
- [Header("Damping")]
- [Tooltip("上浮方向速度阻尼(越大越不弹)。")]
+ [Header("Damping")] [Tooltip("上浮方向速度阻尼(越大越不弹)。")]
public float verticalDamping = 3.0f;
- [Tooltip("整体角速度阻尼(只施加一次,不要太大)。")]
- public float angularDamping = 0.6f;
+ [Tooltip("整体角速度阻尼(只施加一次,不要太大)。")] public float angularDamping = 0.6f;
- [Header("Optional Upright Stabilizer (Recommended for bobber)")]
- [Tooltip("让胶囊轴向更倾向于对齐世界Up。0=关闭。")]
+ [Header("Optional Upright Stabilizer (Recommended for bobber)")] [Tooltip("让胶囊轴向更倾向于对齐世界Up。0=关闭。")]
public float uprightSpring = 0.0f;
- [Tooltip("upright 的角速度阻尼。")]
- public float uprightDamping = 0.5f;
+ [Tooltip("upright 的角速度阻尼。")] public float uprightDamping = 0.5f;
[Tooltip("胶囊轴向:0=X,1=Y,2=Z(通常 CapsuleCollider.direction 也一样)。")]
public int uprightAxis = 1;
- [Header("Water Drag")]
- public float extraDragInWater = 0.8f;
+ [Header("Water Drag")] public float extraDragInWater = 0.8f;
public float extraAngularDragInWater = 0.8f;
- [Header("Debug")]
- public bool drawDebug = false;
+ #region Crest5相关信息
+
+ public Transform Water;
+
+ private WaterRenderer _waterRenderer;
+
+ [Tooltip("要瞄准哪一层水的碰撞层。")] [SerializeField]
+ CollisionLayer _Layer = CollisionLayer.AfterAnimatedWaves;
+
+ [Header("波响应")] [Tooltip("用于物理计算的物体宽度。\n\n此值越大,波响应的滤波效果和平滑程度就越高。如果无法对较大波长进行滤波,则应增加 LOD 级别。")] [SerializeField]
+ float _ObjectWidth = 3f;
+
+ readonly SampleFlowHelper _SampleFlowHelper = new();
+
+ ///
+ /// 查询水面信息点位
+ ///
+ Vector3[] _QueryPoints;
+
+ Vector3[] _QueryResultDisplacements;
+ Vector3[] _QueryResultVelocities;
+ Vector3[] _QueryResultNormal;
+
+ #endregion
+
+ [Header("Debug")] public bool drawDebug = false;
Rigidbody _rb;
CapsuleCollider _cap;
@@ -52,15 +68,30 @@ public class CapsuleBuoyancyStable : MonoBehaviour
_cap = GetComponent();
_baseDrag = _rb.linearDamping;
_baseAngularDrag = _rb.angularDamping;
+ }
- if (WaterBehaviour != null && Water == null)
- Debug.LogError($"{name}: WaterBehaviour 没有实现 IWaterProvider。", this);
+ private 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();
}
void FixedUpdate()
{
- if (Water == null) return;
+ if (Water)
+ {
+
+ }
+ if (!_waterRenderer)
+ {
+ return;
+ }
GetWorldCapsule(out Vector3 a, out Vector3 b, out float radius);
int n = Mathf.Max(3, samplePoints);
@@ -70,12 +101,27 @@ public class CapsuleBuoyancyStable : MonoBehaviour
float subSum = 0f;
int wetCount = 0;
+ for (int i = 0; i < _QueryPoints.Length; i++)
+ {
+ float t = (float)i / (n - 1);
+ Vector3 p = Vector3.Lerp(a, b, t);
+ _QueryPoints[i] = p;
+ }
+
+
+ // 查询
+ var collisions = _waterRenderer.AnimatedWavesLod.Provider;
+ collisions.Query(GetHashCode(), _ObjectWidth, _QueryPoints, _QueryResultDisplacements,
+ _QueryResultNormal, _QueryResultVelocities, _Layer);
+
+
for (int i = 0; i < n; i++)
{
float t = (float)i / (n - 1);
Vector3 p = Vector3.Lerp(a, b, t);
- float waterH = Water.GetWaterHeight(p);
+ float waterH =
+ _QueryResultDisplacements[i].y + _waterRenderer.SeaLevel; //GaiaConstants.Water.GetWaterHeight(p);
float depth = waterH - p.y; // >0 在水下
float sub = Mathf.InverseLerp(-radius, radius, depth); // 0..1
@@ -87,7 +133,8 @@ public class CapsuleBuoyancyStable : MonoBehaviour
Vector3 buoyDir = Vector3.up;
- Vector3 waterVel = Water.GetWaterVelocity(p);
+ // Vector3 waterVel = GaiaConstants.Water.GetWaterVelocity(p);
+ Vector3 waterVel = _QueryResultVelocities[i];
Vector3 pointVel = _rb.GetPointVelocity(p);
Vector3 relVel = pointVel - waterVel;
@@ -184,8 +231,8 @@ public class CapsuleBuoyancyStable : MonoBehaviour
a = center - half;
b = center + half;
}
-
-
+
+
private void OnDrawGizmosSelected()
{
if (drawDebug)