You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中实现物体水面漂浮 解决波浪Shader下浮力计算异常问题

波浪水面船只浮力逻辑修复方案

你当前的问题根源是水面波浪仅在Shader渲染阶段修改了网格顶点位置,并未同步修改Transform或物理层数据,因此原有逻辑无法识别动态水面高度。可通过以下方案实现准确的动态浮力计算:

核心思路

复用Shader中使用的波浪计算逻辑,在C#侧实时计算每个漂浮点对应(x,z)坐标位置的水面高度,替换原有固定的Water.position.y进行浮力判定。
船只位于浪峰下方的示意图

实现代码示例

以下为修改后的Floater脚本,默认适配最常用的多层正弦波波浪效果,你只需将波浪参数调整为和Shader中一致即可:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Floater : MonoBehaviour
{
    public float depthBeforeSubmerged = 1f;
    public float displacementAmount = 3f;
    public Transform[] floatPoints;
    public Transform Water;
    
    // 波浪参数,需和Shader内参数完全一致
    public float waveAmplitude = 0.5f; // 浪高
    public float waveFrequency = 2f; // 浪密度
    public float waveSpeed = 1f; // 浪移动速度

    private Rigidbody rb;

    private void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        foreach (Transform t in floatPoints)
        {
            // 计算当前漂浮点对应位置的水面高度
            float waterY = GetWaveHeight(t.position.x, t.position.z);
            if (t.position.y < waterY) {
                // 用动态水面高度替换原有固定高度计算浮力
                float submergeDepth = waterY - t.position.y;
                float displacementMultiplyer = Mathf.Clamp01(submergeDepth / depthBeforeSubmerged) 
                    * displacementAmount;

                rb.AddForceAtPosition(new Vector3(0f, Mathf.Abs(Physics.gravity.y) * 
                displacementMultiplyer, 0f), t.position,ForceMode.Acceleration);
            }
        }
    }

    // 波浪高度计算方法,逻辑和Shader内保持完全一致
    private float GetWaveHeight(float x, float z)
    {
        // 基础正弦波计算,如果你用的是Gerstner波或其他波浪逻辑,替换此处即可
        float wave1 = Mathf.Sin(x * waveFrequency + Time.time * waveSpeed) * waveAmplitude;
        float wave2 = Mathf.Sin(z * waveFrequency * 0.7f + Time.time * waveSpeed * 1.2f) * waveAmplitude * 0.6f;
        return Water.position.y + wave1 + wave2;
    }
}

可选方案

  • 如果你的波浪逻辑非常复杂不想重复写两遍,可以将波浪计算逻辑放到Compute Shader中,同时输出高度数据给渲染管线和C#逻辑层,适合大范围水面、多漂浮物的场景
  • 临时测试可以给水面添加Mesh Collider,每帧同步Shader变形后的网格到碰撞体,通过射线检测获取对应位置的水面高度,但性能开销较高,不建议正式版本使用

注意事项

  • 所有波浪参数必须和Shader中的参数完全同步,否则会出现浮力计算和水面渲染错位的问题
  • 船只漂浮点建议控制在4~16个,足够覆盖中小型船只的浮力模拟,过多会造成不必要的性能损耗
  • 如果使用Gerstner波,需要同步计算顶点的横向偏移,避免浪尖位置浮力计算偏差

内容的提问来源于stack exchange,提问作者Eternal hunter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 00:15:08