I am working on a submarine, and I have a script that disables the player’s swimming while inside of it. The problem is, my current system is very touchy and isnt really reliable at all:
In server:
collider.Touched:Connect(function(hit)
if hit.Name ~= "HumanoidRootPart" then return end
--give script
local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
if plr then
print("Give")
game.ReplicatedStorage.Remotes.GrabClientScript:FireClient(plr, "SubmarineFloor", script.Parent)
end
end)
collider.TouchEnded:Connect(function(hit)
if hit.Name ~= "HumanoidRootPart" then return end
--remove script
local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
if plr then
print("Remove")
script.Parent.RemoveChar:FireClient(plr)
end
end)
The event fired sends a message to the client, which clones the following script into the player’s character, with an object value inside of the script pointing to the collider object
In client:
local vehicle = script:WaitForChild("vehicle").Value --the collider object
local removeEvent = vehicle.RemoveChar --the event fired when the player leaves the collider
local plr = game.Players.LocalPlayer
local char = plr.Character
local hum = char:FindFirstChildOfClass("Humanoid")
if char:FindFirstChild(script.Name) then script:Destroy() return end --prevent duplicates
hum:SetStateEnabled(Enum.HumanoidStateType.Swimming,false)
removeEvent.OnClientEvent:Connect(function()
hum:SetStateEnabled(Enum.HumanoidStateType.Swimming,true)
script:Destroy()
end)
The collider itself is a union of parts, to accurately encompass all of the rooms of the submarine
Just walking around in the sub however, the Touched and TouchEnded events fire when they are not supposed to, messing with the player’s ability to remain standing.
Your main issue is that the Touched event fires whenever any part of the player touches the collider, even if it’s just their foot briefly brushing against it. This leads to the swimming state being toggled on and off rapidly as the player moves around inside the submarine.
What you could do is make a debounce system, to limit the number of times the script executes within a short timeframe.
as for the collider being a Union, it would have been better with a Region3 since Union can cause unnecessary touches due to its complex & messy mesh structure.
Arent region3s constrained to box shapes? the interior shape of the submarine is more complex than that.
As for the touched event, a debounce may be helpful, i will try implementing that
What I suspect is happening is that the union is forming its collider out of the colliders of the parts it contains, and so leaving one of the parts counts as leaving the collider as a whole. I am making a single mesh instead to try and see a better result.
@toastaspiring To avoid random TouchEnded misfires, I have abandoned the event in favor of this:
while true do wait(.25)
local parts = workspace:GetPartsInPart(collider)
local hums = {}
for _, i in pairs(parts) do
local hum = i.Parent:FindFirstChild("Humanoid")
if not hum then continue end
local found = false
for _, k in hums do
if k == hum then found = true end
end
if not found then table.insert(hums, hum) end
end
local notFound = {}
for _, i in pairs(occupants) do
local found = false
for _, k in pairs(hums) do
if k == i then found = true end
end
if not found then table.insert(notFound, i) end
end
occupants = hums
for _, i in pairs(notFound) do
local plr = game.Players:GetPlayerFromCharacter(i.Parent)
if plr then
print("Remove")
script.Parent.RemoveChar:FireClient(plr)
end
end
end
I dont know how this will work out performance wise, but it is much more reliable