Help with Mesh Deformation Sea

Hey!

With the development of my upcoming game I keep getting more issues with my skinned mesh water, and here we are again. I’m using some basic code to move the bones of the skinned mesh upward, and downward to give a wave effect, although using multiple planes of water, the edges do not meet together, despite the script making them do that by getting all of the bones as if treating the multiple plates as one.

Game View:

Explorer:

Code:

local RunService = game:GetService("RunService")
local descendants = script.Parent.Waves:GetDescendants()
local speed = 0

local function Wave(Position)
	local amplitude = script.Parent.Amplitude.Value
	local frequency = script.Parent.Frequency.Value
	speed += script.Parent.Speed.Value / 10^5
	local X = amplitude * math.cos(Position.X * frequency + speed)
	local Z = amplitude * math.cos(Position.Z * frequency + speed)
	return Vector3.new(X, X + Z, Z)
end

RunService.Heartbeat:Connect(function()
	for _, descendant in pairs(descendants) do
		if descendant.ClassName == "Bone" then
			descendant.Transform = CFrame.new(Wave(descendant.Position))
		end
	end
end)

As I said, I think that by getting all of the bones it should work correctly. If anyone knows how to fix this issue, I’d appreciate the help a ton! Thanks.

Just making sure before I write out a response, your question here is asking why the planes don’t line up at the edges? Or is it that they aren’t all exactly the same? The video doesn’t really show either of these and “they do not sync together” could mean either of the above questions, so just wondering.

Sorry for not being clear enough, the planes are supposed to line up with each other to make a smooth effect, so it basically just looks like one plane.

Something I noticed is that your wave function returns an altered x and z coordinate, which will cause desync problems such as the above. Try changing the function to do

local function Wave(Position)
	local amplitude = script.Parent.Amplitude.Value
	local frequency = script.Parent.Frequency.Value
	speed += script.Parent.Speed.Value / 10^5
	local X = amplitude * math.cos(Position.X * frequency + speed)
	local Z = amplitude * math.cos(Position.Z * frequency + speed)
	return Vector3.new(Position.X, X + Z, Position.Z) --The only changed line
end

And see what happens, I’m also assuming you’ve made sure that the planes are all lined up before you apply the wave.

1 Like

Odd, when I use that function the plates get practically 2x larger than previously did. I actually fixed that enlargement issue last time by removing that part where you use Position.X and Position.Z

Yeh I don’t think you’re setting the Y coordinate correctly.

The equation you need is:

phi = amplitude * math.cos( kVector:Dot(Vector2.new(X, Z)) - frequency * time) 

Then you can just return this:

return Vector3.new(X, phi, Z) 

You can then tweak kVector and frequency to get the desired speed and direction of a single wave.

You can then also add multiple of these phi values together to get more complex patterns.

What would kVector be in this equation?

It is a Vector2 that points in the direction of travel of the wave, the magnitude describes the wave number.

With my current code, it errors out and says:

Current code:

local RunService = game:GetService("RunService")
local descendants = script.Parent.Waves:GetDescendants()
local speed = 0

local function Wave(Position)
	local amplitude = script.Parent.Amplitude.Value
	local frequency = script.Parent.Frequency.Value
	speed += script.Parent.Speed.Value / 10^5
	local X = amplitude * math.cos(Position.X * frequency + speed)
	local Z = amplitude * math.cos(Position.Z * frequency + speed)
	local phi = amplitude * math.cos(Vector2.new(0,0):Dot(Vector2.new(X, Z) - frequency * time))
	return Vector3.new(X, phi, Z) 
end

RunService.Heartbeat:Connect(function()
	for _, descendant in pairs(descendants) do
		if descendant.ClassName == "Bone" then
			descendant.Transform = CFrame.new(Wave(descendant.Position))
		end
	end
end)

I think there’s a closing bracket missing after the :dot method

this thread may be useful to you as well

1 Like

I changed the code and got this, which still errors out.

local phi = amplitude * math.cos(Vector2.new(1,1):Dot(Vector2.new(X, Z)) - frequency * time)

Ah the time variable needs to be replaced with something more robust. It’s trying to use the time built in function atm. You could try replacing time with time() and see how it goes.

1 Like

I’ve just randomly started getting this error, despite not changing anything at all,

image

[DISREGARD I FIXED IT]

And using time() fixes the last issue.

But now, there are no errors, but the water does not move at all.

Edit: Got the water moving again, but the planes still are not ‘in sync’ with each other.

The X and Z in the vector2 should just be Position.X and Position.Z, should’ve made that clearer.

1 Like
local phi = amplitude * math.cos(Vector2.new(Position.X,Position.Z):Dot(Vector2.new(X, Z)) - frequency * time()) 

Still doesn’t work, gives the same effect as the video above.

You need to use descendant.WorldPosition, the position variable is relative to the plate meaning bone 0 is the same position on every plate, same going with 1, 2, 3, etc, but WorldPosition is the position in relative to the world meaning, if you place a part and set its position to the world position of a bone, then they will align

Hope that helps! :slight_smile:

3 Likes

Okay, that actually worked, thanks so much!

@McThor2 Thanks for your help too!

1 Like