Trying to spawn one part per location (its spawning 2+)

currently im making a puzzle script and trying to distribute 11 keys through about 50 possible spawn locations using math.random. i tried to store the keys in a table and the spawn locations in another table then distribute them like that but i couldnt get it to work.

what i did is defined each 11 keys seperately, then stored the locations in a table and spawned them which works how i want, except that one of the locations will spawn 2+ keys and then the player cant pick them up.

is there a way to stop this from happening? each key is important (think of it like colored keys) and is used to open a door but i dont want them to double up (like red key and yellow key together) any ideas are appreciated!

here is how i store the locations, and how i spawn the keys. its not too effectient but it works lol
code:

local Locations = workspace.Lvl5NoteLocations
local Notes = ServerStorage.Lvl5Puzzle

local tbl = {}

for _,part in pairs(Locations:GetChildren()) do
table.insert(tbl, part.CFrame)
end

local Note1 = workspace:FindFirstChild(ā€œIā€)
local Note1Spawned = false

if not Note1 then
local Note1Clone = I:Clone()
Note1Spawned = true
Note1Clone.CFrame = tbl[math.random(#tbl)]
Note1Clone.Parent = workspace
end

1 Like

Have you tried removing the location from the table after you use it using table.remove(tbl, index)? Your script only shows spawning one ā€˜Noteā€™ so itā€™s hard to see what the problem might be.

1 Like
local LocationsTable = {}; -- Table of "Locations"

for _,Part in pairs(Locations:GetChildren()) do
    table.insert(LocationsTable, Part.CFrame); -- Same as your script
end

for _,Key in pairs(<INSERT KEYS PATH>:GetChildren()) do -- Iterate through all of your "Keys"
    local LocationIndex = math.random(1, #LocationsTable); -- Find a random "Location"

    local newKey = Key:Clone() -- Create the new "Key"
    newKey.CFrame = LocationsTable[LocationIndex];
    newKey.Parent = workspace;

    table.remove(LocationsTable, LocationIndex); -- Remove the Location from your table so it cannot be re-used
end

Iā€™ve used <INSERT KEYS PATH>:GetChildren() assuming you have all of your keys as a child of a specific folder/model that you can iterate through, but it would be just as easy to replace this with a table of keys like you said youā€™d already tried earlier.

i have not, though this is a really good idea!! im going to try it right now and see what happens.

I ran through each key as ā€œif not note thenā€ etcā€¦ to spawn one of every kind i needed, i just didnt post them all because its all the same lol

removing the index from the table worked!! thank you i appreciate your help :slight_smile:

1 Like

Glad to hear itā€™s working! Just for the benefit of yourself or anyone else who stumbles across this Iā€™ll give a brief explanation:

Every time you iterate youā€™re using math.random on the table length. As the table length isnā€™t changing you have the possibility of repeating the same randomly generated number. In that circumstance it will index the same location that youā€™ve already used and cause two keys to spawn on the same position.

Example:

local Table = {'one', 'two', 'three', 'four'}; -- Table has a length of 4 (as there is 4 values inside it)

local x = math.random(1, #Table); ---> Random number between 1 and 4, lets assume it picks 2
print(Table[x]) ---> "two"

local y = math.random(1, #Table); ---> Random number between 1 and 4, lets assume it picks 2 again
print(Table[y]) ---> "two"

If you remove the value from the table after every use:

local Table = {'one', 'two', 'three', 'four'}; -- Table has a length of 4 (as there is 4 values inside it)

local x = math.random(1, #Table); ---> Random number between 1 and 4, lets assume it picks 2
print(Table[x]) ---> "two"
table.remove(Table, x); -- Removes the 2nd value from the table

-- Table now looks like this:
local Table = {"one", "three", "four"};

local y = math.random(1, #Table); ---> Random number between 1 and 4, lets assume it picks 2 again
print(Table[y]) ---> "three" as the 2nd index of 'Table' is now "three"
1 Like

other alternatives:

shuffle the whole table, and then for loop it

local rand = Random.new()
rand:Shuffle(table)
for _, locator in table do
  spawnAt(locator)
end

you can also maintain a logical ā€œused portionā€:

local usedCount = 0
for i = 1, #table do
  local last = #table - usedCount
  local index = math.random(1, last)
  spawnAt(table[index])
  table[index], table[last] = table[last], table[index] --swap to place it into used portion
  usedCount += 1
end
1 Like

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