Files
Fishing2/Assets/Scripts/Test/CapsuleBuoyancy.cs
2026-03-02 23:54:11 +08:00

95 lines
2.8 KiB
C#

using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(CapsuleCollider))]
public class CapsuleBuoyancy : MonoBehaviour
{
[Header("Water Settings")]
public float waterHeight = 0f; // 水面高度
public float waterDensity = 1000f; // 水密度
[Header("Buoyancy Settings")]
public int samplePoints = 8; // 采样点数量
public float buoyancyMultiplier = 1.0f; // 浮力强度调节
public float waterDrag = 1.5f; // 水阻力
public float waterAngularDrag = 1.5f; // 水角阻力
private Rigidbody rb;
private CapsuleCollider capsule;
private float capsuleVolume;
private float gravity;
void Start()
{
rb = GetComponent<Rigidbody>();
capsule = GetComponent<CapsuleCollider>();
gravity = Physics.gravity.magnitude;
CalculateCapsuleVolume();
}
void FixedUpdate()
{
ApplyBuoyancy();
}
void CalculateCapsuleVolume()
{
float radius = capsule.radius * Mathf.Max(transform.localScale.x, transform.localScale.z);
float height = Mathf.Max(0, capsule.height * transform.localScale.y - 2f * radius);
float cylinderVolume = Mathf.PI * radius * radius * height;
float sphereVolume = (4f / 3f) * Mathf.PI * radius * radius * radius;
capsuleVolume = cylinderVolume + sphereVolume;
}
void ApplyBuoyancy()
{
float submergedRatioTotal = 0f;
for (int i = 0; i < samplePoints; i++)
{
float t = (float)i / (samplePoints - 1);
Vector3 localPoint = Vector3.up * Mathf.Lerp(
-capsule.height * 0.5f + capsule.radius,
capsule.height * 0.5f - capsule.radius,
t);
Vector3 worldPoint = transform.TransformPoint(localPoint);
float depth = waterHeight - worldPoint.y;
if (depth > 0f)
{
float normalizedDepth = Mathf.Clamp01(depth / (capsule.height / samplePoints));
submergedRatioTotal += normalizedDepth;
float forceMagnitude =
waterDensity *
gravity *
(capsuleVolume / samplePoints) *
normalizedDepth *
buoyancyMultiplier;
Vector3 buoyancyForce = Vector3.up * forceMagnitude;
rb.AddForceAtPosition(buoyancyForce, worldPoint, ForceMode.Force);
}
}
// 如果在水中,加阻力
if (submergedRatioTotal > 0f)
{
rb.linearDamping = waterDrag;
rb.angularDamping = waterAngularDrag;
}
else
{
rb.linearDamping = 0f;
rb.angularDamping = 0.05f;
}
}
}