I have a platform that when the user stands on it, a Gui should be displayed. This is not as easy as it seems like it should be, because there is no TouchStarted event, only a Touched event and a TouchEnded event. And the Touched event gets fired continuously as a user walks around on the part, rather than only the first time they touch it.
I have tried to do something like this:
script.Parent.Touched:Connect(function(Object)
local Player = Players:GetPlayerFromCharacter(Object.Parent)
if not Player then
return
end
-- My own internal data structure that keeps pack of per-player session data.
local SessionData = GameInstanceData[Player.UserId].SessionData
if SessionData.PartGuiReason == Object then
print("Not showing PlayerGui because one is already displayed.")
return
end
SessionData.PartGuiReason = Player
local MyGui = game:GetService("ServerStorage"):WaitForChild("MyGui")
SessionData.PartGui = MyGui()
SessionData.PartGui.Parent = Player.PlayerGui
print("PlayerGui added for player %s" .. Player.Name)
end)
script.Parent.TouchEnded:Connect(function(Object)
local Player = Players:GetPlayerFromCharacter(Object.Parent)
if not Player then
return
end
local SessionData = GameInstanceData[Player.UserId].SessionData
if SessionData.PartGuiReason ~= Player then
print("Not clearing PlayerGui because the TouchEnded event part did not match the PartGuiReason")
return
end
SessionData.PartGuiReason = nil
-- Unparent it to get it out of the player's Workspace.
SessionData.PartGui.Parent = nil
SessionData.PartGui = nil
print("PlayerGui removed for player %s" .. Player.Name)
end)
But this doesn’t seem to work either, because I get tons of TouchEnded events as the right and left legs leave the ground during the walk animation.
I feel like I’m overcomplicating this though, and there should be like 3-5 lines of code I can write that just solve the problem trivially.
I can’t seem to think of another way to do so using touched events, but you might try using region3. Put a region above the platform and detect when the user is in it and when the user leaves it. Region3 | Documentation - Roblox Creator Hub
You can try using debounce thing. Here’s how it works:
local debounce = false
script.Parent.Touched:Connect(function()
if debounce == false then
debounce = true --This will prevent function from firing multiple times
--Rest of your code here
end
end)
script.Parent.TouchEnded:Connect(function()
--Your code here
wait(1) --To prevent code from firing until player actually leaves the platform
debounce = false --Our code can run again
end)
I would have suggested that although another issue is that everytime a leg is lifted while walking on the platform the script sees that as a TouchEnded event which would negate the entire debounce system.
Yea, I’ve tried all of this. Another thing I’ve tried is making an invisible cylinder (or box) with CanCollide = false and putting a weld constraint on it so that it moves with my character, and then checking if the platform is touching this cylinder, rather than any part of the humanoid.
But even when I’m standing right smack in the middle of the platform, it keeps firing Touched followed immediately by TouchEnded, which doesn’t make any sense. It seems like Touch events are kind of just buggy
Try doing this locally and raycast to the ground to see if the player is standing on the shop ground.
If they are then show the gui, if not then close it. You could also try detecting touched by placing an invisible region on the shop instead
local debounce = false
local debounce2 = false
script.Parent.Touched:Connect(function()
if debounce == false then
debounce = true --This will prevent function from firing multiple times
--Rest of your code here
end
end)
script.Parent.TouchEnded:Connect(function()
if debounce2 == false then
debounce2 = true
--Your code here
wait(1) --To prevent code from firing until player actually leaves the platform
debounce = false --Our code can run again
debounce2 = false
end
end)
Why not just calculate the distance (for a radius) between the Player’s HumanoidRootPart and the shop thing itself. If the player is within the distance then the UI is open, the moment they aren’t you can simply ask for it to close. Using a debounce you can then prevent it from reopening. If you are worried about processing time then start capturing the moment the player touches a region. The moment they leave said region by a safe distance then end the capture and close the UI.
That way you can just use the x, y, z components of the position to validate whether a player has entered the desired region.
script.Parent.Touched:Connect(function(hit)
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
if hit.Parent:FindFirstChild("Humanoid") ~= nil then
script.Parent.ShowUI:fireClient(player)
end
end)
For show ui:
(Put this on The UI and make sure that the ui is inside starterGui)
I wouldn’t recommend using region3, but I would however, recommend using .Magnitude.
So, what you will do is constantly check if the HumanoidRootPart is within a certain radius of something using Runservice. And once it’s in a certain magnitude, open the GUI
If you are worried that detecting the magnitude 40 - 60 times per second is too much(which will happen), you can use this method:
You can try detecting only if the right or left foot of the player is touching the part, so all you have to do is edit in this line to both your events:
Change:
if not Player then
to:
if not Player or Object.Name not == "RightFoot" then
If your stilling having a problem just loop creating a ray starting from you character and straight down and this will detect if you are standing on the platform and make sure when you find the part on the ray you use an ignore list of your character so the ray goes trough your character.
YourRayHere = Ray.new(YOURCHATACTERSHUMANOIDROOTPART, Vector3.new(0,-10,0)*100)
Hi Guys, I know this thread is over a year old but I was also having the same issue - I wanted to touch a part and have a message pop-up to the player for a short period of time and then vanish.
My solution eventually came down to something quite small and very usable and I want to share it here as I am sure this topic will come up many times in the future:
On the part being touched, I placed this (server) script:
function onTouched(part)
local h = part.Parent:findFirstChild(“Humanoid”)
if (h~=nil) then
local thisplr = game.Players:findFirstChild(h.Parent.Name)
if part.Parent:FindFirstChild("TheMagicItem") then
script.Parent:Destroy() -- destory or otherwise interact with the part
print('Found Tool magic magic item') -- and place whatever you want here for testing purposes
else
print("player touched the part but needs a magic item to interact it")
local GuiStal = game:GetService("ServerStorage").Guis
script.Parent.Touched:connect(function(Part)
local Player = game.Players:GetPlayerFromCharacter(Part.Parent)
if Player and not Player.PlayerGui:FindFirstChild("Guis") then -- copies the GUI ONCE ONLY
print("Adding the GUI to the player")
GuiStal:Clone().Parent = Player.PlayerGui -- GUI pops up with message
wait(8)
Player.PlayerGui:FindFirstChild("Guis"):Destroy() -- remove the GUI after 8 seconds
end
end)
end
end
end
script.Parent.Touched:connect(onTouched)
Inside ServerStorage I created a folder called Guis and within that folder I added a screen gui which had a simple text label containing the message. When the part is touched, the GUI is copied from server storage and appears on the player’s screen. The after 8 seconds disappears as it is removed from the playergui.
This might not be the best implementation but it is small and works well.