using UnityEngine; public class FloatBobberController : MonoBehaviour { [SerializeField] private Rigidbody _rigidbody; [Header("水属性")] public float waterLevel = 0f; [Header("浮漂最大浮力")] public float bobberVolume = 30f; // 浮漂最大浮力 (cm³) public float bobberHeight = 0.25f; // 浮漂长度,用来决定躺漂角度 [Header("配件重量")] public float sinkerWeight = 2f; public float baitWeight = 0.5f; public float hookWeight = 0.2f; [Header("Behaviour")] public float fallSpeed = 8f; public float riseSpeed = 3f; // public float smoothDamping = 8f; // 插值平滑 [Header("Noise")] public float noiseAmp = 0.015f; public float noiseFreq = 1.5f; float impulseForce = 0f; float impulseDecay = 4f; void FixedUpdate() { SimulateBobber(); } void SimulateBobber() { if (!_rigidbody.isKinematic) return; float totalDownwardWeight = sinkerWeight + baitWeight + hookWeight; float maxBuoyancy = bobberVolume; // 最大浮力 = 体积 float netBuoyancy = maxBuoyancy - totalDownwardWeight; float targetY; // ------------------------- // 1. 判断浮漂应该沉多少(吃水深度) // ------------------------- if (netBuoyancy > 0) { float buoyPercent = Mathf.Clamp01(netBuoyancy / maxBuoyancy); float rise = buoyPercent * 0.1f; // 浮漂露出水面的高度 targetY = waterLevel + rise; } else { // 净浮力为负 → 说明浮漂整体被拉下,沉入水中 float sinkDistance = Mathf.Abs(netBuoyancy) * 0.03f; targetY = waterLevel - sinkDistance; } targetY += Mathf.Sin(Time.time * noiseFreq) * noiseAmp; // 微扰模拟波浪 // 顿口/顶漂力 if (impulseForce != 0f) { targetY += impulseForce * Time.deltaTime; impulseForce = Mathf.Lerp(impulseForce, 0, Time.deltaTime * impulseDecay); } // ----------------------------- // ③ 上浮 / 下沉差速 // ----------------------------- float y = transform.position.y; float diff = targetY - y; if (diff > 0) // 上浮 y += diff * Time.deltaTime * riseSpeed; else y += diff * Time.deltaTime * fallSpeed; transform.position = new Vector3(transform.position.x, y, transform.position.z); } // ---------------------------------------- // 外部控制接口 // ---------------------------------------- public void TriggerDownPulse(float s = 0.8f) { impulseForce -= Mathf.Abs(s); } public void TriggerUpPulse(float s = 0.8f) { impulseForce += Mathf.Abs(s); } public void AddFishPull(float v) { sinkerWeight += v; } public void ReleaseFishPull(float v) { sinkerWeight -= v; } }