How can I make a rigidbody float up and down in water?
Lots of ways to do this, depends how you’ve created your water waves. Assuming it’s a mesh that’s being manipulated through script, take an invisible “surface object” (a plane or box with collider and rigid body) and attach your floating object to it with a spring joint. That way your floating object reacts in a very realistic manner: you can simulate heavier objects with looser springs, etc.
The other way is to do it with script, and I think Yoggy’s boat demo a while back did this.
Another solution is to use the physics system to add buoyancy forces when the object enters a trigger. I’m using this method with a “buoyant object” script. Any rigidbody entering a trigger tagged with “fluid” has buoyant forces added based on the objects volume. This code is based on an example that was posted on the forums quite a while ago, though I’ve changed quite a bit after many revisions.
// density here is killograms per cubic meter. Unity's world units are meters and mass is commonly assumed to be killograms
// Density of wood: 600 kg / cu.m
// Density of water 1000 kg / cu meter
// Density of iron 7000 kg / cu meter
// densityOfBody = b.mass / curBodiesVolume[i];
var divider = 1.0;
var airborneDrag = -1.0; //If left at -1 will use the Rigidbody Drag
var fluidDrag = 0.0;
private var fluidDensity = 1000.0;
private var displacement = 0.0;
private var myRenderer : Renderer;
private var myRB : Rigidbody;
private var myColliders : Array;
private var timer = 0.0;
function Start(){
var renderers = transform.root.gameObject.GetComponentsInChildren(Renderer);
var rendMax = Vector3(0,0,0);
for (var ren : Renderer in renderers){
if(ren.bounds.size.sqrMagnitude>rendMax.sqrMagnitude){
rendMax = ren.bounds.size;
myRenderer=ren;
}
}
if(myRB==null) myRB = GetComponent(Rigidbody);
if(myColliders==null) myColliders = GetComponentsInChildren(Collider);
for(var col : Collider in myColliders){
displacement += col.bounds.size.x*col.bounds.size.y*col.bounds.size.z;
}
displacement = displacement/divider;
if(airborneDrag<0)airborneDrag = myRB.drag;
}
function OnTriggerEnter(c : Collider){
if(c.tag=="fluid") myRB.drag=fluidDrag;
}
function OnTriggerStay(c : Collider){
if(myRenderer==null)return;
var timetemp = Time.realtimeSinceStartup;
if(c.tag=="fluid"){
var surfaceYPos = c.transform.position.y;
var bottom : Vector3 = transform.position;
for(var col : Collider in myColliders){
if(col==null) continue;
var temp = col.ClosestPointOnBounds(transform.position-Vector3(0,100,0));
if(temp.y<bottom.y) bottom = temp;
}
var bottomToSurface : float = (surfaceYPos-bottom.y);
var bottomToCenter : float = (bottom - myRenderer.bounds.center).magnitude;
var pctSubmerged : float = Mathf.Clamp01(bottomToSurface/(bottomToCenter*2));
var force : Vector3 = displacement*fluidDensity*pctSubmerged*-1*Physics.gravity;
bottom = Vector3.Lerp(bottom,transform.position,0.75);
myRB.AddForceAtPosition(force,bottom);
}
timer += Time.realtimeSinceStartup-timetemp;
}
function OnTriggerExit(c : Collider){
if(c.tag=="fluid") myRB.drag=airborneDrag;
}
Thanks! ![]()