浮漂逻辑
This commit is contained in:
95
Assets/Scripts/Test/CapsuleBuoyancy.cs
Normal file
95
Assets/Scripts/Test/CapsuleBuoyancy.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user