So I tried to make like multiple parts in a table and if one of those parts are in rage of the player then activate (do something) but I have no idea how to make it that the closest part to the player activates and not all the parts in range…
local runservice = game:GetService("RunService")
local player = game.Players.LocalPlayer
local inrange = false
local interactable_items = {
game.Workspace.Toy1,
game.Workspace.Toy2,
game.Workspace.Toy3
}
local function distancecheck()
local distance = 10
local object
for i, v in pairs(interactable_items) do
if (v.Position - player.Character.HumanoidRootPart.Position).magnitude < distance then
print("player in range")
inrange = true
object = v
end
end
return object
end
runservice.RenderStepped:Connect(function()
local object = distancecheck()
if object and inrange == true then
object.Position = object.Position + Vector3.new(0, 5, 0) -- do something
end
end)
When you loop through the objects, you should update distance to the parts that are within the 10 stud range. This way you will truly get the closest part instead of the last part that is within the range.
Also, it’s a bad practice to have the global variable inrange
for a function you call to check distance, especially if you never turn to back to false. If object
returns nil from your distancecheck()
function, then it means no parts were in range and the inrange
variable is obsolete.
Yeah I understand that but how do I do that? like how can I apply your method
You just update a variable…?
local function distancecheck()
local distance = 10 -- min range
local object
for i, v in pairs(interactable_items) do
local dist = (v.Position - player.Character.HumanoidRootPart.Position).magnitude
if dist < distance then
print("player in range")
distance = dist -- update distance so only parts closer than this one can be selected
object = v
end
end
return object
end
And then remove all mention of inrange
because it serves no purpose.
1 Like
I tryed something like that before and didn’t worked properly, like I tried to apply it again now but still not really working…
I updated the script to this:
local runservice = game:GetService("RunService")
local player = game.Players.LocalPlayer
local interactable_items = {
game.Workspace.Toy1,
game.Workspace.Toy2,
game.Workspace.Toy3
}
local function distancecheck()
local mindistance = 10
local object
for i, v in pairs(interactable_items) do
local distance = (v.Position - player.Character.HumanoidRootPart.Position).magnitude
if distance < mindistance then
print("player in range")
mindistance = distance
object = v
else
print("player not in range")
v.Keybind.Enabled = false
end
end
return object
end
runservice.RenderStepped:Connect(function()
local object = distancecheck()
if object then
object.Keybind.Enabled = true
end
end)
So basically the closer part should activate that gui but it activates both and not the closer one
Here is a screenshot:
I’m sure i’m doing something bad, my scripting experiences are not that good
The reason they’re both visible is because you’re never setting the object’s Keybind to false, so if the object returns in the RenderStepped once it will forever be active. You should have a variable that stores the previous active part (if there was one). When you get a new part from the distancecheck
function, if that part is not the previous part, then disable the previous part.
I can’t test this, but this should work:
local previousObject -- global variable for previous active object (if there was one)
runservice.RenderStepped:Connect(function()
local object = distancecheck()
if previousObject and previousObject ~= object then -- disable previous object if a new object is found. Outside of `if object` incase no object is returned.
previousObject.Keybind.Enabled = false
end
if object then
object.Keybind.Enabled = true
end
previousObject = object -- update previous object. nil if no object is found.
end)
1 Like
Thank you, it helped me a lot