Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

floating a object on water

Discussion in 'Scripting' started by arshiyan, Oct 6, 2009.

  1. arshiyan

    arshiyan

    Joined:
    Aug 24, 2009
    Posts:
    8
    Hi,I've a problem,how can i floating a object(ship) on the water? :eek:
     
  2. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Welcome to the forum Tahamtan!

    You can create a simple buoyancy effect by adding a force to your object depending on how high it is above the water level. When it is exactly at the water level, the force should be exactly equal to gravity. Above a certain height, the object is completely out of the water and gets no lift from floating.

    The key to getting a good floating effect is that the place where the buoyancy force is applied is not generally the same as the object's centre of mass. For example, a car's centre of mass will be located near the engine, but its "centre of buoyancy" will be in the passenger compartment where all the air is.

    I've attached an example project with a script that applies forces to a simple object. It works OK for a floating object with a fairly regular shape, but you might want to add more points of buoyancy if you are modelling, say, a large boat.

    Post again if you have any questions about this.
     

    Attached Files:

  3. arshiyan

    arshiyan

    Joined:
    Aug 24, 2009
    Posts:
    8
    Thank you very much, you`re the best :p
     
  4. steveo

    steveo

    Joined:
    Nov 13, 2009
    Posts:
    13
    Hey Andeeee,

    I've been looking for a similar 'lightweight' bouyancy script but am having trouble importing your unity package. It seems to unzip as a folder instead of a unitypackage.

    Any chance of reuploading (I'm using Unity Indie 2.6 if that is the problem?) and perhaps a tiny rundown of whats happening in the script and/or how to apply it?

    Cheers

    Steveo
     
  5. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    If the .unitypackage file is appearing as a folder, it is because the browser or unzip program is not stopping after the first decompression (the package itself is a compressed file). I think you can just re-zip the folder once and rename it with a .unitypackage suffix. Either that or turn off automatic decompression in the browser when you download it.

    Anyway... the basic concept behind buoyancy is that the object is being pulled down by gravity, but there is an uplifting force supplied by the water. The uplift increases with the object's depth. So, for a buoyant object, there is a kind of balance point where the gravity pulling down is equal to the uplift. Floating an object, then, is a matter of defining a level for the surface of the water and applying an upward force proportional to the distance of the object below the water level.

    By default, gravity and other forces are applied at the rigidbody's centre of mass. However, you get a much more interesting buoyancy effect if you apply the uplift in a slightly different position in the object, a "centre of buoyancy", so to speak. (If you think about a car floating/sinking, the mass is concentrated around the engine, but the passenger compartment is where all the air is.) You can use rigidbody.AddForceAtPosition to apply the uplift somewhere other than the centre of mass.

    A slight complication is that any balancing of forces like this will tend to make the object oscillate endlessly back and forth around the balance point. In a situation like this, you can damp the oscillation by reducing the force applied in proportion to the speed the object is moving. An analogy for this is that it is easy to push down firmly on a bicycle's pedals when it is moving slowly, but they move away from under your feet when it is going fast.

    So... the script firstly establishes where the object's centre of buoyancy is. It then calculates how far below the water level that point currently is. The uplift is exactly equal to gravity when this point is exactly at the water level, but increases in proportion to the object's depth. An amount proportional to the object's upward speed is then subtracted from the uplift force (this is the damping) and the resulting force is applied at the centre of buoyancy.

    Like many physics scripts, it's a few lines of code but a lot more lines of text to explain ;-)
     
    Ignacii likes this.
  6. steveo

    steveo

    Joined:
    Nov 13, 2009
    Posts:
    13
    Whoa, that was much more than i expected! Yep got it working, thanks heaps for your help mate.

    Steveo
     
  7. UgameX

    UgameX

    Joined:
    Jun 17, 2008
    Posts:
    69
    Hi! I loved the Buoyancy script, it worked great! I was working on adapting it for my game, but I realized that it was in C#, a language in which I am clueless. I wondered about doing a raycast to find the distance to the ground so the script could constantly update the water level (i'm working on a hovercar style game), but I only know javascript. Would you know how to do a raycast in C#, or happen to have a javascript version of this lying around?
     
  8. Project009

    Project009

    Joined:
    Jan 11, 2010
    Posts:
    3
    thanks for the brief physics lesson and the script really helped me out.
     
  9. DangerSnoot

    DangerSnoot

    Joined:
    Nov 23, 2009
    Posts:
    213
    I've nothing much to add really, except regarding andeeee's response here. I'm a scripting newbie and a slow learner by anyone's standards, but thanks to having both a decent description about how the code works and being able to dissect the script myself I've learnt more going through this in a matter of minutes than I did in hours of going through hundreds of other responses to queries. This kinda stuff is above and beyond the call of duty, so for what it's worth I'm really impressed. Cheers!
     
  10. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    I'm not sure exactly what you mean here. Do you need to detect the distance from the hovercar to the water, or the level of the water plane above the ground or... ?
     
  11. Grady Lorenzo

    Grady Lorenzo

    Joined:
    Jan 18, 2010
    Posts:
    407
    Im telling you guys, andeee's a genius...
     
  12. samados

    samados

    Joined:
    Jun 4, 2010
    Posts:
    3
    Hello everyone!

    First thank you Andeeee for buoyancy script!
    It works on my boat :) but the only problem is that the water came inside the boat (a classic wooden boat) at the intersection between them. Is there any trick that i can do to avoid that happen?

    P.S. srry for my bad english.
     
  13. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    If I understand you right, the problem is the graphical effect of the water plane appearing inside the boat. You can use the depth mask shader from the Unify wiki to fix this.
     
  14. samados

    samados

    Joined:
    Jun 4, 2010
    Posts:
    3
    wow it works... Thank you again!!
     
  15. FreakFish

    FreakFish

    Joined:
    Jun 4, 2010
    Posts:
    119
    he really is a genius 0.0
     
  16. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    I think everyone would agree with that statement. Andddddeeeeee needs to consolidate all his gems and put them on the wiki.
     
  17. cosmodog

    cosmodog

    Joined:
    Jan 5, 2010
    Posts:
    45
    Thanks to Andeeee for the script.

    I do have one problem though, changing the water height seems to mess up the buoyancy of the objects. I dug through the script but couldnt find the bug - any ideas?
     
  18. ColossalDuck

    ColossalDuck

    Joined:
    Jun 6, 2009
    Posts:
    3,246
    That would take years out of his lifetime!
     
  19. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    I've just tried playing with the water height, and it seems OK on my (admittedly simple) test project. When you say the buoyancy is messed up, what exactly is going wrong?
     
  20. cosmodog

    cosmodog

    Joined:
    Jan 5, 2010
    Posts:
    45
    If you change the water plane Y, the block will end up floating just under water - very different from the Y = 0 (see pics). Also if you monitor the submerged volume, the number will go out of the 0 to 1 range when the water plane is moved (I suspect the tet slicing code has a bug) I worked around it by using multiple buoyancy spheres (less accurate, but probably faster).
     

    Attached Files:

  21. guyblom

    guyblom

    Joined:
    Jul 23, 2010
    Posts:
    1
    What can I say Andeeee

    Such a tiny script that does so much. A huge thumbs up from me!
     
  22. mojojojo

    mojojojo

    Joined:
    Dec 16, 2009
    Posts:
    138
    Any possibility of getting that script in javascript or maybe a walkthrough of what we need to do. I've got this script that creates a rolling wave for a plane but don't know how to tie in your code.
     

    Attached Files:

  23. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    I've added a JS version of the script (long overdue!) to the post with the other package.
     
  24. Dylan Cristy

    Dylan Cristy

    Joined:
    Sep 14, 2010
    Posts:
    21
    Hi folks,

    New to Unity, scripting, and the forums, but psyched to be here, looks like a great community.

    First of all, thanks Andeeee, your script and explanation are really going to help me out. I did end up making some tweaks though (hope you don't mind), and I'll share them here. (That is the essence of community, right?) And who knows, maybe someone can tweak my tweaks and improve this system even more.

    Ok, so here's what I did:

    First, I tweaked andeeee's script and made a new script called floater_multipoint.js, which essentially expands the original script to apply buoyant force to more than one point on the object. The way I set this up is I added an array of Transforms as a variable you can populate through the Inspector. Then I made a couple empty GameObjects (essentially just reference points), positioned them inside the cylinder, made them children of the cylinder, and then dragged them from the Hierarchy into their respective slots in the script Inspector to populate the array. For the example I'm uploading, I only used two points, but you can make the array as big as you want / need.

    The thinking behind this was that if I have a very large object, it won't really look right if it's teetering and wobbling around one point of buoyancy. By positioning these buoyancy points throughout the object, I can probably arrive at much more convincing "floating" behavior.

    Secondly, andeeee's script uses a variable called waterLevel to set the height of the surface of the water, but that then means that the "surface" of the water is a static plane. I wanted to get some undulating wave action going on, and I found out how to do that through Eric5h5's post here. However, in order for the floating object to respond to the waves, you have to recalculate the waterLevel variable in andeeee's script as the plane changes. The way I accomplished this was by adding a Mesh Collider to the "water" plane mesh, and raycasting down from each of the buoyancy points to find out the water level directly below it. So I made a second script called floater_raycast.js that uses this technique. And in working with the mesh colliders, I realized that if you just add a mesh collider component to the plane, it is calculated once at runtime, so the collider remains a flat plane while the mesh ends up moving because of the Sinus Curve Modifier script. So I had to tweak that script too, and the one I included in the example here actually destroys and re-creates the mesh collider every time the mesh gets recalculated. Since I'm pretty new to Unity, I'm not really sure how taxing that might be on overall performance if there is a lot going on in your scene already. (It works great in the example, though!) The upshot of this is that you do not need to attach a mesh collider component to the water plane in the editor, it gets created at runtime.

    Oh, and another thing - I had to remove the collider from andeeee's original cylinder, otherwise that collider interacted with the mesh collider, and the cylinder never sank into the water properly, just rolled around on top. This could be a problem if you have multiple floating objects that need to be able to collide with each other. Not sure exactly how to work around this, although a thought just occurred to me: apparently if you set a collider to be a trigger, it will not interact with other colliders. So my question then is this: will a collider that's set to be a trigger still generate a raycast hit? If yes, then you can set the water plane mesh collider to be a trigger, and it will still serve it's purpose in calculating the height of the water level, while not interfering with the colliders of floating objects.

    So to recap - in the package I'm attaching there are two cylinders, one uses the floater_multipoint.js script which assumes a static water plane, and one uses the floater_raycast.js script and will rise and fall with the waves. The water plane uses the Sinus Curve Modifier script from the procedural mesh examples, and I've added a "Use Original" bool to toggle between the original example's calculation and Eric5h5's calculation (from the post I linked to above). The original is pretty harsh though.

    Enjoy, and if anyone wants to keep building on this, that would be great. I'd definitely be into collaborating to try and improve this system more and more.
     
    Last edited: Oct 29, 2010
  25. Dylan Cristy

    Dylan Cristy

    Joined:
    Sep 14, 2010
    Posts:
    21
    Ok, I answered my own question. Yes, colliders set to be triggers do generate raycast hits.

    So I re-added capsule colliders to the cylinders. But, since I was casting the ray from an offset point far above the object (in order to still hit the water even if the buoyancy point happened to duck below the water plane for a second), the rays started hitting the collider I had just added, thus the "water level" was calculated to be the top of the cylinder object, a force was added to propel it up above that level, and the cylinder ended up just floating up into the air.

    In come layers and layer masks. In order for this to work properly, the Layer of the water plane has to be set to the default "Water" layer in the Inspector. I have modified the floater_raycast.js script to check only against that layer.

    But it still works. Here's the new package with the updated script, colliders added to the cylinders, and the layer set on the water plane.
     

    Attached Files:

  26. Dylan Cristy

    Dylan Cristy

    Joined:
    Sep 14, 2010
    Posts:
    21
    Ok, more tweaking.

    After I posted the last scene, I added two buoyancy points to the raycast cylinder to see how it would behave. Not well, to say the least. After a bit of trial and error, I think I have things kind of stabilized.

    In this version, the raycast cylinder has six buoyancy points, and the non-raycast cylinder still has only two. The wave script is initially disabled so you can see that despite the different number of buoyancy points, the two cylinders behave virtually identically. Which in my mind is a good thing.

    A couple things I noticed about this new setup:

    - I set the angular drag on each of the cylinders' rigidbodys to 0.4 (as opposed to the default 0.05), which helps the cylinders stop bobbing around and stabilize in what seems a more natural way than just playing with the bounceDamp variable. Play with it and see what seems right to you.

    - Adjusting the mass in the rigidbody seems to be a slightly more effective way to get the cylinder to float higher or lower in the water than using the floatHeight variable, which actually seems to affect some sort of sensitivity. Enable the waves after the scene is running, and play with both those variables on the raycast cylinder to see for yourself.

    ETA: Also try removing two buoyancy points at a time from the raycast cylinder (just drop the size of the array from 6 to 4, and then 4 to 2, while NOT playing the scene, and with the waves still disabled), to see the difference in behavior.
     

    Attached Files:

    Last edited: Oct 29, 2010
  27. Saveremreve_legacy

    Saveremreve_legacy

    Joined:
    Feb 21, 2006
    Posts:
    7
    Has anyone else had trouble downloading Andee's orignal Unity project? It keeps downloading at 8k and results in an incomplete file.
     
  28. Paulo-Henrique025

    Paulo-Henrique025

    Joined:
    Dec 12, 2010
    Posts:
    230
    Working here
     
  29. mattpearse

    mattpearse

    Joined:
    Jan 28, 2011
    Posts:
    8
    hi there, im also new to unity, im trying to get my 3rd person character to float on the plane in the latest example by Dylan Cristy, i tried adding the float points to the controller and also the script but to no avail he simply falls through the water. any advice at all on this would be great!

    thanks,
    Matt
     
  30. kalos

    kalos

    Joined:
    Dec 11, 2010
    Posts:
    121
    Did you add the collider to him?
     
  31. mattpearse

    mattpearse

    Joined:
    Jan 28, 2011
    Posts:
    8
    yeah i added the exact same colider that was on the cylinder, i put it straight into the 3rd person controller section, which is where my buoyancy points were too. thats right?
     
  32. mattpearse

    mattpearse

    Joined:
    Jan 28, 2011
    Posts:
    8
    i added the 3rd person character to the screen, then i added a capsule collider, the floater_raycast script, and then added rigid body aswell as the buoyancy points. is there anything i am missing or need to take off? my character just falls through the plane
     
  33. Dylan Cristy

    Dylan Cristy

    Joined:
    Sep 14, 2010
    Posts:
    21
    Hmm... it's been a while since I looked at that stuff, but let me see... You are using the raycast script? Is your plane set to the "water" layer? The raycasts are checking specifically for hits in the water layer.
     
  34. mattpearse

    mattpearse

    Joined:
    Jan 28, 2011
    Posts:
    8
    actually im using the multipoint script. i have basically tried to copy all of the properties from the cylinder to my 3rd person controller, but it just falls through the ground. really stuck on this one.
     
  35. Dylan Cristy

    Dylan Cristy

    Joined:
    Sep 14, 2010
    Posts:
    21
    Ok, my next suggestion would be to check the position of the water plane on the Y axis. The "water level" variable on the script should match the Y value of the plane, because it is not automatically set to be the same. So if your plane is at Y = 10, and the "water level" variable is set at 0, things will "float" 10 units below the plane. Also keep in mind if the objects start below the water level, the script does not work very well.
     
  36. mattpearse

    mattpearse

    Joined:
    Jan 28, 2011
    Posts:
    8
    yeah my waterlevel is at the right height, i creating this inside of your original package. basically just dragging a 3rd person controller onto the plane. hes positioned above the plane and the Y level is set to 0. if i dont apply rigid body he falls straight through the floor. if i apply rigid body he stops and glitches a bit and falls through the floor really slowly. if i take off the character controller script he doesn't fall a all and just floats in the air
     
  37. Dylan Cristy

    Dylan Cristy

    Joined:
    Sep 14, 2010
    Posts:
    21
    hmm... can you re-package up the scene with what you added and post it here so i could take a look at it? without seeing how you've set it up i don't know what to tell you...
     
  38. mattpearse

    mattpearse

    Joined:
    Jan 28, 2011
    Posts:
    8
    its cool i worked it out, basiclally i had a capsule collider and a third person controller and it would not work with both of these together, i deleted the one and now it floats fine. thanks anyway!
     
  39. coco88

    coco88

    Joined:
    Mar 8, 2011
    Posts:
    4
    Hi I am very new to Unity, I would like to let the game object (eg.boat) moves in one direction and bounce left and right at the same time.
    I had tried to use the JavaScript that you posted above (jsfloater_166.js). But there are some errors on it that I could not figure it out.
    Could you help me on this?
    This are the errors that I got.

    " (10,28) ',' expected, insert semicolon at the end
    (12,28), expecting ),found 'f'
    (12,29), unexpected token: var
    (13,20), ',' expected, insert semicolon at the end
    (16,1), expecting EOF, found '}'. "

    Thanks in advance.
     
  40. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    I've just checked the original script and there aren't any errors coming up in Unity. Have you modified the script? It would be helpful if you could post the script as copied/pasted from your editor.
     
    JwmwiRaniBoro likes this.
  41. coco88

    coco88

    Joined:
    Mar 8, 2011
    Posts:
    4
    I did not modify anything, i only attached it to the boat that I want it to have this effect.
    Or is there any setting that I should have done?

    this is the script:


    var waterLevel: float;
    var floatHeight: float;
    var buoyancyCentreOffset: Vector3;
    var bounceDamp: float;



    function FixedUpdate () {
    var actionPoint = transform.position + transform.TransformDirection(buoyancyCentreOffset);
    var forceFactor = 1f - ((actionPoint.y - waterLevel) / floatHeight);

    if (forceFactor > 0f) {
    var uplift = -Physics.gravity * (forceFactor - rigidbody.velocity.y * bounceDamp);
    rigidbody.AddForceAtPosition(uplift, actionPoint);
    }
    }
     
  42. nevaran

    nevaran

    Joined:
    May 21, 2010
    Posts:
    247
    this is all realy good, but can u tell me a good one for realistic water? like same effect but to be set by a water(trigger) collider, because not all water will be as same height u know :)
     
  43. ankiarora

    ankiarora

    Joined:
    Nov 1, 2011
    Posts:
    2
    Hello all,

    I am new to using Unity3d tool.
    I want to float my character in the air. Please suggest me what i can do for this to implement in my Game?

    Thanks,
    anki
     
  44. niks07

    niks07

    Joined:
    Oct 11, 2011
    Posts:
    11
    hello andeee...

    i am new in unity and i am creating a 3D game.
    i want to float my flying object in forward direction in air same as in water but i can not find any way to do so..please tell me the way i can go with.

    anyone there who had the way to do so or having code please give it me.

    Thank you very much.
     
  45. Tinawchen

    Tinawchen

    Joined:
    Mar 28, 2012
    Posts:
    1
    Hi Andeee,
    can you please give me an guidance in how i can attach the script,
    and all the other steps i have to do, that it works?

    i'm working on a project with water-plants like waterlilys,
    and they have to float on the water, but i dont know how
    i have to import the files, and colliders,....

    im really a newbie, ...! :-|

    thank you
    Tinawchen
     
    Last edited: Mar 28, 2012
  46. Harry1

    Harry1

    Joined:
    Apr 18, 2012
    Posts:
    1
    Hello Andeegenius :)

    i`m so noob at this so sorry for the dumb question ,

    after importing the package and adding the jsFloater script to an object i get this error -

    rigidbody.force assign attempt for 'BoxA' is not valid. Input position is { NaN, Infinity, NaN }.

    how do i fix this ?

    ok i found out how to use it

    this is for all the noobs like me

    just add the script to the object and in unity inspector tab change the var numbers
    float hight = 1
    offset y = 1
    bounce damp = 0.5

    thats it :)
     
    Last edited: Apr 18, 2012
  47. EdwardLM

    EdwardLM

    Joined:
    Oct 10, 2013
    Posts:
    2
    Awesome. Thank you very much for the script.
     
  48. BlackPanda

    BlackPanda

    Joined:
    Jan 24, 2014
    Posts:
    78
    Can anyone plz tell me what does the floatHeight object calculate?? Is it how high our boat's center of mass is from the surface level?? Or how high the actionPoint is from the surface level??

    Edit: OK I worked out a new script anyway. :) But please help me here. I'm having trouble with the DepthMask shader that Andeee suggested. How to apply it correctly?? I'm using the "Low-Poly Wooden Row Boat" asset and I changed the boat's shader to Mask. I also attached SetRenderQueue script to the water object. But somehow the problem persists (water can be seen inside boat's hull).

    Anyone help me???
     
    Last edited: Feb 9, 2014
  49. Lone_Wolf

    Lone_Wolf

    Joined:
    May 4, 2014
    Posts:
    1
    FPS_2.png FPS_1.png Hi andeeeee,
    I used your script to make my character float as if it were swimming. When using the playmode of unity, I get upwards of 100 fps. It runs perfectly. But as soon as I touch the water, I get 1-3 fps. What am I doing wrong? FPS_2.png FPS_1.png
     
  50. JesterGameCraft

    JesterGameCraft

    Joined:
    Feb 26, 2013
    Posts:
    452
    Just an FYI for anyone looking at this solution. In my particular case I just needed boats to stay in place in a harbour but wanted them to be bobbing up/down a bit in calm water. So the boats staying in the same spot in the water.

    The solution here does not really fit this kind of scenario. What I found is that if I applied this script the forces equaled out eventually and the boat came to a stop. So I think this script is more fitting if the boat is moved around on the water (Ie. as someone driving the boat), since that introduces constant forces to it and prevents this "stabilization". In any case, just wanted to mention this here in case someone has a same scenario as me so they're aware of this behaviour.

    Nevertheless the script was very educational, thanks andeeeee.