Hello, I have a script that is supposed to clone items from storage and spawn them on points that are taken from a table. It works like this: The script takes a folder of spawn points in workspace and adds them each to a table. Then it uses a loop to take each item in another folder full of tools in storage and moves them onto the spawn points. It then removes the point from the table so each spawn point is used only once. Here’s the code:
spawnPlates = game.Workspace.ToolSpawns --folder of the spawn objects that the tools spawn on
tools = game.ServerStorage.Tools --folder of the tools in storage
toolSpawns = {}
for i, v in pairs(spawnPlates:GetChildren()) do
toolSpawns[i] = v
end
for i, t in pairs(tools:GetChildren()) do
local newTool = t:Clone()
newTool.Parent = game.Workspace
newTool:MoveTo(toolSpawns[i].Position) --i used moveto so I don't have to deal with rotation issues
table.remove(toolSpawns, i) --i did this so hopefully each spawn point was only used once
end
It works, but only half way. Here’s what it looks like before and after I run it. Also, I just realized typing this out that it doesn’t randomize it like I want it to. How could I randomize it as well?
It doesn’t make sense because it says “attempt to index nil with ‘Position’” even though it works. I believe this error is thrown halfway through which causes it to only spawn half the items.
According to this, you are looping through all the items. Consequently, I believe your tables are having a mismatch in it’s index value.
So can I ask you to debug further, try printing what is exactly being returned by these functions?
spawnPlates:GetChildren()
tools:GetChildren()
I believe you have more tools than spawn plates. Consequently, if this is the case it is possible to index a nil variable in the second loop like:
local toolSpawns ={1,2}
local tools = {1,2,3,4}
Yeah it might be possible to index tool number 3 within the third index for toolSpawns. Also I don’t think using this is necessary since :GetChildren() already returns an array/table so you shouldn’t need to for loop what it returns.
The issue arises from running table.remove() while the loop is still running. Because that function automatically slides everything down to fill in the gap, some items get skipped.
@JigglyWiggles, are you always spawning in all items? If so, you do not need to remove elements from the table and can just let it get garbage-collected.
Instead of looping through the tools, try looping through all spawn plates. I haven’t tested the code so it might not work. If that’s the case, please tell me.
local spawnPlates = game.Workspace.ToolSpawns
local tools = game.ServerStorage.Tools
local toolSpawns = {}
for _, spawnPlate in pairs(spawnPlates:GetChildren()) do
table.insert(toolSpawns, spawnPlate)
end
for i, spawnPlate in pairs(toolSpawns)
local tool = tools[i]
tool.Parent = game.Workspace
tool:MoveTo(spawnPlate.Position)
end
The goal is to spawn these items in once per round. I did the remove to hopefully stop it from doubling up but I see why it wouldn’t help. Thank you for your response.
local spawnPlates = game.Workspace.ToolSpawns
local tools = game.ServerStorage.Tools
local toolSpawns = {}
for _, spawnPlate in pairs(spawnPlates:GetChildren()) do
table.insert(toolSpawns, spawnPlate)
end
local prevTool
for i, spawnPlate in pairs(toolSpawns) do
local tool
repeat tool = tools[math.random(1, #tools)] until tool ~= prevTool
tool.Parent = game.Workspace
tool:MoveTo(spawnPlate.Position)
prevTool = tool
end
Your first reply definitely worked after adding “do” in the for loop and :GetChildren for the tools variable. Thank you very much! This section still works, but isn’t filling every spawn plate. So each run it is missing a few items, but different than last run so the randomization does work fortunately. I think I may be able to figure it out from here but if you have any ideas I’ll definitely listen, haha. Thank you very much.
Alright, so, this will spawn each item exactly once. E.g. it will spawn 4 coal models, etc.
local spawnPlates = game.Workspace.ToolSpawns
local tools = game.ServerStorage.Tools:GetChildren()
local toolSpawns = {}
for _, spawnPlate in pairs(spawnPlates:GetChildren()) do
table.insert(toolSpawns, spawnPlate)
end
local prevTools = {}
for _, spawnPlate in pairs(toolSpawns) do
local tool
repeat tool = tools[math.random(1, #tools)] until tool and not prevTools[tool]
local clonedTool = tool:Clone()
clonedTool.Parent = game.Workspace
clonedTool:MoveTo(spawnPlate.Position)
table.insert(prevTools, tool)
end
Thank you so much! I have been trying here as well. I did try to use a table as well but couldn’t figure out how to add the object and I also somehow did something to crash studio, lol. Thanks again, I appreciate everything.
Hey, I hate to bug and bring that back up. I noticed that the script would spawn more than one type of item, for example, 5 coal instead of four and then as a result spawns one less of another item. I spent a lot of time trying to fix it to avoid having to ask again but it’s got me beat. Do you have any ideas?
Hey, I figured it out. I want to tell you just in case you could benefit from it, the least I can do for all your help. So what I ended up doing was first getting it to work properly without the randomization, which you helped me with. So it spawned the proper amount of objects perfectly, just in a predictable pattern. Then I decided instead of choosing a random item from a table, I just randomized the table instead. I had an old shuffle algorithm I used in a project awhile back in Java, and luckily enough it transferred pretty easily into Lua. Here’s the code in case you’re interested:
local spawnPlates = game.Workspace.ToolSpawns
local tools = game.ServerStorage.Tools:GetChildren()
local toolSpawns = {}
local toolsA = {}
for i, v in pairs(tools) do
toolsA[i] = v
end
for i = 1, #tools, 1 do
local index = math.random(1, #tools)
local x = toolsA[i]
toolsA[i] = toolsA[index]
toolsA[index] = x
print(x, index, i)
end
for _, spawnPlate in pairs(spawnPlates:GetChildren()) do
table.insert(toolSpawns, spawnPlate)
end
for i, spawnPlate in pairs(toolSpawns) do
local tool = toolsA[i]
tool.Parent = game.Workspace
tool:MoveTo(spawnPlate.Position)
end