local plane = script.Parent:WaitForChild("Plane")
local origPosTable = {}
local LocalPlayer
local speedCounter = 5
local maxDistance = 10
script.RemoteEvent.OnServerEvent:Connect(function(plr)
LocalPlayer = plr
end)
for _, bone in pairs(plane:GetChildren()) do
if bone:IsA("Bone") then
table.insert(origPosTable,bone.Position)
origPosTable[bone] = bone.WorldPosition
end
end
--GerstnerWave(Vector3 SamplePosition, Float Wavelength, Vector2 Direction, Float Steepness, Float Gravity, Float SampleTick)
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
game:GetService("RunService").Heartbeat:Connect(function()
for _, bone in pairs(plane:GetChildren()) do
if bone:IsA("Bone") then
if origPosTable[bone] then
local SamplePosition = bone.WorldPosition
local Wave1 = GerstnerWave(SamplePosition, 150, Vector2.new(1, 0), .05, 1, speedCounter)
local Wave2 = GerstnerWave(SamplePosition, 175, Vector2.new(0, .3), .2, 1.25, speedCounter)
local Wave3 = GerstnerWave(SamplePosition, 200, Vector2.new(1, 1), .1, 1.5, speedCounter)
local TotalDisplacement = Wave1 + Wave2 + Wave3
bone.Position = origPosTable[bone] + TotalDisplacement
end
end
end
end)
I dont know if itll work , but uh, someone correct me if i did this wrong
Anyone with superficial knowledge in Lua will easily be able to understand how that code functions. I made my ocean explicitly by looking at that page, and I myself only know Lua.
I take algebra 1, so much math i dont think i understand, thats why, and i can barely understand what the tutorial is trying to tell me, and I dont know what they are trying to explain, just makes my brain hurt.
for _, bone in pairs(plane:GetChildren()) do
if bone:IsA("Bone") then
table.insert(origPosTable,bone)
end
end
---bunch of code
bone.Position = origPosTable[bone].Position + TotalDisplacement
this should work, right? or should i findfirstchild the bone in the mesh after getting the bone’s name?
@Frogbottles
Yes it is a LocalScript. Visual effects should always be handled on the client.
@Sb0bster and @intergravitation
You need to save the positions of each bone inside of a dictionary. Like this:
local plane = workspace:WaitForChild("Ocean"):WaitForChild("Plane")
for _, bone in pairs(plane:GetChildren()) do
if bone:IsA("Bone") then
origPosTable[bone] = bone.Position
end
end
This code piece assumes the “Plane” object has the bones inside of it.
This doesn’t work, as you are referencing the new position every time. You need to store every bone’s position, not just the instance.
Here is a place file that should work: Ocean.rbxl (185.9 KB)
Keep in mind that I haven’t really optimized this script. You might have lag on lower end devices.
Skinned meshes don’t collide if you change their bones. the solution is to make a custom floating function that takes in an x and z coordinate and spits out a y coordinate. This y coordinate will be how high the object is floating. As stated in the OP:
about a month ago I attempted making an ocean using gerstner waves as well and I got pretty far. https://gyazo.com/d7def53d363c76f7ea9fabfaea16e263 But the only thing that I got stuck on and what led me to quitting was making a swim system with an accurate collision. I know your suppost to apply the formula to the player and use the Y position on a bodyposition to do this but I could never figure out how to sync it up properly ever. https://gyazo.com/3a5a26f8c714175188fe5951d6264502 Basically what I am trying to ask is if you have any idea on how to make an accurate swimming/ floating system for the water could you give me any clues on how to achieve this as well.
It’s hard to know just from looking at the video, but one thing that I encountered was that if you set the wavelength to be too much smaller than the distance between your bones, you lose out on a lot of detail and precision. I don’t know why else it would be so out of sync, you are doing it all on the client, right?
yea I am, but the reason its so wacky right now is because of a bunch of failed attempted fixes, usually its just delayed.
edit: Although the way you did yours is a bit different than mine because you added more parameters with gravity and steepness the math is nearly identical, so just out of curiosity how would you go about doing this in relation to your code?
I’m pretty sure the reason I can’t seem to link up floating objects in the water and the water itself to have actual physics is because the ocean’s bones are using relative position, instead of world position.
If there was some way to find the relative position to maybe the sea itself and the floating object, maybe they would finally be in sync.
I’m also using a client & server time synchronizer, which I checked myself to see if it was really in sync (it is), so in case that isn’t the issue. I’m not sure how Desired synched his objects so well with a BP.
Ok I figured it out the reason why I couldn’t get it to work. It was because In my script I was just solving for the Y when I was supposed to solve for the entire position and then just use the Y position.
No all I’m really doing is using a bodyposition to keep the players Y position exactly where it needs to be for it to look like the player is floating in the water. You cant do accurate collisions like OP said because the skinned water mesh acts like a special mesh.
Yeah I’m talking about the equation you’re using for the BP. I can’t seem to sync up the BP with the ocean even as I am using the HumanoidRootPart’s CFrame.
I’m still getting these results while using a bodyPos with the X being the position’s X.
function sin(a, b, c, d, e, f)
local x = a * math.sin(b * c + (d * e)) + f
return x
end
if root ~= nil and root:IsDescendantOf(player.Character) then
bp.Position = Vector3.new(0, sin(amplitude, root.Position.X, frequency, syncedTime + increment, speed, height), 0)
bp.Parent = root
root.Parent.Humanoid.WalkSpeed = 32
end