Need help with trap

Im making a dungeon escape game, and im making a trap, theres a bunch of pressure plates, and when you step on the wrong one the camera moves to a anchored part so you can see yourself explode basically, it all works perfectly but i have a script in StarterGui for each part, id like for it all to be in 1 script if its even possible, this is one of the scripts

wait(1)
local TouchPart = game.Workspace.PressurePlates.Plate1
local Camera = game.Workspace.CurrentCamera
local Player = game.Players.LocalPlayer
local Char = Player.Character
local Head = Char.Head
local debounce = true


TouchPart.Touched:Connect(function(Boom)

repeat wait() until Player.Character
	Camera.CameraType = "Scriptable"
	Camera.CFrame = game.Workspace.BombCam.CFrame
wait(1)
local explosion = Instance.new("Explosion")
	if debounce == false then return end
	debounce = false
	explosion.Parent = game.Workspace
	explosion.Position = Boom.Position
	explosion.BlastRadius = 2.5
	explosion.BlastPressure = 25
	wait(2.2)
	debounce = true
	Camera.CFrame = Head.CFrame
	Camera.CameraType = "Follow"
end)

and another problem im having, its a first person game, so when the camera moves to third person, the player is invisible because the game thinks the person is in first person still.

1 Like

You can apply a tag to each of the trap parts and use CollectionService to add behavior to them automatically.

Try something like this: Here I’ve modified your code to apply itself to any part that is tagged with TouchPart. This should be placed in a script in StarterPlayerScripts

local CollectionService = game:GetService("CollectionService")
local Camera = game.Workspace.CurrentCamera
local Player = game.Players.LocalPlayer

local function RegisterTouchPart(TouchPart)
    local debounce = true
    TouchPart.Touched:Connect(function(Boom)
        local Char = Player.Character
        local Head = Char and Char.Head
        if Char == nil or Head == nil then return end
        -- Make sure the part belongs to your character!
        if not Boom:IsDescendantOf(Char) then return end
        if Camera.CameraType == "Scriptable" then return end
        if debounce == false then return end
        debounce = false
        Camera.CameraType = "Scriptable"
        Camera.CFrame = game.Workspace.BombCam.CFrame
        wait(1)
        local explosion = Instance.new("Explosion")
        explosion.Parent = game.Workspace
        explosion.Position = Boom.Position
        explosion.BlastRadius = 2.5
        explosion.BlastPressure = 25
        wait(2.2)
        debounce = true
        Camera.CFrame = Head.CFrame
        Camera.CameraType = "Follow"
    end)
end

for _, TouchPart in CollectionService:GetTagged("TouchPart") do 
    RegisterTouchPart(TouchPart)
end
CollectionService:GetInstanceAddedSignal("TouchPart"):Connect(RegisterTouchPart)
2 Likes

The reason why players in first person are still invisible once you take control of the camera, is because the CameraSubject is still set to their character. Adding a line which changes the CameraSubject over to the anchored part, should fix this issue.

@berezaa’s answer would be a solid solution. Though based on your code, it seems like you could also accomplish this without using CollectionService tags. I’d assume PressurePlates is already a dedicated container? You could use an approach similar to what they demonstrated, just iterating through its children. Though CollectionService makes things neat–as being able to grab direct references to instances, solves potential name collisions when accessing their path.

2 Likes

Why not use 1 .Touched event and check using CollectionService if the part is tagged?
It’s better than having a lot of connections for each individual part.

I think what you mean to say is why not have a single OnPartTouched function? Touched is an event of BasePart, and you are required to make a connection for every single part that you want to listen to, there’s no avoiding that. The number of connections will be the same whether or you use one function or individual anonymous functions like in my example.

In the above example, the TouchPart Touched function requires two key pieces of information for context: the part hitting and the part being hit, let’s call them part0 and part1 of the form part1.Touched:Connect(function(part0) .... The Touched event only passes information about part0, it does not pass information about part1. So if you were to define a single function to act as the handler for all touched events, presumably of the form OnPartTouched(part0, part1), you wouldn’t be able to connect that function to the Touched event and receive all of the information you need.

At best, you could move all of the code to an OnPartTouched function but it would still require the use of a barebones anonymous function to pass information about part 1:

-- Assume OnPartTouched(part0, part1) is defined above

-- This would not work because part1 would not be passed
part1.Touched:Connect(OnPartTouched)

-- This works, but you still make an anonymous function
part1.Touched:Connect(function(part0)
    OnPartTouched(part0, part1)
end

There may be some OOP patterns I’m not aware of that can get around this and let you perfectly define a single touched function that fits this use case, but I don’t think you are going to see any noticeable improvements in code execution performance by doing so. If I missed something and there is a better way of doing this please do let me know.

2 Likes

The way you’d have one touched event (at least per player) would be by making one for the character (either a hitbox or the feet or something). I doubt this would be more efficient because the character’s part would be unanchored and fire hundreds of events as the character walks around.

It’s not worth the time to try to limit touched events–one per player and one per trap are on fairly similar magnitudes. Either solution is fine.

Maybe they could swap

repeat wait() until Player.Character

for

repeat task.wait() until Player.Character

or maybe ideally

if not player.Character then
	player.CharacterAdded:Wait()
end

(though there is a bigger problem with that code block from it being in starter gui and having reset on respawn and them waiting for the character but not setting their character variable again)

TL;DR: The golden rule of optimization: don’t do it*.
* unless you have to


@OP:

I’d recommend putting the script you have in StarterPlayerScripts and additionally checking if the hit is part of the character refer to Bereza

1 Like

I meant when touching HumanoidRootPart, check if the part is a trap and that’s it.
You can modify CollectionService tags on the properties menu nowadays.

Note the script cant be clientside, since then you’d do
if not game:IsLoaded() then game.Loaded:Wait() end

replace repeat wait() until Player.Character with local Character=Player.Character or Player.CharacterLoaded:Wait() i think

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.