Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Multidimensional array is saying "attempt to index field '?' (a nil value)"

I've tried to figure this out for a while now and just can't find the error. There is a comment above the line of code that triggers the error. Basically I'm trying to store the position data within a table (whenever the player clicks on certain parts) that can be quickly accessed for later use (I have no need to sort the data, and the data is only ever used for comparison purposes). Here are some code snippets that affect what I'm trying to do:

local player = game:GetService("Players").LocalPlayer
local equipped = false
local depressStopped = false
local part = ""
local mouse = player:GetMouse()
local distance = 0
local tool = script.Parent
local copy = ""
local copyPosition = ""
local copyPositionX = game.Workspace.Parttay.Position.X
local copyPositionY = game.Workspace.Parttay.Position.Y
local copyPositionZ = game.Workspace.Parttay.Position.Z
local masterTable = {

[copyPositionX] = {[copyPositionY] = {[copyPositionZ]={copyPositionZ}}}

}

--[[TABLE LAYOUT: with example data
	
masterTable		copyPositionX	copyPositionY	copyPositionZ		
				200				150				200			=200x150y200z
								100				200			=200x100y200z
				300				150				200			=300x150y200z
				400				100				150			=400x100y150z

*note: the only data that can be directly accessed is the copyPositionZ
--]]
tool.Equipped:connect(function()
	equipped = true
	while equipped do
		pcall(function()
			distance = (mouse.Target.Position - game.Workspace[player.Name].Head.Position).magnitude
			if mouse.Target:IsDescendantOf(game.Workspace.ConstantBlocks)  and distance < 20 then
				part = mouse.Target			
				position = part.Position
			--other code
			end
		end)
	end
end)

tool.Unequipped:Connect(function()
	equipped = false
end)
mouse.Button1Up:connect(function()
	depressStopped = true
end)

mouse.Button1Down:connect(function()
	while equipped == true and depressStopped == false do
		if part:IsDescendantOf(game.Workspace.ConstantBlocks) and distance < 20 then
			--part comes from the equipped function
			copyPositionX = part.Position.X
			copyPositionY = part.Position.Y
			copyPositionZ = part.Position.Z
			print(copyPositionX, copyPositionY, copyPositionZ)
			--THE FOLLOWING LINE CAUSES THE ERROR!
			masterTable[copyPositionX][copyPositionY][copyPositionZ] = copyPositionZ
		--other code
		end
	end
	depressStopped = false
end)

I'm still kinda new to this and would appreciate any pointers as well!

[EDIT]

I may just misunderstand how it works, but this code works just fine:

part = game.Workspace.Parttay
copyPositionX = part.Position.X
copyPositionY = part.Position.Y
copyPositionZ = 0
print(copyPositionX, copyPositionY, copyPositionZ)
local masterTable = {

[copyPositionX] = {[copyPositionY] = {[copyPositionZ] = {copyPositionZ}}}

}
masterTable[copyPositionX][copyPositionY][copyPositionZ] = copyPositionZ
print(masterTable[copyPositionX][copyPositionY][copyPositionZ])

3 comments

0

First of all you should get rid of those dots in empty lines

0

That's to show there is more code, but I can separate the code snippets if it makes it easier.

0

I wasn't sure if this was a simple error on my part or not, so I didn't have every variable declared in the snippets. I just added all of them, I really am stumped on this though.

2 answers

✓ Accepted answer

In Lua, you can't declare a multidimensional array and then have it work for all combination of values, you have to make a new table for every index. That is, on line 15, you declare your masterTable, but you only initialize the tables needed for one coordinate.

If you wanted a 10x10x10 array with integer values, you could do this:

local t = {}
for x = 1, 10 do
	t[x] = {}
	for y = 1, 10 do
		t[x][y] = {}
		for z = 1, 10 do
			t[x][y][z] = 0
		end
	end
end

However, if you're wanting to put in arbitrary coordinates (ie they involve decimals or arbitrarily large integers), you'll want to use a function that sets up the tables on an as-needed basis (since you can't possibly make enough tables to cover all possible decimals):

local masterTable = {}
function store(x, y, z, value)
	local tx = masterTable[x]
	if not tx then
		tx = {}
		masterTable[x] = tx
	end
	local ty = tx[y]
	if not ty then
		ty = {}
		tx[y] = ty
	end
	ty[z] = value
end
function get(x, y, z)
	return masterTable[x] and masterTable[x][y] and masterTable[x][y][z]
end
function delete(x, y, z) -- Delete the value stored at x,y,z and release memory if possible
	if get(x, y, z) == nil then return end
	local tx = masterTable[x]
	tx[y][z] = nil
	if not next(tx[y]) then
		tx[y] = nil
		if not next(tx) then
			masterTable[x] = nil
		end
	end
end
store(1, 2, 3, true)
print(get(1, 2, 3)) -- true
print(get(10, 10, 10)) -- nil, but doesn't error (unlike saying masterTable[10][10][10] here)
delete(1, 2, 3)
print(masterTable[1]) -- nil -- tables have been removed to save memory

I noticed you store a value identical to your 'z' coordinate - if there's nothing else being stored, that's redundant and you can remove the value (just store 'true' for example). The equivalent in a 1D table:

local t = {}
t[5] = 5 -- redundant
t[5] = {5} -- redundant and harder to access the '5' at the end -- this is what you appear to be doing
t[5] = true -- all you need

2 comments

0

This will take me a bit to digest, but I think you may have solved it. The reason I added stored the key as the data is I needed it to compare, but with your method I could just compare the value in t[5] to true (since only those coordinates will allow it)

0

Thank you for your time/answer

For your error, since you didn't list a line it occurred on I can't tell you what line it happens on, but you're attempting access a table[x][y] where [x] doesn't exist. This usually happens if you're assuming the array is going to be a 5x5 array so you try to access table[5][5] without first making table[1] through table[5] empty arrays first.

function initialize2d(x, y, default)
  local t = {}
  for i = 1, x do
    t[i] = {}
    for j = 1, y do
      t[i][j] = default
    end
  end
end

This discussion is preserved as it was. New answers, comments, and votes are closed.