Keybind Interaction for my game

Hey there, wondering if someone could help me out here…

So I am attempting to create a keybind system, by that I mean when someone is within 5 studs of a part that is recognized as a part that can be interacted with, a BillboardGui will Adornee to that part. I have a somewhat working system, however it breaks upon use of more than one part within a close proximity. By this I mean that two parts are close together, and both within the distance of each other, I want to choose the closest part to the character.

The BillboardGui Adornee’s itself to the correct part, however you need to be within distance of the previous part for the BillboardGui to become visible, not too sure how to explain here is a GIF to show GIF

If someone could leave some tips, advice or solutions that’d be much appreciated! I know it’s something popular that ‘everyone’ wants to be able to do, I just can’t get over the last hurdle. I will also attach my ROBLOX game so you can download to see all scripts. Roblox Keybind Interaction.rbxl (28.8 KB)

Thanks!

2 Likes

Just me trying to understand what you mean by this. So you are trying to get it to only show up when you’re a certain distance from the last part?

1 Like

This might help you.

1 Like

I’ve had similar issues with things like this before, and I found it work by looping through all the billboard guis and doing a simple distance check which stores the one of least distance.
Unfortunately I’m not on my pc at the moment so I can’t look at your code to suggest a more specific fix, but I’ll give it a look when I get home.

Best of luck.

1 Like

I found the issue, just one character in the code needs to be changed! We all make mistakes, but anyways here’s the fix:

Inside your KeybindInteraction script (located in StarterPlayer > StarterPlayerScripts) you have used the wrong variable on line 60, where distance1 should be changed to distance2 since you are wanting to check the distance of the currently active part rather than the part you are iterating through.

Here is the fully fixed script if you just want to copy and paste, but i suggest you take a look at the issue to make sense out of it and see where you went wrong (good learning practice).

--[[
  KeybindInteraction
  JamieWallace_RBLX
]]

-- < Services > -- 
local RS = game:GetService("ReplicatedStorage")
local UIS = game:GetService("UserInputService")
local RunService = game:GetService("RunService")

-- < RemoteEvents > --
local events = RS.Events
local interactionEvent = events.InteractionEvent

-- < Constants > -- 
local player = game.Players.LocalPlayer
local interactionValue = player:WaitForChild("InteractionValue")
local playerGui = player:WaitForChild("PlayerGui")
local keybindBillboardGui = playerGui:WaitForChild("KeybindBillboardGui")
local character = player.Character or player.CharacterAdded:Wait()
local interactionParts = workspace:WaitForChild("Interaction Parts")
local universalDistance = 5

-- < Variables > --
local currentInt    eraction = nil

-- < AssignGui > -- 
function assignGui(part)	
	local textForGui 
	local objective, key = part:FindFirstChild("Objective"), part:FindFirstChild("Key")
	textForGui = "Press "..key.Value.." to "..objective.Value
	keybindBillboardGui.KeybindTextLabel.Text = textForGui
	keybindBillboardGui.Adornee = part
	keybindBillboardGui.Enabled = true	
	currentInteraction = part	
end

-- < UnAssignGui > --
function unassignGui()
	keybindBillboardGui.Enabled = false
	keybindBillboardGui.Adornee = nil
	currentInteraction = nil
end

-- < CheckDistance > --
function checkDistance(part)	
	if currentInteraction == nil then
		if player:DistanceFromCharacter(part.Position) <= universalDistance then
			return true, part
		elseif player:DistanceFromCharacter(part.Position) > universalDistance then
			unassignGui()
		end
	elseif currentInteraction then
		local distance1, distance2 
		distance1 = player:DistanceFromCharacter(part.Position)
		distance2 = player:DistanceFromCharacter(currentInteraction.Position)
		if distance1 < distance2 and distance1 <= universalDistance then
			return true, part
		elseif distance2 > universalDistance then --here is the issue, distance1 was replaced with distance2
			unassignGui()
		end
	end
end

-- < Initiate Check > --
function initiateCheck()	
	if interactionValue.Value == true then unassignGui() return end
	for _,part in pairs(interactionParts:GetChildren()) do
		local value, part = checkDistance(part)
		if value then 
			assignGui(part)
		end
	end	
end

-- < Heartbeat > --
RunService.Heartbeat:Connect(initiateCheck)

-- < Input Began > --
deBounce = false
UIS.InputBegan:Connect(function(input, isTyping)	
	if isTyping or (not currentInteraction) then return end	
	if deBounce == false then
		deBounce = true
		local key = currentInteraction.Key.Value
		if input.KeyCode == Enum.KeyCode[key] then
			interactionEvent:FireServer(currentInteraction)
		end	
		wait(.25)
		deBounce = false
	end
end)
2 Likes

Aha… that was slightly embarrassing on my half, thanks for your support!

1 Like

All good, I can’t even count how many times I’ve made a mistake like that!

1 Like