I am making an oxygen system (if you are touching the water your oxygen will drain), but the level isn′t going slow and steady (1 second = -1 value of the oxygen), but it′s going so super saiyan fast, it reached negative in 2 seconds.
We need to see the code responsible for draining oxygen to help you resolve the issue
I’ll do it tomorrow, can’t now, sorry!
add task.wait(0.1) and make sure the value is more than 0
local part = game.Workspace.woer
local ChildDescentHead = game.Players.LocalPlayer.Character.PrimaryPart
local function onTouch(ChildDescentHead)
while part.Touched do
wait(1)
script.Parent.Value -=1
end
end
local function onTouchEnded(ChildDescentHead)
script.Parent.Value = 45
end
part.Touched:Connect(onTouch)
part.TouchEnded:Connect(onTouchEnded)
A few issues
Touched
is an event, not a property you can reference
You need a proper debounce system for this to work as right now there’s no debounce
However, since I assume you’re trying to make a zone using touched events, I recommend you use either Spatial queries or ZonePlus, to make a zone. You can use these to detect a player within every second to reduce the value. It’s finicky to make a zone via touched events
WaterOxygenTest.rbxl (47.0 KB)
local HeadList = {}
script.Parent.Touched:Connect(function(part)
if part.Name == "Head" then
local player = game.Players:GetPlayerFromCharacter(part.Parent)
if player then
if HeadList[player.UserId] == nil then
HeadList[player.UserId] = part
end
end
end
end)
script.Parent.TouchEnded:Connect(function(part)
if part.Name == "Head" then
local player = game.Players:GetPlayerFromCharacter(part.Parent)
if player then
if HeadList[player.UserId] then
HeadList[player.UserId] = nil
part:SetAttribute("Oxygen",1)
end
end
end
end)
local secondsOfOxygen = 5
local elapsed = 0
while true do
for _,head in pairs(HeadList) do
local oxygen = head:GetAttribute("Oxygen") or 1
oxygen = math.max(oxygen-((1/secondsOfOxygen)*elapsed),0)
head:SetAttribute("Oxygen",oxygen)
end
elapsed = task.wait()
end
local player = game.Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local screenGui = playerGui:WaitForChild("OxygenScreenGui")
local backBar = screenGui:WaitForChild("OxygenBar")
local frontBar = backBar:WaitForChild("Level")
backBar.BackgroundColor3 = Color3.new(1,1,1)
frontBar.BackgroundColor3 = Color3.new(.2,.2,1)
local oxyLevel = 1
local module = {}
module.Reset = function()
screenGui.Enabled = false
frontBar.Size = UDim2.new(1,-4,1,-4)
backBar.BackgroundColor3 = Color3.new(1,1,1)
frontBar.BackgroundColor3 = Color3.new(.2,.2,1)
oxyLevel = 1
end
module.Draw = function(level)
screenGui.Enabled = true
oxyLevel = level
frontBar.Size = UDim2.new(level,-4,1,-4)
local backColor = Color3.new()
if level == 0 then
frontBar.Visible = false
backColor = Color3.new(1,0,0)
else
frontBar.Visible = true
backColor = Color3.new(level,level,level)
end
backBar.BackgroundColor3 = backColor
local frontColor = Color3.new()
if level < .5 then
frontColor = Color3.new(1,level*2,level*2)
else
local rg = 1-(((level-.5)/.5)*.8)
frontColor = Color3.new(rg,rg,1)
end
frontBar.BackgroundColor3 = frontColor
end
return module
local character = script.Parent
local head = character:WaitForChild("Head")
local oxygenBarModule = require(character:WaitForChild("OxygenBarModule"))
oxygenBarModule.Reset()
head:GetAttributeChangedSignal("Oxygen"):Connect(function()
local oxygenLevel = head:GetAttribute("Oxygen")
if oxygenLevel < 1 then
oxygenBarModule.Draw(oxygenLevel)
else
oxygenBarModule.Reset()
end
end)
This has a server script (for security) check the player’s head to see if they are inside the water block.
Then the server script will set an Attribute on the head to show the oxygen level
A LocalScript will check if the oxygen Attribute changes, and if it does, it will
Draw the Oxygen Bar, using the code in the OxygenBarModule.
Hope this helps in some way
Thanks! I′ll try it tomorow… Can′t do it now.
Also a thing, how can I make the oxygen, but with oxygen upgrade?
Video of what I mean:
Next time, wait until you have all the pieces of your topic before making it.
part.Touched
is a RBXScriptSignal, and therefore this loop will always run. Instead you should make a touched variable which is set to true when Touched is fired, and false with TouchEnded is fired. Or you can use part:GetTouchingParts()
to determine if it’s being touched.
Okay, I’ll try it tommorow! Thanks!