Adding to an empty table makes a dictionary

I’m currently trying to make a VR grab system, but encountering a problem. I made a table that is automatically empty that will later contain the distances between a close grabbable object and the players hand. Whenever I add a distance number to the table, it assigns it a key, making it a dictionary. Just so I can grab the closest object, I unpack the table and use math.min to get the smallest distance, giving me which object is closest. But table.unpack only works with arrays, not dictionaries.

I’ve tried adding a key and that is the distance number and assigning its value to nil, but that just gives me a blank table.

local Grabbables					= script:FindFirstChild("Grabbables")

local maxDistance					= 1
	
local objectDistances				= {}	--> All objects that are grabbable and close to the hand that includes their distances
--local numDistances					= {}	--> All distances in a simply array for later reference

local objectToGrab					= nil
local handGrabbingWith				= nil

--> 1. Get all objects within radius of hand

local function checkHandRadius(hand)
	local PartsInRadius					= game.Workspace:GetPartBoundsInRadius(hand.Position, maxDistance)
	for _, v in pairs(PartsInRadius) do --> Checks for parts within hand radius
		local grabbable					= v:FindFirstChild("grabbable")

		if (grabbable) and grabbable:IsA("BoolValue") then --> Checks whether one of the objects is grabbable
			if v:FindFirstChild("grabbable").Value then
				local distance			= (v.Position - hand.Position).Magnitude --> Distance between the object and the hand

				if not Grabbables:FindFirstChild(v.Name) then --> Checks if the object doesn't exist yet in the table
					--> Temporary value for object

					local TempValue		= Instance.new("NumberValue")

					TempValue.Name		= v.Name
					TempValue.Value		= distance
					TempValue.Parent	= Grabbables
				else
					local TempValue		= Grabbables[v.Name]
					
					TempValue.Value		= distance
				end
			
				objectDistances[distance]		= nil	--> Adds object's distance to table

			end
		end
	end
	
	return
end

coroutine.wrap(function()
	while true do
		checkHandRadius(leftHand)
		checkHandRadius(rightHand)
		
		wait()
	end
end)()

Grabbables.ChildAdded:Connect(function()
	
	--> Get closest object
	
	print(table.unpack(objectDistances)) --> PRINTS BLANK

	local smallestDistance			= math.min( --> MISSING ARGUMENT #1 (NUMBER EXPECTED)
		table.unpack(objectDistances)
	)

	for object, distance in pairs(objectDistances) do
		if distance == smallestDistance then
			print("found closest object!")

			objectToGrab					= object
			
			--> Create highlight for the object
			
			local Highlight					= Instance.new("Highlight")
			
			Highlight.FillColor				= Color3.fromRGB(
				0,
				255,
				255
			)
			Highlight.FillTransparency		= 0
			Highlight.OutlineTransparency	= 1
			Highlight.Parent				= objectToGrab
		end
	end
end)

This is the area of the error I’m getting

Why are there so many white spaces? This is so hard to comprehend.

2 Likes

Sorry, it’s just my way of organization. I edited it to have less white spaces.

Bumping this up since I still haven’t found anything

Wasted my time also reformatting this and fixing performance issues. Hope this works.

local Grabbables = script:FindFirstChild("Grabbables")
local maxDistance = 1

local objectDistances = {}	--> All objects that are grabbable and close to the hand that includes their distances
--local numDistances = {}	--> All distances in a simply array for later reference

local objectToGrab = nil
local handGrabbingWith = nil

--> 1. Get all objects within radius of hand
local function checkHandRadius(hand)
	local PartsInRadius	= game.Workspace:GetPartBoundsInRadius(hand.Position, maxDistance)
	for _, v in pairs(PartsInRadius) do --> Checks for parts within hand radius
		local grabbable	= v:FindFirstChild("grabbable")

		if (grabbable) and grabbable:IsA("BoolValue") then --> Checks whether one of the objects is grabbable
			if v:FindFirstChild("grabbable").Value then
				local distance = (v.Position - hand.Position).Magnitude --> Distance between the object and the hand

				if not Grabbables:FindFirstChild(v.Name) then --> Checks if the object doesn't exist yet in the table
					--> Temporary value for object

					local TempValue	= Instance.new("NumberValue")
					TempValue.Name = v.Name
					TempValue.Value	= distance
					TempValue.Parent = Grabbables
				else
					local TempValue	= Grabbables[v.Name]
					TempValue.Value	= distance
				end
			
				objectDistances[distance] = grabbable	--> Adds object's distance to table

			end
		end
	end
	
	return
end

local handle --> Use :Disconnect() on this to stop checking hands (if necessary)
local checkTimer = 0
local checkDelay = 10 --> This checks both hands every 10 frames
handle = game:GetService("RunService").RenderStepped:Connect(function()
	if checkTimer < (checkDelay - 1) then checkTimer += 1
	else
		checkTimer = 0
		checkHandRadius(leftHand)
		checkHandRadius(rightHand)
	end
end)


Grabbables.ChildAdded:Connect(function()
	
	--> Get closest object
	local closestDistance = maxDistance
	for distance, grabbable in objectDistances do
		closestDistance = math.min(closestDistance,distance)
	end
	local closestObject = objectDistances(closestDistance)
	
	--> Create highlight for the object
	local Highlight	= Instance.new("Highlight")
	Highlight.FillColor	= Color3.fromRGB(0, 255, 255)
	Highlight.FillTransparency = 0
	Highlight.OutlineTransparency = 1
	Highlight.Parent = closestObject
end)

I modified the code and was able to get the highlight working, but now I have to remove the highlight when the object leaves the part’s radius. Also for some reason, TWO parts are highlight instead of one.

local Grabbables	= script:FindFirstChild("Grabbables")

local maxDistance = 2
	
local objectDistances = {}	--> All objects that are grabbable and close to the hand that includes their distances

local objectToGrab = nil
local handGrabbingWith = nil

--> 1. Get all objects within radius of hand

local function checkHandRadius(hand)
	local PartsInRadius	= game.Workspace:GetPartBoundsInBox(hand.CFrame, hand.Size * 2)

	for _, v in pairs(PartsInRadius) do --> Checks for parts within hand radius
		local grabbable = v:FindFirstChild("grabbable")

		if (grabbable) and grabbable:IsA("BoolValue") then --> Checks whether one of the objects is grabbable
			if v:FindFirstChild("grabbable").Value then
				local distance = (v.Position - hand.Position).Magnitude --> Distance between the object and the hand

				if not Grabbables:FindFirstChild(v.Name) then --> Checks if the object doesn't exist yet in the table
					--> Temporary value for object

					local TempValue = Instance.new("ObjectValue")

					TempValue.Name = v.Name
					TempValue.Value = v
					TempValue.Parent = Grabbable
				else
					local TempValue = Grabbables[v.Name]
					
					TempValue.Value = v
				end
				
				objectDistances[distance] = v	--> Adds object's distance to table
			end
		end
	end
	
	return
end

--> 2. Get object to grab + add and remove highlight

local handle --> Use :Disconnect() on this to stop checking hands (if necessary)

local checkTimer = 0
local checkDelay = 10

handle	= RunService.RenderStepped:Connect(function()
	if checkTimer < (checkDelay - 1) then checkTimer += 1
	else
		checkTimer = 0
		
		checkHandRadius(leftHand)
		checkHandRadius(rightHand)
	end
end)

Grabbables.ChildAdded:Connect(function(child)
	
	--> Get closest object
	
	local OGValue = script:FindFirstChild("ObjectToGrab") --> Object value for "ObjectToGrab" for use in value change

	local closestDistance = maxDistance
	
	local function getSmallestDistance()
		for distance, obj in pairs(objectDistances) do
			closestDistance = math.min(
				closestDistance,
				distance
			)

			if closestDistance ~= maxDistance then
				objectToGrab = obj
				OGValue.Value = objectToGrab
				
				print("ObjectToGrab:", objectToGrab)
			end
		end
	end
	
	getSmallestDistance()
	
	child:GetPropertyChangedSignal("Value"):Connect(getSmallestDistance)
	
	--> Set "objectToGrab"

	OGValue:GetPropertyChangedSignal("Value"):Connect(function()
		
		print("value changed!")
		
		if objectToGrab then
			print("Created highlight!")

			--> Create highlight for the object

			local Highlight = Instance.new("Highlight")

			Highlight.FillColor = Color3.fromRGB(
				0,
				255,
				255
			)
			Highlight.FillTransparency = 0
			Highlight.OutlineTransparency = 1
			Highlight.Parent = objectToGrab
		end
	end)
end)

Grabbables.ChildRemoved:Connect(function(child)
	if child:IsA("ObjectValue") then
		local Highlight = child.Value:FindFirstChild("Highlight")
		
		if Highlight then
			print('Removed highlight!')
			
			Highlight:Destroy()
		end
	end
end)

I was able to make a different system that could work. Thanks for the help!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.