Hello everyone,
I am making a script so that a UI pops up when a player is on the shopEnter part, and closes when the player leaves the part.
However, the only efficient way to do this that I’m aware of is getting .TouchEnded and getting the character that way, but .TouchEnded is called even when the player doesn’t touch the part and just walks or an animation plays etc
Can you clarify this part a little bit more? It’s kind of hard to understand.
Do you mean getting the character when TouchEnded() is called? Why not just directly close the GUI when the player leaves the part? Unless I’m missing something that requires the character in the TouchEnded() function.
Sorry, I mean Part.TouchEnded(), and then get the char from that
The problem is with how .Touched
works: if you stop moving while on the part, there’s no “still on the part” event. They end up firing every time the player moves while still on the part.
I can give you a zone code that can handle this perfectly. Would you like that posted?
Yes please, that would be very helpful!
But can’t you also do TouchEnded on the zone part instead of checking every frame?
Touch will act oddly with how you’re using it here. Many run into this problem with .TouchEnded()…
Let me re-do this with one script, cutting out the generic set-up part and just focusing on a manually set up Region3.
--ServerScript in ServerScriptService
local rns = game:GetService("RunService")
local zoneRegion = Region3.new(Vector3.new(-10, 0, -10), Vector3.new(10, 10, 10)) -- Set your own region coordinates
local trackedItems = {}
local itemEntered = Instance.new("BindableEvent")
local itemExited = Instance.new("BindableEvent")
itemEntered.Event:Connect(function(item)
print(("%s entered the zone!"):format(item.Name))
end)
itemExited.Event:Connect(function(item)
print(("%s exited the zone!"):format(item.Name))
end)
task.spawn(function()
while true do
local itemsInZone = {}
local parts = workspace:FindPartsInRegion3(zoneRegion, nil, math.huge)
for _, part in ipairs(parts) do
local item = part.Parent
if item:FindFirstChild("Humanoid") then
if not trackedItems[item] then
trackedItems[item] = true
itemEntered:Fire(item)
end
itemsInZone[item] = true
end
end
for item in pairs(trackedItems) do
if not itemsInZone[item] then
trackedItems[item] = nil
itemExited:Fire(item)
end
end
rns.Stepped:Wait()
end
end)
Keep in mind this is a box (Region3) set up over (on top of) the part you’re stepping on.
Utility script to get coordinates if needed.
part to Region3 call
--using a (box) part named Zone as a reference
local part = workspace:WaitForChild("Zone")
local size = part.Size
local position = part.Position
local min = position - size / 2
local max = position + size / 2
print(("local zoneRegion = Region3.new(Vector3.new(%.0f, %.0f, %.0f), Vector3.new(%.0f, %.0f, %.0f))")
:format(min.X, min.Y, min.Z, max.X, max.Y, max.Z))
--copy from the output
You might want to check out this resource by ForeverHD:
Here is some example code from that:
-- This constructs a zone based upon a group of parts in Workspace and listens for when a player enters and exits this group
-- There are also the ``zone.localPlayerEntered`` and ``zone.localPlayerExited`` events for when you wish to listen to only the local player on the client
local Zone = require(game:GetService("ReplicatedStorage").Zone)
local container = workspace.AModelOfPartsRepresentingTheZone
local zone = Zone.new(container)
zone.playerEntered:Connect(function(player)
print(("%s entered the zone!"):format(player.Name))
end)
zone.playerExited:Connect(function(player)
print(("%s exited the zone!"):format(player.Name))
end)
I’m going to implement this script and I’ll tell you if it works well
Region3 methods are deprecated. It’s best to use workspace:GetPartsInPart()
and/or workspace:GetPartBoundsInBox()
instead. I also agree with BendsSpace.
Then why not post your scripts? Let your programming do the talking…
GetPartsInPart()
--this version will need the zonepart to stay on the workspace.
local zonePart = workspace:WaitForChild("ZonePart")
zonePart.Transparency = 1
--these can be set on the part itself
zonePart.CastShadow = false
zonePart.CanCollide = false
zonePart.CanTouch = true
zonePart.CanQuery = true
zonePart.Anchored = true
zonePart.Locked = true
--
local rns = game:GetService("RunService")
local trackedItems = {}
local itemEntered = Instance.new("BindableEvent")
local itemExited = Instance.new("BindableEvent")
itemEntered.Event:Connect(function(item)
print(("%s entered the zone!"):format(item.Name))
end)
itemExited.Event:Connect(function(item)
print(("%s exited the zone!"):format(item.Name))
end)
task.spawn(function()
while true do
local itemsInZone = {}
local touching = workspace:GetPartsInPart(zonePart)
for _, part in ipairs(touching) do
local item = part:FindFirstAncestorOfClass("Model")
if item and item:FindFirstChild("Humanoid") then
if not trackedItems[item] then
trackedItems[item] = true
itemEntered:Fire(item)
end
itemsInZone[item] = true
end
end
for item in pairs(trackedItems) do
if not itemsInZone[item] then
trackedItems[item] = nil
itemExited:Fire(item)
end
end
rns.Stepped:Wait()
end
end)
GetPartBoundsInBox()
--this version will need the zonepart to stay on the workspace.
local zonePart = workspace:WaitForChild("ZonePart")
zonePart.Transparency = 1
--these can be set on the part itself
zonePart.CastShadow = false
zonePart.CanCollide = false
zonePart.CanTouch = true
zonePart.CanQuery = true
zonePart.Anchored = true
zonePart.Locked = true
--
local rns = game:GetService("RunService")
local trackedItems = {}
local itemEntered = Instance.new("BindableEvent")
local itemExited = Instance.new("BindableEvent")
itemEntered.Event:Connect(function(item)
print(item.Name .. " entered the zone!")
end)
itemExited.Event:Connect(function(item)
print(item.Name .. " exited the zone!")
end)
task.spawn(function()
while true do
local cf = zonePart.CFrame
local size = zonePart.Size
local parts = workspace:GetPartBoundsInBox(cf, size)
local itemsInZone = {}
for _, part in ipairs(parts) do
local item = part:FindFirstAncestorOfClass("Model")
if item and item:FindFirstChild("Humanoid") then
if not trackedItems[item] then
trackedItems[item] = true
itemEntered:Fire(item)
end
itemsInZone[item] = true
end
end
for item in pairs(trackedItems) do
if not itemsInZone[item] then
trackedItems[item] = nil
itemExited:Fire(item)
end
end
rns.Stepped:Wait()
end
end)
This is more of a technique to do this along with a working command.
The outcome here you should be going for is… posting a working script/technique.
I’m looking for a way to fix the issue here, and testing techniques is how you get there.
I’m not looking for a debate. If you have something that will work, post it.
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.