Sword Arena not working

Hello. I was going to make a sword fight arena for my game but there are some bugs. Check the video and script for more info. Thank you for your time!

local character = script.Parent -- The script is located is StarterCharacterScripts
local Player = game.Players:GetPlayerFromCharacter(script.Parent)
local PlrBackPack = Player.Backpack


character.HumanoidRootPart.Touched:Connect(function(zone)
	if zone.Name == "PvPZ" and not PlrBackPack:FindFirstChild("LinkedSword") and not character:FindFirstChild("LinkedSword") then
		local Sword = game.Lighting.Storage.LinkedSword:Clone()
		Sword.Parent = PlrBackPack
	end
end)

character.HumanoidRootPart.TouchEnded:Connect(function(zone)
	if zone.Name == "PvPZ" and PlrBackPack:FindFirstChild("LinkedSword") or zone.Name == "PvPZ" and character:FindFirstChild("LinkedSword")then
		character.LinkedSword:Destroy()
		PlrBackPack.LinkedSword:Destroy()
	end
end)

-- the sword only gets destroyed when I have the sword equiped and the sword keeps on 

video: Crowned Projects's Place Number_ 0 - Roblox Studio 2021-05-12 16-09-57.mp4 - Google Drive

Ignor the messages on the video due to the resolution. All I explain was that the sword keeps on destroying even though touch hasn’t ended and that the Tool only deletes when Workspace.(MyCharacter) is the Parent of the tool.

Hello, I think that the problem here is that you might have a part(floor) on touched event so whenever you touch the floor player gets the sword you need to change that to something bigger for example make transparent part with can collide and scale it up(above the character height even when it jumps) and scale its x and z to the zones size.

Sorry, I forgot to state that I added an Invisible barrier

So you added an invisible Box and it still didn’t work?

Yea, I have no idea what Is Happening

So basically touch and touchended keeps repeating over and over can you screen the box in the workspace pls? And also 1thing can you add prints in your touched events so we know if repeating Is the problem.

Here’s the thing:

Both the Touched & TouchEnded Events are detecting the current names of the zone, so it’s repeatedly firing over & over again (Or removing & adding the Tool in a fast way)

I wouldn’t rely on detecting for a TouchEnded event, as it can become extremely unreliable in certain instances

What I’d recommend doing, is using Region3 which can be used to obtain a specific region of the world area (It’d be really useful in this Instance) or Magnitude through a loop:

--Server Script inside ServerScriptService
local Part = workspace.PvPZ
local Tool = game.Lighting.Storage:WaitForChild("LinkedSword")

while true do
    for _, Player in pairs(game.Players:GetPlayers()) do
        local Character = Player.Character
        if Character and Player.Backpack:FindFirstChild("LinkedSword") == nil and Character:FindFirstChild("LinkedSword") == nil then
            if (Character.HumanoidRootPart.Position - Part.Position).Magnitude < 25 then
                local Clone = Sword:Clone()
                Clone.Parent = Player.Backpack
            end
        else
            if Player.Backpack:FindFirstChild("LinkedSword") then
                Player.Backpack.LinkedSword:Destroy()
            else
                Character.LinkedSword:Destroy()
            end
        end
    end
    wait(1)
end
1 Like

I think it’s better to use region3 then magnitude in this case, so you won’t have to use while loop.
Edit: but the script works perfectly fine and fixes the problem :slightly_smiling_face:

Thing is, you’d still need to detect when a Player enters a Region by encasing it inside a loop so that it updates frequently & have it not fire just once

And you’d also need to detect when players exit out of a Region so you can remove the Tool

1 Like

Yes but also no. The native Region3 checks can be considerably expensive, so you want to avoid constantly polling them in an infinite loop. What I do is use Touched to start the loop that polls for Region3 checks, and have that loop stop it’s self the first time it detects no characters within the Region3.

Here’s that logic being used for a sliding door; apologies for the mess.

function SlidingDoor:Start()
    self:Disconnect('TouchSignal')

    self.TouchSignal = self.TouchPart.Touched:Connect(function(touchedPart)
        if self.StepSignal then return end -- early exit from the Touched handler if we're currently polling Region3's 

        -- check touched by character
        if touchedPart.Parent:FindFirstChild('Humanoid') then

            local playerTouched = game:GetService('Players'):GetPlayerFromCharacter(touchedPart.Parent)
            if playerTouched then
                self.PlayerTouchedBindable:Fire(playerTouched, true)
            end

            -- every server step check to make sure at least 1 character still standing in region
            self.StepSignal = RunService.Heartbeat:Connect(function()
                local tryCycle = true
                local playersInRegion = {}

                local parts = self.Region:Cast(self.IgnoreList)

                for i = 1, #parts do
                    if parts[i].Parent:FindFirstChild('Humanoid') then
                        tryCycle = false

                        local player = game:GetService('Players'):GetPlayerFromCharacter(parts[i].Parent)
                        if player then

                            playersInRegion[player] = true

                            if not self.PlayersTouching[player] then
                                self.PlayersTouching[player] = true
                                self.PlayerTouchedBindable:Fire(player, true)
                            end
                        end
                    end
                end

                for player, _ in pairs(self.PlayersTouching) do
                    if not playersInRegion[player] then
                        self.PlayerTouchedBindable:Fire(player, false)
                        self.PlayersTouching[player] = nil
                    end
                end

                -- no chars in region; make sure we're not still opening and close doors
                if self.IsAnimating then return end
                
                if tryCycle then
                    self:Animate()

                    self:Disconnect('StepSignal')
                end
            end)

            self:Animate()
        end
    end)
end
3 Likes