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.