Floating in water

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! :smile: