Calculating Custom Buoyancy

Hey guys!

I’m trying to create a custom buoyancy effect, however I’m having a bit of a trouble with it. The way I’m currently doing it is applying a Y force to the part (using a BodyForce) that is equal to Part:GetMass() * workspace.Gravity. I’m applying this force when the object goes below the water, and setting the force back to 0 when the object is above the water. However, it seems to be unstable and just keeps bouncing.

https://gyazo.com/8257abb68d66771496484952ffd30483

Does anyone have any equations/methods for achieving custom buoyancy?

7 Likes

A BodyPosition mover and a Gyro can give decent results. I guess it depends on how central the effect is to your game. It may ultimately be worth finding a way to code that up the hard way in order to give you the control you want. We’ll need someone else to help with that though. :smiley:

Here’s the code I used for the vid above. This was just for testing out ideas. You wouldn’t do it like this unless you have only one object that needs to float. It’s just to help generate other ideas.

-- water is 20x20x20 semi-transp cube with collision off
local water = script.Parent

-- to keep from reapplying bodymovers in this test
local db = false

-- top of the water cube	
local waterLevel = water.Position.Y + 0.5*water.Size.Y

-- for this test just attaching movers to part that enters water
-- part was 5x5x5 in the video
water.Touched:Connect(function(part)
	-- saw some nice results with these settings
	if db then return end
	db = true
	
	-- force part to waterline
	local bodyPosition = Instance.new("BodyPosition")
	bodyPosition.MaxForce = Vector3.new(0, workspace.Gravity, 0) * part:GetMass()* 1.6
	bodyPosition.Position = Vector3.new(0, waterLevel, 0)
	bodyPosition.P = 400
	bodyPosition.D = 10
	bodyPosition.Parent = part
	
	-- force it to float upright
	local bodyGyro = Instance.new("BodyGyro")
	bodyGyro.Parent = part

end)
12 Likes

The buoyant force is equal to [the volume of the water displaced] * [the density of water] * gravity. Try calculating the force based on that, instead.

Note: Calculating the volume of the part that’s under water is a good approximation for the amount of water displaced. This is easy if the part is axis-align (not rotated), but is pretty hard if the part is rotated.

Edit: Replied to the wrong person, whoops.

Anyway, Astr0Derp’s solution seems good enough. Depending on your game, I doubt players in your game would care if it’s inaccurate.

7 Likes

You also need to calculate the resistance of the water. You can do this by using this equation:

(Velocity * AbsoluteVelocity * Density) / 2 * Area * Efficiency

Velocity, Area, and Efficiency are all Vector3s. Density is a number.

You can either set density as a constant or calculate it based on depth for more realistic results.

8 Likes

This won’t fix your issue, but you should be using a VectorForce as opposed to a BodyForce when you just want to apply a force in Roblox.

I recomend @XAXA’s solution.

2 Likes

Thats not a bad idea, but it’s sort of an “artificial” way of making it appear buoyant. I’m going to be using the buoyancy effect on boats so I don’t think this would work out that well.

3 Likes

Yes, I have also tried the equation that @XAXA provided. I came up with a simple equation to calculate the volume of water displaced based on the size of the part and the position of it (didn’t take into account the rotation just yet as to not make things more complicated), but the same thing still happened since it transitioned from no volume displaced to maximum volume displaced like within a split second.

Can you please elaborate more on your equation? By velocity do you mean the velocity of the part? And how would I get the FacialArea and Efficiency? Also how come I should be using a VectorForce as opposed to a BodyForce? Does it make a difference?

2 Likes

Roblox hasn’t really said anything about the benefits of using VectorForces over BodyForces, however VectorForces are a replacement for BodyForces and that must be for a reason. With VectorForces, you can use an attachment to set a custom centre of gravity. I’m guessing that it is much more efficient too.

Velocity is simply Part.Velocity. Unfortunately we can’t use exponents on vectors so you have to multiply it by itself. FacialArea is the area of each face of the bounding box surrounding the boat. Efficiency is just a coefficient, as different shapes create a different amount of drag.

2 Likes

Update on the situation: we have figured this out, it uses air resistance, water resistance, and buoyancy from @XAXA

3 Likes

Yes, you need to include the friction from the water to prevent the object from leaving the water with the same velocity that it entered with.

8 Likes

I’m new to the forum and not sure if questions from the OP are supposed to be answered and that’s it or if continuing relevant discussion is okay. Apologies if the following is inappropriate.

It seems like it would be less important to model buoyancy for a boat than it would for flotsam. I think it would be unusual to see a boat bobbing under water and floating back to the surface. Would it not be reasonable to assume there is an equilibrium between boat weight and buoyant force and just pick a height for the boat to float at (or heights for empty, loaded, overloaded)–maybe add some bobbing and rolling for effect as rotations? It seems like adding real deal physics could add hassle when it comes to modeling (building) boats if things like hull shape/volume and center of buoyancy vs CoG need to be handled correctly in order for a boat to float as expected in the game. Of course, all that may be worth dealing with if the game is a sailing simulator or the like, but I didn’t get the sense that this thread was headed that way.

That said, as an intellectual exercise this is all very interesting. How did you decide to go about determining [the volume of the water displaced]? I started looking into that and ended up in the land of tetrahedrons, voxels, integration and the like. Still working on a path forward that I like. Have you found a solution that is well suited to this platform? Are you tracking changes in the amount of hull that is underwater or simplifying that to some value that is proportional to depth? I’m also curious as to what benefit are you hoping to see in your game by modeling the buoyancy rather than faking it? Since my training was in animation rather than simulation, my first inclination is to make things look right rather than to behave correctly. Wondering if your inclination is the opposite due to your training, or if there is a cost-benefit analysis at play behind some of this.

Best of luck on your project. Hope to see it in action, live, on the front page of Roblox someday.

6 Likes

The displacement calculation I did was very simple and assumes that the part doesn’t rotate. I did this to not make things any more complicated as we were trying to get the buoyancy and resistance to work right. The way I calculated the displacement was, I got the top surface position of the object and subtracted the height of the water to determine the distance between the top of the object and the top of the water. I then subtracted that number from the total height of the object to determine how much of the object was in the water. To make sure that this number stays within the bounds of 0 and the total object’s height, I just wrapped it in math.min and math.max. Then I multiplied this number by the surface area of the object (Object.Size.X * Object.Size.Z) to determine the volume. Here’s the final equation:

local objectHeight = Object.Size.Y
local topSurfacePosition = Object.Position.Y + (objectHeight * 0.5)
local surfaceArea = Object.Size.Z * Object.Size.X
local waterHeight = Water.Position.Y + (water.Size.Y * 0.5)j

local totalWaterDisplaced = surfaceArea * math.min(math.max(objectHeight - (topSurfacePosition - waterHeight), 0), objectHeight)

As for the reason why I’m trying to model buoyancy rather than doing it artificially is because I’m also trying to have waves in my game. If the water was completely flat, artificial physics like you talked about, would work perfectly fine. However, since I’m trying to also create waves, I need the boats move and rotate in respect to the waves.

Also, I’m pretty sure we are only supposed to answer the questions from the OP. If you want to continue discussion related to the OP, it’s better to create a new thread about it or discuss it in private DMs. So feel free to shoot me a DM if you would like to know more about my game and what I’m trying to achieve. I’ll be happy to talk to you :slight_smile:

4 Likes

:+1:
Maybe you’ll get a chance to post something about the end result. Will be interesting to see how it all works with the waves. The thread made me curious about how difficult it would be to code something more boat-like than what I might normally attempt. Using tetrahedrons to calculate underwater volume maybe isn’t as epic as I imagined…at least not with the very minimal dummy hull I’m using. I’ve been setting it up to handle boat rotation but a flat water line. Allowing for water coming at an angle or as something other than a plane adds an interesting wrinkle. Anyway, I’ll start a new post if I manage to come up with anything useful. Thanks for the follow-up info and also for your original post: Lots of good info here.

2 Likes

I’ve made quite a few improvements to air and water resistance since, however this is a result we are getting. If your boat density is higher than the water density (set at .9), it will sink.

The script is only around 50 lines I believe, not very complicated at all. It will certainly help make the game feel more immersive.

4 Likes