I’m adding realistic water to my game and so I used a skin mesh. I wanted boats so I opted to just have a model called Boat stick to the surface of that mesh. It doesn’t work at all. I don’t know if it doesn’t know the location of the wave or if the scripts just have an issue but it isn’t working. Any ideas? Thanks:
Local Boat Script in StarterPlayerScripts:
local RunService = game:GetService("RunService")
local boat = workspace:WaitForChild("Boat")
RunService.RenderStepped:Connect(function()
if _G.GetWaveHeightAt then
local pos = boat.Position
local waveY = _G.GetWaveHeightAt(pos)
boat.Position = Vector3.new(pos.X, waveY, pos.Z)
end
end)
Local Wave Script in StarterPlayerScripts:
local RunService = game:GetService("RunService")
local waveModel = workspace:WaitForChild("Wave")
local plane = waveModel:WaitForChild("Plane")
local bones = {}
for _, v in ipairs(plane:GetDescendants()) do
if v:IsA("Bone") then
table.insert(bones, v)
end
end
local waves = {
{dir = Vector2.new(1, 0).Unit, amplitude = 15, wavelength = 60, speed = 8},
{dir = Vector2.new(0, 1).Unit, amplitude = 10, wavelength = 40, speed = 12},
{dir = Vector2.new(1, 1).Unit, amplitude = 8, wavelength = 50, speed = 6},
{dir = Vector2.new(-1, 1).Unit, amplitude = 6, wavelength = 70, speed = 5},
}
local function getWaveHeightAtXZ(x, z, t)
local height = 0
for _, wave in ipairs(waves) do
local k = (2 * math.pi) / wave.wavelength
local phase = k * (wave.dir.X * x + wave.dir.Y * z - wave.speed * t)
height += math.sin(phase * 1.2) * wave.amplitude * 0.3
end
return height
end
local boneData = {}
for _, bone in ipairs(bones) do
local pos = bone.CFrame.Position
boneData[#boneData+1] = {
bone = bone,
originCFrame = bone.CFrame,
originXZ = Vector2.new(pos.X, pos.Z)
}
end
RunService.RenderStepped:Connect(function()
local t = tick()
for _, data in ipairs(boneData) do
local xz = data.originXZ
local totalOffset = Vector3.zero
for _, wave in ipairs(waves) do
local k = (2 * math.pi) / wave.wavelength
local phase = k * (wave.dir.X * xz.X + wave.dir.Y * xz.Y - wave.speed * t)
local offsetX = math.cos(phase) * wave.amplitude * 0.5 * wave.dir.X
local offsetZ = math.cos(phase) * wave.amplitude * 0.5 * wave.dir.Y
local offsetY = math.sin(phase * 1.2) * wave.amplitude * 0.3
totalOffset += Vector3.new(offsetX, offsetY, offsetZ)
end
data.bone.CFrame = data.originCFrame * CFrame.new(totalOffset)
end
end)
_G.GetWaveHeightAt = function(position)
return getWaveHeightAtXZ(position.X, position.Z, tick())
end
Server Wave Script in ServerScrtipService:
local RunService = game:GetService("RunService")
local waveModel = workspace:WaitForChild("Wave")
local plane = waveModel:WaitForChild("Plane")
local bones = {}
for _, v in ipairs(plane:GetDescendants()) do
if v:IsA("Bone") then
table.insert(bones, v)
end
end
local waves = {
{dir = Vector2.new(1, 0).Unit, amplitude = 15, wavelength = 60, speed = 8},
{dir = Vector2.new(0, 1).Unit, amplitude = 10, wavelength = 40, speed = 12},
{dir = Vector2.new(1, 1).Unit, amplitude = 8, wavelength = 50, speed = 6},
{dir = Vector2.new(-1, 1).Unit, amplitude = 6, wavelength = 70, speed = 5},
}
local function getWaveHeightAtXZ(x, z, t)
local height = 0
for _, wave in ipairs(waves) do
local k = (2 * math.pi) / wave.wavelength
local phase = k * (wave.dir.X * x + wave.dir.Y * z - wave.speed * t)
height += math.sin(phase * 1.2) * wave.amplitude * 0.3
end
return height
end
local boneData = {}
for _, bone in ipairs(bones) do
local pos = bone.CFrame.Position
boneData[#boneData+1] = {
bone = bone,
originCFrame = bone.CFrame,
originXZ = Vector2.new(pos.X, pos.Z)
}
end
RunService.Heartbeat:Connect(function()
local t = tick()
for _, data in ipairs(boneData) do
local xz = data.originXZ
local totalOffset = Vector3.zero
for _, wave in ipairs(waves) do
local k = (2 * math.pi) / wave.wavelength
local phase = k * (wave.dir.X * xz.X + wave.dir.Y * xz.Y - wave.speed * t)
local offsetX = math.cos(phase) * wave.amplitude * 0.5 * wave.dir.X
local offsetZ = math.cos(phase) * wave.amplitude * 0.5 * wave.dir.Y
local offsetY = math.sin(phase * 1.2) * wave.amplitude * 0.3
totalOffset += Vector3.new(offsetX, offsetY, offsetZ)
end
data.bone.CFrame = data.originCFrame * CFrame.new(totalOffset)
end
end)
_G.GetWaveHeightAt = function(position)
return getWaveHeightAtXZ(position.X, position.Z, tick())
end
Any ideas? Thanks!