Floatation not working with gerstner waves

Hello, I have been working on a gerstner wave system for a couple days now. Just got the waves properly generating on the client, and I thought “oh hey lets make something float!” BIG MISTAKE so I made a part, added a script to it for testing and made the script use the same formula the client uses. The formula required a time so I used tick() on both. Then I just had it use the gained Y position from the formula to set the Y position of the object. After all that you’d think it’d be pretty close to following the water on the client?


This is that object, floating very incorrectly compared to the client.
I have no idea why this is happening, here’s the formula (Credit to @Sir_Falstaff for making the formula) I used on both client and server:

function GerstnerWave(SamplePosition,Wavelength,Direction,Steepness,Gravity,SampleTick)
	local k = (2 * math.pi) / Wavelength
	local a = Steepness/k
	local d = Direction.Unit
	local c = math.sqrt(Gravity / k)
	local f = k * d:Dot(Vector2.new(SamplePosition.X,SamplePosition.Z)) - c * SampleTick
	local cosF = math.cos(f)

	--Displacement Vectors
	local dX = (d.X * (a * cosF))
	local dY = a * math.sin(f)
	local dZ = ( d.Y * (a * cosF))
	return Vector3.new(dX,dY,dZ)
end

RunService.Heartbeat:Connect(function()
	local Height1 = GerstnerWave(script.Parent.Position,10.0,Vector2.new(0,1),5.0,2.0,tick()).Y
	local Height2 = GerstnerWave(script.Parent.Position,10.0,Vector2.new(1,0),5.0,2.0,tick()+1).Y
	local NewHeight = (Height1/2)+(Height2/2)
	script.Parent.Position = Vector3.new(script.Parent.Position.X,NewHeight,script.Parent.Position.Z)
end)

*Is the server version, but the client is the exact same math.
and also on the client I used the world position of the bones not just their position. Which means these should be synced up?
Someone please tell me what I’m messing up here, I even tried sampling four points around it, still didn’t work.

1 Like

Looks like to me the height multiplier might be different. Maybe check if it is that? Either that or it might be the fact that gerstner waves have an X,Z translation? Idrk.

I am not really sure how the sampling works. The issue could come from a multitude of places.

If it is lagging behind then it would probably the time. I would probably send the current tick from the server to the client then simply use the RunTime and add it on.

local Height1 = GerstnerWave(v.WorldPosition,10.0,Vector2.new(0,1),5.0,2.0,tick()).Y
local Height2 = GerstnerWave(v.WorldPosition,10.0,Vector2.new(1,0),5.0,2.0,tick()+1).Y
local NewHeight = (Height1/2)+(Height2/2)
v.Position = Vector3.new(v.Position.X,NewHeight,v.Position.Z)

this is what the client does, exactly the same thing as the server.

hi. I don’t really have much experience with roblox, but one thing I’ve learned is that getting the client and server to sync is practically impossible. There will always be a delay between the two and the physics can give a lot of problems. That’s why when it comes to visual effects everything is done on the client side.

Another important thing is to never use the Tick function to do animations. you should use Runservice instead.

But this is using runservice? It just feeds the tick into the formula to generate the wave, and tick is universal across server and client (or they should be pretty close atleast)
One thing I noticed about that cube is that it never moves as high or as low as the water, but I cant figure out why. Infact now that I look at it, they rise/fall at the same time. It’s just not high or low enough. And that’s what I can’t figure out.

Are you positively sure that there isn’t a height multiplier? Maybe, check for if you have included a MAX_HEIGHT variable or something like that in the positioning of the bones in the wavemesh. I am almost certain that there must be a height multiplier missing.

I was referring to using the first parameter of the Heartbeat handler. Searching the forum you can find out why it is not good to use the Tick function. But you are right, for experimenting there should be no problem.

I sent basically the entire script to you, besides for a few variables used for getting RunService and such.

local NewHeight = (Height1/2)+(Height2/2) * 8 -- random constant

If that is the case try multiplying the height og the part by a random constant for now and see what you get

I can make them go to almost equal heights, but I’m seeing that they’re just slightly out of sync.
I’ll try and make a timer from server to client and see how that pans out

Ok made a working global timer, still not working

so I gave it a global timer, (Client and all floaters use the same timer, same formula, etc)
and this happened


what
WHY

I even tried adding something that floats and doing it client side to look for any desync.
it floats in the exact same way.

Hold on. How far apart are your bones? It could be that sampling bones far apart and the actual formula being the problem.

I’ve been trying to figure out the distance between my bones, I need to find two bones next to eachother

135.491 is the distance between each bone exactly

1 Like

so I put a floater on the exact position of one of the bones.
and it lined up just fine.

1 Like

Yes that was what I was sort of trying to help you understand. The X,Z size of the waves is very small previously so you have to mess around with either making the bones more closer together or making the frequency of the waves larger
.

This is very likely the problem, you need to increase the generated wavelength so that it’s larger than the smallest distance between your wave mesh bones. The other solution is to increase the resolution of the wave mesh, which brings with it another set of problems. One thing to consider is that you don’t need to use the same resolution across the board, you can use a higher resolution plane near the player and lower resolution planes as the distance from the player increases.

2 Likes

I’ve decided (since I can’t exactly figure out how to line everything up) just to make a module that can generate points on the wave based off of a pre-made positioning that lines up with the water. A little scuffed way of doing it but I should be able to use this for making floating objects. Thank you for the formula btw and the info about it.