Assigning value to a 3d array making all previous values in 3d array nil

Whenever I try to set a value in my 3d array to a value in another 3d array it sets all previously set values in the array to nil.
Code:

local function cullNoise(map)
	local culledMap = {}
	
	for x, a in ipairs(map) do
		if culledMap[x] == nil then culledMap[x] = {} end
		
		for y, b in ipairs(a) do
			if culledMap[x][y] == nil then culledMap[x][y] = {} end
			
			for z, c in ipairs(b) do
				if checkNeighbors(x, y, z, map) == false then
					print(map[x][y][z]) --print the value from the array I want the value from
					culledMap[x][y][z] = map[x][y][z] --Setting the value of the new array to the value from the old array (Problem line)
					print(culledMap[x][y][z]) --print the new value that was set
					if z - 1 > 0 then print(culledMap[x][y][z-1]) end --print the value set before it
				end
			end
		end
	end

	return culledMap
end

This is what the output shows: (cM = culledMap) (z-1 is the previous value set)
Screenshot 2023-10-28 114801 (1)

If it was confusing, my code sets culledMap[x][y][z] (which looks like
{ (x) { (y) { (z is index of valueX) value1, value2, … }, … }, … }, ) to another array that is set up in the same way, but the previous value apparently gets overridden and set to nil (value1 is set to a value properly, but when value2 is set value1 becomes nil, along with all previous values)

Thank you!

You probably aren’t overwriting it, you are accessing that location before it is created.

1 Like

I don’t have a solution but I think it could be helpful to add one more print in the if statement and post the new output.

if checkNeighbors(x, y, z, map) == false then
	print(string.format("x, y, z: %i, %i, %i", x, y, z))
	print(map[x][y][z]) --print the value from the array I want the value from
	culledMap[x][y][z] = map[x][y][z] --Setting the value of the new array to the value from the old array (Problem line)
	print(culledMap[x][y][z]) --print the new value that was set
	if z - 1 > 0 then print(culledMap[x][y][z-1]) end --print the value set before it
end

What I think could be the problem is that checkneighbors() has returned true for the earlier z indices. However, from the output in the original post, I can’t tell whether this is the case.

1 Like

I think I found the problem.
For some reason, when culledMap is called outside of the for loops it is blank (as in there are no values in the last arrays), but when it is inside the loops it returns fine (after improving the code at least)
image (3)


Do you have any idea why it is doing this? (Thank you for the output suggestion btw)

In the first screenshot, you are showing the arrays at the second x index, but in the second screenshot, you are showing the arrays at the first x index.

Could you show the printed arrays at the first x index both inside and outside the loop and the printed arrays at the second x index both inside and outside the loop. For the arrays at the second x index inside the loop, show a print that’s from an iteration in which x is greater than 2.

If the arrays at the first x index after the loop are empty, I’m pretty sure they are also empty inside the loop.

Also, I still think it would be useful to show a sequence of the prints in my earlier reply (your original prints and the one I added). Those prints could actually show whether previously set values were set to nil or whether values for the previous indices were never even set to a non-nil value.

1 Like

For the second screenshot the 1st x index is the same as all the rest and the first screenshot has a random assortment of values for all x indexes. What I was trying to point out was how the array printed inside the for loop was different from when it was printed outside the loop, despite using the same variable. (also what I mean by “completely empty array” in the code screenshot is that the values that should be in the z array arent there, but it is still structured as a 3d array, sorry for any confusion)

If, after the loop, the array is actually missing values that it had during the loop, the only reason I can think of is that checkNeighbors() somehow causes that. Could you show the checkneighbors() function?

Edit: I realized that since it has no reference to culledMap, it can’t modify it. However, I still think it’s the reason for earlier z indices having nil as their value in culledMap.

1 Like

Here is the checkNeighbors() code:

local function checkNeighbors(x, y, z, map)
	for xx = -1, 1, 1 do
		for yy = -1, 1, 1 do
			for zz = -1, 1, 1 do
				if xx == 0 and yy == 0 and zz == 0 then
					continue
				elseif x == 1 or y == 1 or z == 1 or x == MAPLEN_X or y == MAPLEN_Y or z == MAPLEN_Z then
					continue
				elseif math.abs(xx) + math.abs(yy) + math.abs(zz) > 1 then
					continue
				elseif not map[x][y][z] then
					continue
				elseif not map[x + xx][y + yy][z + zz] then
					return false
				end
			end
		end
	end
	wait()
	return true
end

(MAPLEN_X, Y, and Z all have the same value of 30)

The only solution I can think of right now is, in the for loops in cullNoise, to check if x is equal to the length of map, if y is equal to the length of a, and if z is equal to the length of b, then use return the map from inside the for loops.

I have no idea what could cause values to be erased from culledMap. But, in regards to the problem in the original post (values of earlier z indices nil), are you sure that the values at the earlier z indices are not nil or false and that they have a nil or false neighbor value (in which case checkNeighbors() returns false and the if statement condition in cullNoise is satisfied)?

Also, you could write checkNeighbors differently. I think the code below will work the exact same way and at least in my opinion it’s easier to understand what it does. Making this change won’t fix any problems, it’s just a suggestion. If your current code is more readable to you, perhaps keep it the way it is.

local function checkNeighbors(x, y, z, map)
	if x == 1 or y == 1 or z == 1 or x == MAPLEN_X or y == MAPLEN_Y or z == MAPLEN_Z then
		return true
	end
	if not map[x][y][z] then
		return true
	end
	for xx = -1, 1, 2 do
		if not map[x + xx][y][z] then
			return false
		end
	end
	for yy = -1, 1, 2 do
		if not map[x][y + yy][z] then
			return false
		end
	end
	for zz = -1, 1, 2 do
		if not map[x][y][z + zz] then
			return false
		end
	end
	wait()
	return true
end
1 Like

Your culledMap is a mixed table of array and dictionary parts, because any time checkNeighbors() returns true, you’re not populating a spot in the array for that value of z. You have to assign a non-nil value for every x,y, and z with no gaps, or part of your arrays will be moved into the dictionary section of the table, even if the keys are integers.

I’m wondering if it’s some quirk of how the tables are output in the Output window that you’re not seeing the dictionary parts or something.

I’d try simply adding an else clause where you set culledMap[x][y][z] = Vector3.zero or something like that, to see if array sparseness is part of the problem.

1 Like

Yea that worked the first time, thanks!

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