How can ı make drowning system in a part?

Not under of the terrain water just under of a water but its a part.

Hi!

I am making something relatively similar myself, so I decided to write you a short script. It has no visual effects, but you can always add GUIs, for example Minecraft like hearts, and so on.

The simplest way of detecting touches is using .Touched event. When it comes to really high speeds (e.g. bullet speeds), .Touched doesn’t run reliably, but is almost definitely good enough for water drowning effect. The most full-proof way involves Region3, but they demand too much resources for simple water drowning, especially when they are large.

Before I continue explaining, you can find the full code here:

Code
local water = script.Parent
water.Anchored = true; water.CanCollide = false

-- Settings --------------------------------
local DAMAGE_PER_SECOND = 8
local TIME_BEFORE_DAMAGE = 3 -- seconds
--------------------------------------------

local inWater = {}

water.Touched:Connect(function(object)
	if (object.Name == "Head" and inWater[object.Parent] == nil) then
		inWater[object.Parent] = TIME_BEFORE_DAMAGE
	end
end)

water.TouchEnded:Connect(function(object)
	if (object.Name == "Head") then
		local n = inWater[object.Parent]
		inWater[object.Parent] = nil
		
		if (n < 3) then
			repeat n += 1; wait(1)
			until n >= TIME_BEFORE_DAMAGE or inWater[object.Parent] ~= nil
		end
		inWater[object.Parent] = n
	end
end)

while (true) do
	for char, count in pairs(inWater) do
		if (count > 0) then
			inWater[char] -= 1
		else
			char.Humanoid:TakeDamage(DAMAGE_PER_SECOND)
		end
	end	
	wait(1)
end

I’m using a table called inWater. It is a dictionary-type table, meaning indexes are not necessary numbers, and its form reminds us of a dictionary.

local inWater = {
	[character here] = number of seconds here;
	...
}

Indexes are characters that are in water, and seconds represent time interval before player starts “drowning”/loosing health points.

We only continue with the drowning function under the condition that head is under water (inside the part) and if head is not yet under water.

water.Touched:Connect(function(object)
	if (object.Name == "Head" and inWater[object.Parent] == nil) then
		-- further code
		inWater[object.Parent] = TIME_BEFORE_DAMAGE
	end
end)

We have an infinite while-loop, running every second. Set the time interval customly. The while-loop checks every index and element in the inWater table using pairs().

Remember this line?

		inWater[object.Parent] = TIME_BEFORE_DAMAGE

Number is seconds, right? If player is not in water, that value is nil. Conversly, if player is in water, that value is a number value.

for char, count in pairs(inWater) do
		if (count > 0) then
			inWater[char] -= 1 -- Subtract 1 each second.
		else -- Once value <= 0, player starts taking damage every second.
			char.Humanoid:TakeDamage(DAMAGE_PER_SECOND)
		end
	end	

Why do we even have the value stored. Because we don’t want player to start “drowning” immediately. Alright. But that value has even further functionality. Once player gets their head out of the water, that value slowly starts raising. We set it to nil, because head is not under water anymore, but we remember what the value was before. If player wast taking damage, that means it was zero, if player got out of the water before that, it means that it’s between zero and default.

		local n = inWater[object.Parent] -- 1) Store the previous number.
		inWater[object.Parent] = nil -- 2) Mark player as out of water.
		
		if (n < 3) then
			repeat n += 1; wait(1) -- 3) Restore the number every second (custom).
			--[[
				4) Continue until value is back to normal, or player
				gets in water again.
			]]
			until n >= TIME_BEFORE_DAMAGE or inWater[object.Parent] ~= nil
		end
		--[[
			When player is in water, timer is reset to default value:
			that is why we have to set it to current value (n).
		]]
		inWater[object.Parent] = n

How do we detect whether player got out of the water? The opposite of .Touched is .TouchEnded event.

Hopefully this gives you a good start!

4 Likes