Touched event doesn't fire

Hello! I’m trying to make a capture the flag game, and I’m trying to test touching the flag stands. The problem is that the Touched event doesn’t fire at all, with no errors popping up in the output. The position of the flag stands do print, proving that I got them. The flag stands are inside of the maps, in replicated storage, and aren’t in the workspace until they are cloned.
I’ve tried making the variables global, moving the function out of the while loop, and trying to place the variables outside of the function, but WaitForChild doesn’t have an option to make it recursive.

local Lobby = workspace.Lobby
local Maps = game.ReplicatedStorage.Maps:GetChildren()
local Status = game.ReplicatedStorage.Status
local Teams = {game.Teams.Red, game.Teams.Blue}
local intermissionTime = 5
local roundTime = 180
while true do
	-- Intermission
	for i = intermissionTime, 0, -1 do
		Status.Value = "Intermisson: "..i
		task.wait(1)
	end
	
	-- Spawn Random map
	local chosenMap = Maps[math.random(1, #Maps)]
	local clonedMap = chosenMap:clone()
	
	clonedMap.Parent = workspace
	Status.Value = "Map: "..clonedMap.Name
	
	task.wait(3)
	local BlueFlagStand = game.Workspace:FindFirstChild("BlueFlaStand", true)
	local RedFlagStand = game.Workspace:FindFirstChild("RedFlagStand", true)
	print(RedFlagStand.Position)
	-- Assign teams
	for i, player in pairs(game.Players:GetPlayers()) do
		if player then
			local randomTeam = Teams[math.random(1, #Teams)]
			player.Team = randomTeam
			player:LoadCharacter()
		end
	end
	
	-- Game timer
	for i = roundTime, 0, -1 do
		Status.Value = "Game: ".. i
		task.wait(1)
	end
	
	RedFlagStand.Touched:Connect(function(hit)
		print(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
			local char = hit.Parent
			print("Touched")
		end
	end)
	-- Spawm players back into the lobby
	for i, players in pairs(game.Players:GetPlayers()) do
		if players then
			players.Team = game.Teams.Waiting
			players:LoadCharacter()
		end
	end
	clonedMap:Destroy()
end

Please do not ask people to write entire scripts or design entire systems for you. If you can’t answer the three questions above, you should probably pick a different category.

3 Likes

I’m sorry to ask such a simple question but is this a local or a server script?
BasePart.Touched Doesn’t fire when on a local script.

some things you may want to consider:
if it’s a local script
Where local scripts will run
if the flags have “Can Collide” off
Non-Collide parts and touching parts

Second post on the forum sorry if it isn’t helpful!

1 Like

This is in a server script in ServerScriptService

1 Like

Did you check if the object has can collide on?

1 Like

And canTouch (if cancollide is off)

You could also try using magnitude of distance between each plr and the flag or Introduction - ZonePlus

(although I wouldn’t suggest it for this)

1 Like

Both Can collide and can touch are on

2 Likes

Make sure that the names you’re using to find the flag stands are correct. In your code, you’re looking for flag stands named “BlueFlaStand” and “RedFlagStand”. There seems to be a typo in “BlueFlaStand”.

1 Like

Fixing the typo does not solve the issue unfortunately

1 Like

Then it might be something with event connection timing; the event connection for the Touched event is being set up inside the loop where you’re iterating through the maps and managing the game flow. This means that you’re creating a new event listener each time you go through the loop. This could potentially lead to multiple listeners being attached, causing unexpected behavior.
Here’s an example of how you can modify your code to address these issues:

-- Other code above remains the same

local BlueFlagStand = game.Workspace:WaitForChild("BlueFlagStand")
local RedFlagStand = game.Workspace:WaitForChild("RedFlagStand")

RedFlagStand.Touched:Connect(function(hit)
    local character = hit.Parent
    local player = game.Players:GetPlayerFromCharacter(character)
    if player then
        print(player.Name .. " touched the Red flag stand!")
    end
end)

-- Start the game loop
while true do
    -- Rest of your game loop logic

    -- Inside the loop, you can update the positions of the flag stands if they are dynamically changing

    -- Rest of your game loop logic
end

I used WaitForChild instead of FindFirstChild to ensure that the script waits until the flag stands are available in the workspace. Also, I’ve moved the event connection outside of the loop to ensure that only one event listener is attached for each flag stand.

The problem is, WaitForChild doesn’t seem to have an option to make it recursive, is there a way to do that?

1 Like

this is where the problem most likely is. You are using a for loop before the touched event is connected, and this game timer loop is yielding the rest of the script. A solution would be to put that part in a coroutine.

local timer=coroutine.create(function()
    for i = roundTime, 0, -1 do
		Status.Value = "Game: ".. i
		task.wait(1)
	end
end)
coroutine.resume(timer)

you can then later stop the timer with coroutine.close or pause with coroutine.yield

edit: I realized this can cause your game to crash since all of the code is in a while loop, and when removing that for loop it never yields. So you’ll need some sort of way to know when the game is being played and when its over, this is to stop the game from repeat everything before the round is over.
You could also move the for loop to after you connect the touched events but before you start the round ended part

I forgot WaitForChild doesn’t have a built-in option for recursive searching. In this case, you can implement your own recursive function to wait for the flag stands to appear in the workspace.
Here’s an example:

-- Recursive function to wait for a child to appear
local function WaitForChildRecursive(parent, childName)
    local child = parent:FindFirstChild(childName)
    if child then
        return child
    else
        local connection
        local promise = Instance.new("BindableEvent")

        connection = parent.ChildAdded:Connect(function(childAdded)
            if childAdded.Name == childName then
                connection:Disconnect()
                promise:Fire(childAdded)
            end
        end)

        local result = promise.Event:Wait()
        promise:Destroy()

        return result
    end
end

-- Wait for the flag stands to appear
local BlueFlagStand = WaitForChildRecursive(game.Workspace, "BlueFlagStand")
local RedFlagStand = WaitForChildRecursive(game.Workspace, "RedFlagStand")

if not BlueFlagStand or not RedFlagStand then
    error("Flag stands not found!")
end

-- Rest of your script remains the same

This code defines a WaitForChildRecursive function that will wait for a child with the specified name to appear in a parent. It uses a BindableEvent and a connection to the ChildAdded event to wait for the child to be added if it doesn’t exist initially. I’m not sure if this will work, but you can try.

I tried using this, but while loop doesn’t run unless I put the function below it, and it still doesn’t work then

1 Like

If the while loop doesn’t run unless you place the WaitForChildRecursive function below it, it might be due to the fact that the flag stands are not being found in the workspace, causing the script to get stuck in the waiting loop.
you can add some debugging output to better understand what’s happening.

-- Recursive function to wait for a child to appear
local function WaitForChildRecursive(parent, childName)
    local child = parent:FindFirstChild(childName)
    if child then
        return child
    else
        local connection
        local promise = Instance.new("BindableEvent")

        connection = parent.ChildAdded:Connect(function(childAdded)
            if childAdded.Name == childName then
                connection:Disconnect()
                promise:Fire(childAdded)
            end
        end)

        local result = promise.Event:Wait()
        promise:Destroy()

        return result
    end
end

-- Wait for the flag stands to appear
local BlueFlagStand = WaitForChildRecursive(game.Workspace, "BlueFlagStand")
print("BlueFlagStand found")

local RedFlagStand = WaitForChildRecursive(game.Workspace, "RedFlagStand")
print("RedFlagStand found")

if not BlueFlagStand or not RedFlagStand then
    error("Flag stands not found!")
end

-- Rest of your script

You should be able to see in the console whether the script successfully finds the flag stands or if it’s getting stuck in the waiting loop. If you see the “BlueFlagStand found” and “RedFlagStand found” messages, it means the script found the flag stands, and the issue may lie elsewhere in your script. If you don’t see these messages, it means the script is still waiting for the flag stands to appear. Maybe try checking if the flag names match the names in the script and model of the flags in your game; other than that, idk.

The Red and BlueFlag messages don’t show up, and the name is correct. I think the problem is that they don’t spawn in until the while loop runs

1 Like

I tried doing this in a separate script, to no success

-- Recursive function to wait for a child to appear
local function WaitForChildRecursive(parent, childName)
	local child = parent:FindFirstChild(childName)
	if child then
		return child
	else
		local connection
		local promise = Instance.new("BindableEvent")

		connection = parent.ChildAdded:Connect(function(childAdded)
			if childAdded.Name == childName then
				connection:Disconnect()
				promise:Fire(childAdded)
			end
		end)

		local result = promise.Event:Wait()
		promise:Destroy()

		return result
	end
end

-- Wait for the flag stands to appear
local BlueFlagStand = WaitForChildRecursive(game.Workspace, "BlueFlagStand")
print("BlueFlagStand found")

local RedFlagStand = WaitForChildRecursive(game.Workspace, "RedFlagStand")
print("RedFlagStand found")

if not BlueFlagStand or not RedFlagStand then
	error("Flag stands not found!")
end

RedFlagStand.Touched:Connect(function(hit)
	print(hit)
	if hit.Parent:FindFirstChild("Humanoid") then
		local char = hit.Parent
		print("Touched")
	end
end)

wait wait wait wait wait actually isn’t the issue just that you initiate the game timer BEFORE you connect the touched events? shouldn’t you connect the events first? otherwise you need to wait for the game to end before the flags would work

just swap the order of the Game timer and the events

I already said that the game timer doesn’t run unless ai place the extra code below

1 Like

dont seem to see that but ok

why doesn’t it run? that might be the issue : P

I figured out that my new script doesn’t run because apparently red and blue flag stands are nil

1 Like