So I was making a script that shows a text on your screen when you’re close to a part, To do this I used a for loop and looped through a folder but I just realized that if the folder had multiple parts the text will never show up due to the fact that other parts may be not close to me, Im trying to see if there’s a better way to do this.
my script:
while wait() do
for i, v in pairs(game.Workspace.Hays:GetChildren()) do
local UpMag = (math.abs(player.Character.HumanoidRootPart.Position.Y) - math.abs(v.Position.Y))
local DisMag = (math.abs(player.Character.HumanoidRootPart.Position.X) - math.abs(v.Position.X))
local HoriMag = (math.abs(player.Character.HumanoidRootPart.Position.Z) - math.abs(v.Position.Z))
if math.floor(DisMag) <= 11 and math.floor(UpMag) >= script.MinHeight.Value and math.floor(HoriMag) <= 30 and math.floor(HoriMag) > 0 then
if CanLeap == true then
print("yes")
player.PlayerGui.LOF_Msg.Msg.Visible = true
else
player.PlayerGui.LOF_Msg.Msg.Visible = false
end
else
player.PlayerGui.LOF_Msg.Msg.Visible = false
end
end
end
Something like a hitbox would be a better solution to this, because as it is you’re looping through some number of parts once per frame. It’s probably fine, but if you have a lot of parts that might get slow.
Anyways, the idea for loops like this is something like this (obviously you’ll need to adapt it)
local isCloseEnough = false
for i, v in pairs(children) do
if (PlayerIsNearby(v)) then
isCloseEnough = true
break
end
end
if (isCloseEnough) then
print("yes")
else
print("no")
end
Again though, I think there are better ways to achieve what you’re trying to do without this loop-check stuff.
It would be easier to describe what you’re trying to accomplish. You’ve told us “this is how I’m solving this problem: with a for loop”, but there’s probably a better way to do what you want.
Im trying to make a text appear when a person is atleast 14 studs higher than a part, I have multiple parts which mean i wonts be 14 studs high than every single part which makes the text always transparent due to the fact the part’s positions differ
Why not use an if statement for finding the magnitude of the part. If the players magnitude >= 14 then the distance of the part then the text will display.
I’m still not really sure why you’re doing what your doing, but that’s OK.
If you really want to keep doing it that way, GetPropertyChangedSignal won’t work to detect position changes. It’s bad with Position updates. And anyways, that changed event would fire pretty much every frame anyways, so you might as well skip the event and check every frame.
Here, I refactored your code and labeled where I changed things with comments. I haven’t tested it so there might be some typos, but it should be mostly fine. You have to do some work to integrate it with whatever system you’re using (for example, I assumed “player” was a variable because I don’t know where you got that from).
local folder = game.Workspace.Hays
local root = player.Character.HumanoidRootPart
local gui = player.PlayerGui.LOG_Msg.Msg
-- distance you must be within on the X axis
local maxX = 11
-- min on the Y axis
local minY = script.MinHeight.Value
-- max on the Z
-- issue 0: Why are your X and Z limits different?
local maxZ = 30
local function update()
local shouldShow = false
for _, part in pairs(folder:GetChildren()) do
-- issue 1: you were subtracting the absolutes. You should absolute the
-- subtraction instead:
local dx = math.abs(root.Position.X - part.Position.X)
local dy = math.abs(root.Position.Y - part.Position.Y)
local dz = math.abs(root.Position.Z - part.Position.Z)
-- issue 2: no need for math.floor
-- also since dx,dy,dz are all positive now this check is simpler:
if (dx < maxX and dy > minY and dz < maxZ) then
-- issue 3: don't set the visibility on/off yet. Just determine that
-- you should show it...
shouldShow = true
-- ...and exit the loop because we don't need to check anything else
break
end
end
-- issue 3b: ... NOW we can determine visibility because if we're within ONE
-- of the parts, that loop up there would've caught it and set shouldShow.
-- So, we can just use shouldShow directly:
gui.Visible = shouldShow
end
-- issue 4: instead of a loop, we bind our update to the rendering step so it
-- just runs before anything gets rendered.
-- issue 5: As I said, you ideally wouldn't do this -- you're checking so often!
-- A better method would be to not do the distance checking at all, and instead
-- rely on Touched/TouchEnded events or something but for now this should work
game:GetService("RunService"):BindToRenderStep(
"positionCheck",
Enum.RenderPriority.First.Value,
update
)
edit:
Also, I don’t know if you’re doing this in a persistent LocalScript or not - if you are, fine. If not, you’re going to need to add logic to bind/unbind that renderstep update when a player joins/leaves.