Good way to accomplish pickup scripts?

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.

An example of what I am trying to accomplish:
https://gyazo.com/eb303e8135a4abf0594efd711f67205a

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
1 Like

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)

Oh, didn’t think about using RunService. Thank you!

1 Like

I would do something like

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)

UserInputService on RunService Events doesn’t seem to work for me. Got any ideas?

Maybe use the mouse KeyDown event. Even though it is deprecated it still works sometimes :thinking:

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 :slight_smile:

1 Like

So it’d be somthing like this

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.

What is UiClose, and why do you do +1 for Distance?

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

(Part.Position - Character.HumanoidRootPart.Position).Magnitude =< Distance

But this

(Part.Position - Character.HumanoidRootPart.Position).Magnitude < Distance

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 :slight_smile:

Everything clear ?

1 Like

I cannot thank you enough! :slight_smile::slight_smile:

1 Like