I'm trying to execute the code in the while loop in correspondence with the value of "active". However, it isn't running. The script is indeed enabled, and script.Parent is indeed a BasePart..
local active, author = false script.Parent.Touched:connect(function(hit) if pcall(function() return hit.Parent.Humanoid end) then local player = game.Players:playerFromCharacter(hit.Parent) active, author = true, player end end) script.Parent.TouchEnded:connect(function() active, author = false end) -- edit while active and wait() do warn(author, '\n') end
Probably a silly error, but i can't seem to figure out what it is.
There's no reason to have separate author
and active
variables, since active
will always be the same as author ~= nil
.
You shouldn't use pcall
to do work for you. It's slow, complicated, and confusing. Write code that doesn't error instead of trying to cover it up. In this case, it's really, really easy to avoid that code:
local touching = nil script.Parent.Touched:connect(function(hit) local player = game.Players:GetPlayerFromCharacter(hit.Parent) if player then touching = player end end)
Your code was missing a closing paren after the end
on line 12.
script.Parent.TouchEnded:connect(function() touching = nil end
The final while
loop has a problem. Whenever touching
became false
, the loop would stop -- and not resume. If you want to something "whenever active
is true" you have to loop forever and check if touching then
:
while wait() do if touching then print(touching, "is touching me") else print("no one is touching me") end end
There are a few caveats to this overall design:
Both of these are a little difficult to solve.
You can more or less solve them using dictionaries:
local touching = {} script.Parent.Touched:connect(function(hit) local player = game.Players:GetPlayerFromCharacter(hit.Parent) if player then touching[player] = true end end script.Parent.TouchEnded:connect(function(hit) local player = game.Players:GetPlayerFromCharacter(hit.Parent) if player then touching[player] = nil end end
Instead of having a single "touching", we save the state more or less for all players using a dictionary.
You can get all of the players currently touching with a generic for loop:
while wait() do for player in pairs(touching) do print(player, "is touching") end end
One problem with this is if the TouchEnded event doesn't fire. I believe this will happen if, for instance, the player leaves or despawns. It would be safest to also ensure that the original part survived. Thus, instead of using true
, we'll save hit
:
script.Parent.Touched:connect(function(hit) local player = game.Players:GetPlayerFromCharacter(hit.Parent) if player then touching[player] = hit end end
and we'll delete "dead" touches in the loop:
for player, part in pairs(touching) do print("player is touching") if not part.Parent then -- The part no longer exists, so forget about this player touching[player] = nil end end
This is still a little lacking -- if you stand on the button with one leg, and the other brushes against it, that TouchEnded will say you are no longer pressing the button. Ideally, we would only worry about the final touch.
We could use a dictionary, or just keep track of a count, adding 1 for a touch and subtracting for a touch ended.