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
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.
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?
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.
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