How to create terrain water behavior, without terrain water

I am trying to re-create the terrain water system. Players and bricks should float the same way, and people must be able to swim.

Placing a brick and calling FillBlock is not what I am looking for. I need the same behavior, only works with parts instead of terrain. Anyone got any ideas?

9 Likes

Part water, then?

1 Like

I checked all topics and none of them explained how it worked. They just gave basic ideas.

I guess I’ll stick with this workaround:

1 Like

Absolutely beautiful.

You could probably use a BodyVelocity with its Velocity property set to (0, 0, 0) to simulate no gravity, and you could apply a VectorForce to move the player, as well as fiddling with some humanoid states.

Just a thought.

2 Likes

So you’re asking for a system that sets your state to Swimming?

That’s fairly easy to do, but can be a bit performance intensive if not handled correctly
Consider looking into Humanoid:ChangeState() as this allows you to arbitrarily set a humanoid’s state

1 Like

Set the Humanoid State to Swimming and have a BodyVelocity set to the Humanoids MoveDirection * WalkSpeed

This is how i’ve done it

1 Like

This strange behavior occurs, for some reason.

Here’s my code:

local Sea = workspace.Sea --Directory of the water part
--
local RS = game:GetService("RunService")
local Character = script.Parent
local Humanoid = Character:WaitForChild("Humanoid")
local Root = Character:WaitForChild("HumanoidRootPart")
local Swim


Humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(function()
	if Root.Position.Y < Sea.Position.Y then
		if not Swim then
			Swim = Instance.new("BodyVelocity")
			Swim.Parent = Root
		end
		Swim.Velocity = Humanoid.MoveDirection * Humanoid.WalkSpeed
		if Humanoid:GetState() ~= Enum.HumanoidStateType.Swimming then
			Humanoid:ChangeState(Enum.HumanoidStateType.Swimming)
		end
	elseif Swim then
		Swim:Destroy()
	end
end)

you still having issues with that

well have you set it to true

like this

Humanoid:ChangeState(Enum.HumanoidStateType.Swimming, true)

i dont know if this will fix the problem

just checked

that swimming is

Swimming
4	
The Humanoid is currently swimming in Terrain water.

i think it assumes that this only works when the humanoid is swimming on terrain water?

The issue was so simple. Every time I set the Humanoid state type to Swimming, it got set to GettingUp immediately after. Here’s the finished code to prevent future scripters from struggling with this:

local Sea = workspace.Sea --Directory of the water part
--
local RS = game:GetService("RunService")
local Character = script.Parent
local Humanoid = Character:WaitForChild("Humanoid")
local Root = Character:WaitForChild("HumanoidRootPart")
local Swim


RS.Heartbeat:Connect(function()
	if Root.Position.Y < Sea.Position.Y - Root.Size.Y / 2 then
		if not Swim then
			Swim = Instance.new("BodyVelocity")
			Swim.Parent = Root
		end
		Swim.Velocity = Humanoid.MoveDirection * Humanoid.WalkSpeed + Vector3.new(0,4,0)
		if Humanoid:GetState() ~= Enum.HumanoidStateType.Swimming then
			Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
			Humanoid:ChangeState(Enum.HumanoidStateType.Swimming)
		end
	elseif Swim and Root.Position.Y < Sea.Position.Y then
		Swim.Velocity = Humanoid.MoveDirection * Humanoid.WalkSpeed
	elseif Swim then
		Swim:Destroy()
		Swim = nil
		Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, true)
	end
end)
51 Likes

Is there a way I could put this inside of a part script instead of startercharacterscripts? I’m having problems just having it in SCS and would rather just have it in a part. Especially since I am going to have many of them.

I can’t think of a good way of going about that, as swimming is an individual action of each character, just like walking or jumping. I don’t think you should have any kind of problem putting stuff in character scripts, so my recommendation to you is to get that fixed instead.

Alright, well my problem is that the water is being detected everywhere, not just on the part.

The code I wrote is very basic. The part is considered “sea level”, which means the player will be able to swim anywhere under the part’s Y coordinate. The whole purpose of the script is to create an infinite sea, something that terrain didn’t allow and came nowhere near in performance. However, for your purpose, the script can be modified by using the ZonePlus module. What you would do is remove the parts that use the “water part” and make use of the “localPlayerEntered” event of ZonePlus.

2 Likes