Mesh Deformation Seas Project - Dynamic Waves, Foam FX, Sounds, and more

https://gyazo.com/c19c1e00757a5f07fd68af2b4f60e3ad

this is very interesting

3 Likes

Just looks like a regular ocean. Then again, I’m in Florida, so that might change somethings :laughing:
Sorry for the bump, just realized.

2 Likes

Sorry for the bump, but I feel like this might just help the few people trying to recreate this system, since there aren’t many similar topics on the matter in the DevForum and almost none that actually solve the issues most struggle with, I’ve decided to make this small post.

Issue Ⅰ : Nearby Bones
Most likely the biggest problem many would encounter while trying to recreate this system, luckily however a pretty simple solution to this exists.

Assume your mesh is composed of 4x4 grid of bones, all of them named a specific number of a decrescent order that starts at (0x, 4y) and ends at (4x, 0y), such as:

16, 15, 14, 13
12, 11, 10, 09
08, 07, 06, 05
04, 03, 02, 01

Then, let i be equal to (3x, 3x), which in this model is 10. (represented in bold above), which is enough information to give us a definition of i as 10 divided by the amount of rows (4), or 2.5 (that is, 2(4)+4/2≻8+2=10), note that if we add a 1 to that 2.5 (3.5) we would instead have 3(4)+4/2≻12+2=14, which to our surprise is exactly the number above 10 in our table!

To simplify this, all we would need to fetch the number above 10 in this table would be to add the amount of columns of the table to our current number, which translated to code would result in something along the lines of:

local Points : any = {
	'Bone01', 'Bone02', 'Bone03', 'Bone04';
	'Bone05', 'Bone06', 'Bone07', 'Bone08';
	'Bone09', 'Bone10', 'Bone11', 'Bone12';
	'Bone13', 'Bone14', 'Bone15', 'Bone16';
} --[[
	A table that mimics what you might already have for your ocean system, 
	remember however that these have to be indexed in the right order, based
	on a crescent order (not decrescent as would make it harder to properly index,
	however also theoretically possible.)
	]]--

local AMOUNT_OF_COLUMNS : number = 4

local function fLeft(i : number) : any -- fLeft is a function that returns the value left of i
	local tLeft = i-1 -- Use minus if your table is crescent and plus otherwise.
	return Points[tLeft] ~= nil and Points[tLeft] or "Empty"
end

local function fRight(i : number) : any -- fRight is a function that returns the value right of i
	local tRight = i+1 -- Use plus if your table is crescent and minus otherwise.
	return Points[tRight] ~= nil and Points[tRight] or "Empty"
end

local function fTop(i : number) : any -- fBottom is a function that returns the value below i
	local tLeft = i-AMOUNT_OF_COLUMNS -- Use minus if your table is crescent and plus otherwise.
	return Points[tLeft] ~= nil and Points[tLeft] or "Empty"
end

local function fBottom(i : number) : any -- fTop is a function that returns the value above i
	local tRight = i+AMOUNT_OF_COLUMNS -- Use plus if your table is crescent and minus otherwise.
	return Points[tRight] ~= nil and Points[tRight] or "Empty"
end

local PointsLeft = {} --[[
	"Empty", "Bone01", "Bone02", "Bone03";
	"Empty", "Bone05", "Bone06", "Bone07";
	"Empty", "Bone09", "Bone10", "Bone11";
	"Empty", "Bone13", "Bone14", "Bone15";
]]--
for i = 1, 16 do
	table.insert(PointsLeft, fLeft(i))
end

local PointsRight = {} --[[
	"Bone02", "Bone03", "Bone04", "Empty";
	"Bone06", "Bone07", "Bone08", "Empty";
	"Bone10", "Bone11", "Bone12", "Empty";
	"Bone04", "Bone15", "Bone16", "Empty";
]]--
for i = 1, 16 do
	table.insert(PointsLeft, fRight(i))
end

local PointsTop = {} --[[
	"Empty",  "Empty",  "Empty",  "Empty" ;
	"Bone01", "Bone02", "Bone03", "Bone04";
	"Bone05", "Bone06", "Bone07", "Bone08";
	"Bone09", "Bone10", "Bone11", "Bone12";
]]--
for i = 1, 16 do
	table.insert(PointsLeft, fTop(i))
end

local PointsBottom = {} --[[
	"Bone05", "Bone06", "Bone07", "Bone08";
	"Bone09", "Bone10", "Bone11", "Bone12";
	"Bone13", "Bone14", "Bone15", "Bone16";
	"Empty",  "Empty",  "Empty",  "Empty" ;
]]--
for i = 1, 16 do
	table.insert(PointsLeft, fBottom(i))
end

Issue Ⅱ : Player and Object Collision
This one is a little bit harder, but still achievable.

The simple method requires you to have a function of the wave that returns a Y value for any X, Z inputs, then, all you would need to do is place a BodyPosition on the object or character (that can only affects the Y axis), and set the Y value of the BodyPosition to the Y value from the function (with the X, Z of the part’s position) if touching the water.

1 Like