Need help with part position script

Hey so i have this script here that is supposed to make the “item” go to a position like next to another so like imagine a grid and it goes to the first slot possible, if a slot is taken it will just go to the first possible slot

the “item” does not go to the slot, every item just stays ontop of eachother and are not changing position

here is the script

local Items = {
	{},
	{},
	{},
	{},
	{},
}

local thing = false

while task.wait() do
	if script.Parent:FindFirstChild("Items") then

		for index, v in pairs(script.Parent.Items:GetChildren()) do
			if v.Name == "Item" and v:FindFirstChild("_Item") and v:FindFirstChild("Item") then

				thing = false 

				for i = 1, 9 do
					for j = 1, 5 do
						
						local OtherItem = Items[j][i-1]
						
						if not (OtherItem and OtherItem.Parent) and thing == false then
							v.Item.Position = Vector3.new((script.Parent.Position.X + 13.8) + (i * 4.6),(script.Parent.Position.Y + 2.05),(script.Parent.Position.Z + 9.2) + (j-1) * 4.6)
							Items[j][i] = v.Item
							thing = true
						end
					end
				end
			end
		end
	end
end

think of a UIGridLayout but for parts, if that makes sense

1 Like

Can you store a table that represents the two-dimensional grid, use the index as the position, and check its contents to see if it’s taken? You could repeat a loop to attempt all its neighbors ([x-1][y-1] to [x+1][x+1]) until it finds an open spot. Just have a way ready to break out of the loop if there’s no possible spots.

I have a snippet of code that sounds similar, it was for a personal project regarding filling a grid of GUI elements, but allowed travelling out of bounds, like (3,3) → (3,1). Let me know if seeing that might help.

well im pretty sure thats what Items do, theres 5 tables inside for 5 rows and 9 columns but i could try
could you show me that i think it could help

Yeah your structure is similar but from your code it seems you’re iterating every cell. Maybe I misunderstood though. Is the issue finding the nearest-point the item can go, or just anywhere not taken?

imagine a 9x5 grid, 9 horizontal, 5 vertical

imagine theres a slot taken at the 1st position, 2nd position and 4th position,

i would want the item to go to the third position aka the first possible slot

Ah! I mistook the objective, sorry about that. I’m not too sure of the application and how the Items heirarchy is laid out, but here’s my attempt at the problem, in testing what I could replicate it’s close to your goal and positions the parts properly apart from each other:

local Items = {
	{},
	{},
	{},
	{},
	{},
}


local function findEmptyCell(item)
	for i = 1, 9 do
		for j = 1, 5 do
			if Items[i][j]== item then
				Items[i][j] = nil -- In the event an items re-assigned, set it to nil so it doesn't double-book cells
			end
			if not Items[i][j] then--same as saying "if empty.."
				Items[i][j] = item--assign item into that cell
				return Vector3.new(i*4.6, 0, (j-1) * 4.6)--return offset vector
			end
		end
	end
	
	return Vector3.new(0,0,0)--default if not found
end

while task.wait() do
	if script.Parent:FindFirstChild("Items") then
		for k,v in pairs(script.Parent.Items:GetChildren()) do
			if v:FindFirstChild("Item") then
				local pos = findEmptyCell(v)--findEmptyCell will book a cell for the item and return the offset vector
				v.Item.Position = script.Parent.Position + pos--add offset to parent pos
				print(string.format("Moved %s to %s.", v.Name, tostring(pos)))
			end
		end
	end
end

Heya it works but would you know how to make it so once an item is deleted, all of the items stay there until another item is created? because right now once an item is deleted, everything moves and it gets kind of confusing, i tried adding a debounce, kind of works but kind of does not

Sure! I would change it from a while loop to event triggers. You can use Instance.ChildAdded() and Instance.ChildRemoved() on script.Parent.Items, so it can separately handle removing the item from the grid without iterating the rest when a child is removed and operate normally when a child is added.

How have I not thought of that… Thank you very much!

1 Like

quick question, would this “delete” the item from the Items table?

local function RemoveCell(item)
	for j = 1, 5 do
		for i = 1, 9 do
			Items[j][i] = nil
		end
	end
end

for like when deleting an item so it does not stay in the table forever cause right now what happens is:

it works, when an item is deleted the next item just goes to the first slot, not first possible slot, it goes to the first slot then just restarts and theres multiple items in a slot

That loop will reset the whole table as you’re assigning nil to every cell. If you needed to find “item” in Items it would look like:

	for i = 1, 9 do
		for j = 1, 5 do
			if Items[i][j] == item then
				Items[i][j] = nil
			end
		end
	end

If you wanted to delete only the first occurrence of Item you could have a bool “found” and break out of the loop using it.