public void ApplyForceToRB(ShapeGerstnerBatched _waves, Rigidbody _rb) { Vector3 undispPos = _waves.GetPositionDisplacedToPosition(ref _position, 0f); Vector3 displacement = _waves.SampleDisplacement(ref undispPos, 0f); float height = OceanRenderer.Instance.SeaLevel + displacement.y; Vector3 onSeaLevel = _position; onSeaLevel.y = OceanRenderer.Instance.SeaLevel; // h is the height of the water relative to the center of the sphere float h = height - _position.y + _r; h = Mathf.Min(h, 2f * _r); float submergedness = Mathf.Clamp01(h / (2f * _r)); if (submergedness < 0.001f) { // not in water return; } // volume of spherical cap, from https://en.wikipedia.org/wiki/Spherical_cap float Vdisp = Mathf.PI * h * h * (3f * _r - h) / 3f; // scale up to full volume //float Vfull = 4f * Mathf.PI * _r * _r * _r / 3f; float V = Vdisp;// _volume * Vdisp / Vfull; float rotAmt = .1f; float F = V * _waterDensity * Physics.gravity.magnitude; _rb.AddForceAtPosition(-F * Physics.gravity.normalized, Vector3.Lerp(_rb.position, _position, rotAmt)); Debug.DrawLine(_position, _position - F * Physics.gravity.normalized, Color.red * 0.5f); // apply drag relative to water var vel = _waves.GetSurfaceVelocity(ref undispPos, 0f); var deltaV = _rb.velocity - vel; // approximation - interpolate drag based on how submerged the sphere is _rb.AddForceAtPosition(-submergedness * _dragInWater * deltaV, Vector3.Lerp(_rb.position, _position, rotAmt)); Debug.DrawLine(_position, _position - submergedness * _dragInWater * deltaV, Color.white); }