Search Unity

Floating in water

Discussion in 'Scripting' started by Sam Shiels, Oct 25, 2007.

  1. Sam Shiels

    Sam Shiels

    Joined:
    Feb 25, 2007
    Posts:
    160
    How can I make a rigidbody float up and down in water?
     
  2. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,434
    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.
     
  3. jeffcraighead

    jeffcraighead

    Joined:
    Nov 15, 2006
    Posts:
    740
    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.


    Code (csharp):
    1.  
    2.  
    3. // density here is killograms per cubic meter. Unity's world units are meters and mass is commonly assumed to be killograms
    4.   // Density of wood: 600 kg / cu.m
    5.   // Density of water 1000 kg / cu meter
    6.   // Density of iron 7000 kg / cu meter
    7.   // densityOfBody = b.mass / curBodiesVolume[i];
    8.  
    9. var divider = 1.0;
    10.  
    11. var airborneDrag = -1.0; //If left at -1 will use the Rigidbody Drag
    12. var fluidDrag = 0.0;
    13.  
    14. private var fluidDensity = 1000.0;
    15. private var displacement = 0.0;
    16.  
    17. private var myRenderer : Renderer;
    18. private var myRB : Rigidbody;
    19. private var myColliders : Array;
    20.  
    21. private var timer = 0.0;
    22.  
    23. function Start(){
    24.     var renderers = transform.root.gameObject.GetComponentsInChildren(Renderer);
    25.     var rendMax = Vector3(0,0,0);
    26.     for (var ren : Renderer in renderers){
    27.         if(ren.bounds.size.sqrMagnitude>rendMax.sqrMagnitude){
    28.             rendMax = ren.bounds.size;
    29.             myRenderer=ren;
    30.         }
    31.     }
    32.        
    33.     if(myRB==null) myRB = GetComponent(Rigidbody);
    34.     if(myColliders==null) myColliders = GetComponentsInChildren(Collider);
    35.     for(var col : Collider in myColliders){
    36.         displacement += col.bounds.size.x*col.bounds.size.y*col.bounds.size.z;
    37.     }
    38.     displacement = displacement/divider;
    39.    
    40.     if(airborneDrag<0)airborneDrag = myRB.drag;
    41. }
    42.  
    43.  
    44. function OnTriggerEnter(c : Collider){
    45.     if(c.tag=="fluid") myRB.drag=fluidDrag;
    46.    
    47. }
    48. function OnTriggerStay(c : Collider){
    49.         if(myRenderer==null)return;
    50.         var timetemp = Time.realtimeSinceStartup;
    51.         if(c.tag=="fluid"){
    52.             var surfaceYPos = c.transform.position.y;
    53.  
    54.             var bottom : Vector3 = transform.position;
    55.  
    56.             for(var col : Collider in myColliders){
    57.                 if(col==null) continue;
    58.                 var temp = col.ClosestPointOnBounds(transform.position-Vector3(0,100,0));
    59.                 if(temp.y<bottom.y) bottom = temp;
    60.             }
    61.                        
    62.             var bottomToSurface : float = (surfaceYPos-bottom.y);
    63.             var bottomToCenter : float = (bottom - myRenderer.bounds.center).magnitude;
    64.            
    65.             var pctSubmerged : float = Mathf.Clamp01(bottomToSurface/(bottomToCenter*2));
    66.             var force : Vector3 = displacement*fluidDensity*pctSubmerged*-1*Physics.gravity;
    67.             bottom = Vector3.Lerp(bottom,transform.position,0.75);
    68.             myRB.AddForceAtPosition(force,bottom);
    69.         }
    70.         timer += Time.realtimeSinceStartup-timetemp;
    71. }
    72.  
    73. function OnTriggerExit(c : Collider){
    74.     if(c.tag=="fluid")  myRB.drag=airborneDrag;
    75. }
    76.  
    77.  
    78.  
     
  4. Sam Shiels

    Sam Shiels

    Joined:
    Feb 25, 2007
    Posts:
    160
    Thanks! :D