EDIT: using GetPartBoundsInRadius, how would i get the closest object to me instead of an array of objects

There are multiple parts in my game called “HookPoint”, i want to be able to get the one that is closest to me using WorldRoot (if it really is impossible or overly complicated, i am willing to change from WorldRoot to something else) but with how it is currently working i am getting returned either an array with one HookPoint on the inside, or an array that has both HookPoints in it, i want just one and for it to be as an Instance, not an Array.

I tried using WorldRoot to find my objects because i already tried looking for a way to make this work after seeing a lot of complicated looking alternatives in this post

This is what my code looks like;

local UserInputService = game:GetService("UserInputService")
local TS = game:GetService("TweenService")
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local root = character:WaitForChild("HumanoidRootPart")
local camera = game.Workspace.CurrentCamera
local fovval = camera.FieldOfView
--local animation = script:WaitForChild("Animation")
--local animtrack = humanoid:LoadAnimation(animation)
local alive = true
local parts = workspace.HookPoints
local playerpos = root.Position
local OverPara = OverlapParams.new()

OverPara.FilterType = Enum.RaycastFilterType.Include
OverPara.FilterDescendantsInstances = {workspace.HookPoints}

local close = workspace:GetPartBoundsInRadius(root.Position, 100, OverPara)


UserInputService.InputBegan:Connect(function(input, gameProcessed)
	
	if input.KeyCode == Enum.KeyCode.Space and humanoid.FloorMaterial == Enum.Material.Air then
		local char = player.Character or player.CharacterAdded:Wait() -- Get the player character
		local Rope = Instance.new("RopeConstraint")
		Rope.Parent = close		
		local At1 = Instance.new("Attachment")
		local At2 = Instance.new("Attachment")

		At1.Parent = close
		At2.Parent = char.LeftHand

		At1.Name = "Attachment0"
		At2.Name = "Attachment1"

		Rope.Attachment0 = At1
		Rope.Attachment1 = At2

		Rope.Length = 10
		Rope.Visible = true
	end
end)

If anyone can tell me how i can get an instance instead of an Array, that would be a massive help

You are only getting the “close” parts one time at the start of the script. You need to get the nearby parts again every time you want to use it.

change the bottom half of your code to this:

local function close()
	return workspace:GetPartBoundsInRadius(root.Position, 100, OverPara)
end


UserInputService.InputBegan:Connect(function(input, gameProcessed)
	
	if input.KeyCode == Enum.KeyCode.Space and humanoid.FloorMaterial == Enum.Material.Air then
		print(close())
	end
end)

thank you, also i reformatted the post because it actually did work, or so i though, thanks for telling me it was only running once (oopsy, lol)

also, with my new code would i just smack “close()” right at the start of the keypress check, or would that be bad to do and if so, what would i do instead?

I would break it down into functions like this

local swinging = false
local currentRope

local function getNearestPart()
	local nearbyParts = workspace:GetPartBoundsInRadius(root.Position, 100, OverPara)
	for _, part in nearbyParts do
		local distance = (part.Position - root.Position).Magnitude
		if distance < shortestDistance then
			shortestDistance, nearestPart = distance, part
		end
	end
    
	return nearestPart
end

local function breakRope()
	--break the rope
	currentRope:Destroy()
	swinging = false
end
local function connectRope(nearbyPart)
	local char = player.Character
	if not char then
		return
	end

	swinging = true
	local Rope = Instance.new("RopeConstraint")
	Rope.Parent = nearbyPart		
	local At1 = Instance.new("Attachment")
	local At2 = Instance.new("Attachment")

	At1.Parent = close
	At2.Parent = char.LeftHand

	At1.Name = "Attachment0"
	At2.Name = "Attachment1"

	Rope.Attachment0 = At1
	Rope.Attachment1 = At2

	Rope.Length = 10
	Rope.Visible = true

	currentRope = Rope
end

local function canSwing()
	return humanoid.FloorMaterial == Enum.Material.Air and not swinging
end


UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if input.KeyCode == Enum.KeyCode.Space and canSwing() then
		local nearbyPart = getNearestPart()
		if nearbyPart then
			connectRope(nearbyPart)
		end
	end
end)

UserInputService.InputEnded:Connect(function(input, gameProcessed)
	if input.KeyCode == Enum.KeyCode.Space and swinging then
		breakRope()
	end
end)
1 Like

is this example code or should i 100% use this? both shortestDistance and nearestPart are underlined in red

image_2024-06-18_211601578

VERY IMPORTANT detail i feel i may have omitted, HookPoints are Unions of multiple parts with one attachment point for the rope, im not sure if that makes a difference, but i feel that if it does you probably should know (though i will probably remove the attachment point as we are making new ones within the code anyway)

image_2024-06-18_213125811

Sharing my new code;

local UserInputService = game:GetService("UserInputService")
local TS = game:GetService("TweenService")
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local root = character:WaitForChild("HumanoidRootPart")
local rarm = character:WaitForChild("Right Arm")
local rhand = rarm.RightGripAttachment
local camera = game.Workspace.CurrentCamera
local fovval = camera.FieldOfView
--local animation = script:WaitForChild("Animation")
--local animtrack = humanoid:LoadAnimation(animation)
local alive = true
local parts = workspace.HookPoints
local playerpos = root.Position
local OverPara = OverlapParams.new()

OverPara.FilterType = Enum.RaycastFilterType.Include
OverPara.FilterDescendantsInstances = {workspace.HookPoints}


local swinging = false
local currentRope

local function getNearestPart()
	local shortestDistance = math.huge  -- Initialize with a very large number
	local nearestPart = nil  -- Initialize as nil
	local nearbyParts = workspace:GetPartBoundsInRadius(root.Position, 100, OverPara)
	for _, part in nearbyParts do
		local distance = (part.Position - root.Position).Magnitude
		if distance < shortestDistance then
			shortestDistance, nearestPart = distance, part
		end
	end
	return nearestPart  -- Optionally return the nearest part
end

local function breakRope()
	--break the rope
	currentRope:Destroy()
	swinging = false
end
local function connectRope(nearbyPart)
	local char = player.Character
	if not char then
		return
	end

	swinging = true
	local Rope = Instance.new("RopeConstraint")
	Rope.Parent = rarm		
	local At1 = rhand
	local At2 = Instance.new("Attachment")

	At1.Parent = rarm
	At2.Parent = getNearestPart()

	At1.Name = "Attachment0"
	At2.Name = "Attachment1"

	Rope.Attachment0 = At1
	Rope.Attachment1 = At2

	Rope.Length = 10
	Rope.Visible = true

	currentRope = Rope
end

local function canSwing()
	return humanoid.FloorMaterial == Enum.Material.Air and not swinging
end


UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if input.KeyCode == Enum.KeyCode.Space and canSwing() then
		local nearbyPart = getNearestPart()
		if nearbyPart then
			connectRope(nearbyPart)
		end
	end
end)

UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if input.KeyCode == Enum.KeyCode.Space and swinging then
		breakRope()
	end
end)

I did actually get it to work on my own, but instead of swinging the player just floats where they began to swing using the rope, almost like the rope is anchored in place, i have no idea how to fix this so any help would be great