skyguy skyguy - 20 days ago 11
C# Question

Unity physics - how to make objects bob down then up as if in space with gravity?

Alright, just getting into physics here in Unity and Ive been through Unity's forums as well, however I cant figure out how to create this specific gravity related effect -

I have these rigid bodies of mass 100 that I am able to push off the platform (my game is a bunch of platforms set in space) into open space. Because they are checked for affected by gravity, they fall.

What I need is for the objects to slide off the platform, fall a little bit slowly but then bob up and stay there floating. Like if pushed off in space, but they cant keep going. Just bob down, then up, stay and float.

This seems to be a lot more complicated than I thought, as Ive played with gravity and with high values they fall straight down (not out, obviously) and low values they float up above when pushed off. There doesn't seem to be a sweet spot where they neither go down or up, just bob.

How can I achieve this? My masses are 100.

Answer

My suggestion is to implement a force function that tries to resemble Arkimedes' principle. The key is that the potential is dependant on how far down the object is: the further down into the water the object is, the more lift force. As such, the key function here (and the most tricky one) is volumeBeneathSurface.

double liftForce(object)
{
    const double waterLevel = 0.0;
    const double density = 1000.0; // kg/m^3 -- using water atm

    double vol = volumeBeneathSurface(object, waterLevel);

    double displacedMass = vol*density; // density = m/vol
    double displacedWeight = displacedMass*gravity; // F = m*a
    return displacedWeight;
}

Now, the tricky part here can be to calculate what amount of volume is beneath the water surface. Imagine a really tricky geometry that might be rotated -- it can become as complicated as you want. The simplest case is probably to approximate your shape by a non-rotating box.

double volumeBeneathSurface(object, double surfaceLevel)
{
     // assuming the object has `height`, `width`, and `depth`
     // also assuming its coordinate is references from the center of the object
     double r = object.y - surfaceLevel - object.height/2.0; // How much of the object is beneath the surface
     if (r > 0)
         return 0.0; // the object is purely above
     else if (r < object.height)
         return object.height*object.width*object.depth; // the whole object is beneath
     else
         return abs(r)*object.width*object.depth; // partly under
}

Realistic things in water bobs up and down a little, but eventually the motion fades away. This is due to the energy transferring to the object and creating waves in the water. We have no such effect here, so most likely our object will bob up and down forever. What you could to is add some extra friction to the object and the motion should fade out.