浮力
This commit is contained in:
169
Assets/Scripts/FloatBobberControllerPro.cs
Normal file
169
Assets/Scripts/FloatBobberControllerPro.cs
Normal file
@@ -0,0 +1,169 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class FloatBobberControllerPro : MonoBehaviour
|
||||
{
|
||||
[Header("Water")]
|
||||
public float waterLevel = 0f;
|
||||
|
||||
[Header("Bobber Physical")]
|
||||
public float bobberVolume = 30f; // 浮漂最大浮力 (cm³)
|
||||
public float bobberMass = 1f; // 浮漂自重 (g)
|
||||
public float bobberHeight = 0.25f; // 浮漂长度,用来决定躺漂角度
|
||||
|
||||
[Header("Tackle Weight")]
|
||||
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 angleLaySpeed = 2f; // 躺漂速度
|
||||
public float uprightSpeed = 2f; // 立漂速度
|
||||
public float bottomDrag = 1.2f; // 铅坠触底阻力(越大越难被浮漂拉起)
|
||||
|
||||
[Header("Angles")]
|
||||
public float maxLayAngle = 75f; // 最大躺漂角度
|
||||
float currentAngle = 0f;
|
||||
|
||||
[Header("Noise")]
|
||||
public float noiseAmp = 0.015f;
|
||||
public float noiseFreq = 1.5f;
|
||||
|
||||
float impulseForce = 0f;
|
||||
float impulseDecay = 4f;
|
||||
|
||||
void Update()
|
||||
{
|
||||
SimulateBobber();
|
||||
}
|
||||
|
||||
void SimulateBobber()
|
||||
{
|
||||
float totalWeight = bobberMass + sinkerWeight + baitWeight + hookWeight;
|
||||
float netBuoyancy = bobberVolume - totalWeight; // 正 → 上浮;负 → 下拉
|
||||
|
||||
// -----------------------------
|
||||
// ① 计算浮漂底部 Y 的高度
|
||||
// -----------------------------
|
||||
float bobberBottomY = transform.position.y - bobberHeight * 0.5f;
|
||||
float bottomY = waterLevel - 0.02f; // 水底高度(可替换真实地形)
|
||||
|
||||
bool sinkerOnBottom = (bobberBottomY <= bottomY);
|
||||
|
||||
// -----------------------------
|
||||
// ② 计算 targetY
|
||||
// -----------------------------
|
||||
float targetY;
|
||||
|
||||
if (!sinkerOnBottom)
|
||||
{
|
||||
// 铅坠悬浮 → 浮漂直立
|
||||
if (netBuoyancy > 0)
|
||||
{
|
||||
float rise = Mathf.Clamp01(netBuoyancy / bobberVolume) * 0.1f;
|
||||
targetY = waterLevel + rise;
|
||||
}
|
||||
else
|
||||
{
|
||||
float sink = Mathf.Abs(netBuoyancy) * 0.02f;
|
||||
targetY = waterLevel - sink;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 铅坠触底 → 浮漂无法再被向下拉
|
||||
if (netBuoyancy > bottomDrag)
|
||||
{
|
||||
// 浮漂浮力足够将其立起来
|
||||
float rise = Mathf.Clamp01((netBuoyancy - bottomDrag) / bobberVolume) * 0.1f;
|
||||
targetY = waterLevel + rise; // 轻轻立起
|
||||
}
|
||||
else
|
||||
{
|
||||
// 浮漂浮力不足 → 躺漂
|
||||
targetY = waterLevel + 0.01f; // 漂身贴水
|
||||
}
|
||||
}
|
||||
|
||||
// 水波噪声
|
||||
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);
|
||||
|
||||
// -----------------------------
|
||||
// ④ 浮漂角度控制
|
||||
// -----------------------------
|
||||
float targetAngle = 0f;
|
||||
|
||||
if (sinkerOnBottom)
|
||||
{
|
||||
// 触底 → 判断是否能立漂
|
||||
if (netBuoyancy > bottomDrag)
|
||||
{
|
||||
targetAngle = 0f; // 立漂
|
||||
}
|
||||
else
|
||||
{
|
||||
// 躺漂
|
||||
targetAngle = maxLayAngle;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 铅坠在水中 → 漂直立
|
||||
targetAngle = 0f;
|
||||
}
|
||||
|
||||
// 平滑角度
|
||||
currentAngle = Mathf.Lerp(
|
||||
currentAngle,
|
||||
targetAngle,
|
||||
Time.deltaTime * (targetAngle == 0 ? uprightSpeed : angleLaySpeed)
|
||||
);
|
||||
|
||||
transform.rotation = Quaternion.Euler(currentAngle, 0, 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
// 外部控制接口
|
||||
// ----------------------------------------
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user