I am trying to make a pickup system in my game (When player is in range of tool billboard will be visible), But I’m not sure if this is the best way to accomplish this goal / take up as less memory as possible.
local handle = workspace:WaitForChild("Handle")
local player = game.Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local humroot = char:WaitForChild("HumanoidRootPart")
local humanoid = char:WaitForChild("Humanoid")
local uis = game:GetService("UserInputService")
local remote = game.ReplicatedStorage:WaitForChild("Remote")
local runservice = game:GetService("RunService")
local Billboard = game.Workspace:WaitForChild("BillboardPart").BillboardGui
while wait() do
if (humroot.Position - handle.Position).Magnitude > 10 then
Billboard.Enabled = false
repeat wait() until (humroot.Position - handle.Position).Magnitude <= 10
elseif (humroot.Position - handle.Position).Magnitude < 10 then
Billboard.Enabled = true
runservice.Heartbeat:Wait()
end
end
I can’t personally think of a way to do this other than magnitude. It’s just one mathematical operation being handled on the client, so memory usage shouldn’t be too insane. Might I ask why you dont just do
runservice.Heartbeat:connect(function()
if (humroot.Position - handle.Position).Magnitude > 10 then
Billboard.Enabled = false
elseif (humroot.Position - handle.Position).Magnitude < 10 then
Billboard.Enabled = true
end
end)
local char = game.Players.LocalPlayer
local distToShow = 5
local handle = workspace:WaitForChild("Handle")
local Billboard = game.Workspace:WaitForChild("BillboardPart").BillboardGui
game:GetService('RunService').Stepped:Connect(function() -- so it can run everyframe
local hrp = char:FindFirstChild('HumanoidRootPart')
if (hrp.Position - handle.Position).Magnitude <= distToShow then
Billboard.Enabled = true
-- Also checking if player pressed E
else
Billboard.Enabled = false
end
end)
You shouldn’t use runservice for this, there is an option on BillboardGui called MaxDistance (BillboardGui | Documentation - Roblox Creator Hub). This does exactly what you want. What you need to do is just check with userinput service, when they press e, and then which Billboard is the closest and if they are in the minimal range for activating it. If you don’t understand feel free to ask more questions
local UIS = game:GetService("UserInputService")
local player = game.Players.LocalPlayer
local UiFolder = --put in this folder from the workspace all the part using a interactive Ui billboard
local Character = player.Character
local debounce = false
local MaxDistFromUi = 50
UIS.InputBegan:Connect(function(input,chat)
if input.KeyCode == Enum.KeyCode.E and not chat and not debounce then
debounce = true
local Distance = MaxDistFromUi + 1
local UiClose = nil
for _, Part in pairs (UiFolder:GetChildren()) do
if (Part.Position - Character.HumanoidRootPart.Position).Magnitude < Distance then
UiClose = Part
Distance = (Part.Position - Character.HumanoidRootPart.Position).Magnitude
end
end
if UiClose then
--do stuff here
end
debounce = false
end
end)
Well sincerely I would use .magnitude to determine if the player is near to the item that is pickup-able then like a Imagelabel or Textlabel would appear with like “E to interact” and add all the pickup-able items in a module script in a table for easier use.
So to use a billboardgui, you need to parent it to a part right ? UiFolder is a folder parented to the workspace containing all those parts that can be pickable, so it’s easier to track them.
We need to reset the distance everytime we press e, that’s why we are setting a new variable distance every time. I’m adding 1 in the case of an item being exactly 50 studs from you, if i didn’t add 1 there and because i’m not doing this
It’d not accept the part and say it’s too far, you don’t really need to do +1 but i just do it for part if they are on the exact limit set by MaxDistFromUi