What do you want to achieve?
I have a coin pile spawn script that uses CollectionService. It detects a CoinSpawn, chooses one random coin pile, and sets the coin pile’s position to the SpawnBox’s position. I have the coins in a folder under ReplicatedStorage, and the SpawnBoxes are put inside a room model. Both use their own tags for CollectionService to work.
What is the issue?
The coin pile is either a couple of studs above the SpawnBox, doesn’t spawn, spawns at its original position in the workspace, or spawns multiple coin piles at different locations.
I’ve tried asking ChatGPT for a solution, but nothing worked. I’m lost at this point.
-- Services
local CollectionService = game:GetService("CollectionService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Variables
local coinPiles = ReplicatedStorage.Objects["Coin Piles"].Coins:GetChildren()
local coinPileSpawnConns = {}
-- Set RNG
math.randomseed(os.time())
-- Functions
local function CoinPileSpawn(spawnBox: Part)
local coinPile = coinPiles[ math.random(#coinPiles) ]:Clone()
coinPile.Parent = workspace
coinPile.CFrame = spawnBox.CFrame
spawnBox:Destroy()
if coinPileSpawnConns[spawnBox] then
coinPileSpawnConns[spawnBox]:Disconnect()
coinPileSpawnConns[spawnBox] = nil
end
end
local function HandleExistingSpawns()
local boxes = CollectionService:GetTagged("coinPileSpawn")
if #boxes > 0 then
local pick = boxes[ math.random(#boxes) ]
CoinPileSpawn(pick)
end
end
-- Initial Load
HandleExistingSpawns()
-- Runtime
CollectionService:GetInstanceAddedSignal("coinPileSpawn"):Connect(function(spawnBox: Part)
coinPileSpawnConns[spawnBox] = spawnBox.Destroying:Connect(function()
if coinPileSpawnConns[spawnBox] then
coinPileSpawnConns[spawnBox]:Disconnect()
coinPileSpawnConns[spawnBox] = nil
end
end)
CoinPileSpawn(spawnBox)
end)
There is a part that is confusing. You use GetInstanceAddedSignal to connect the Destroy event to then disconnect it immediately when calling CoinPileSpawn?
Also, is there a second script that re-adds the SpawnBox? You destroy it when calling CoinPileSpawn but you should use GetInstanceAddedSignal destroy event to store the position and re-add the SpawnBox.
You may also have Streaming on. When streaming is enabled, some objects that are far away may spawn in as you move to reduce lag. I have a feeling GetInstanceAddedSignal is being triggered when you get in distance, causing multiple spawn boxes to load in. I am assuming you are just testing for just 1 spawning at the moment. Look at the properties in workspace and check if StreamingEnabled is on. I am not sure why the coin piles would be offset though.
Your code is at the moment saying:
“If a spawn box is streamed in or added in workspace: connect the destroy event, add the coins, disconnect the destroy event right after adding the coins.
If HandleExistingSpawns function is called: Pick only one of the spawn boxes and use CoinPileSpawn to create the coins.”
Sorry for the paragraphs, but I feel if I ask questions then we could fix this faster. Correct me on stuff, I am not at computer at moment but I think I could help a little. I here to help.
This is my first time using CollectionService, so I’m not quite sure how to use it. I did my best with the wiki and some YouTube videos. What would you recommend I do?
I am not at my computer right now but I could try typing it on phone:
local CollectionService = game:GetService("CollectionService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local function SpawnCoin(SpawnBox: BasePart)
local coinPile: Part = coinPiles[ math.random(#coinPiles) ]:Clone()
coinPile.Parent = workspace
coinPile.CFrame = SpawnBox.CFrame
SpawnBox:RemoveTag(“coinPileSpawn”)
coinPile.Destroying:Once(function()
SpawnBox:AddTag(“coinPileSpawn”)
end
end
CollectionService:GetInstanceAddedSignal(“coinPileSpawn”):Connect(SpawnCoin)
while task.wait(math.random(5)) do
local getSpawnBoxes = CollectionService:GetTagged(“coinPileSpawn”)
if 0 < #getSpawnBoxes then
SpawnCoin(getSpawnBoxes[ math.random(#getSpawnBoxes) ])
end
end
Instead of deleting the spawn box we instead remove the tag so the loop doesn’t add it again. Once the coin is destroyed the spawn box gets tagged again so another coin can spawn.
Let me know if there are errors and such, I tried :3
This script looks great, but I forgot to add some needed info. This script is for a game similar to Doors, so the coins won’t respawn. Also, spawnboxes will be added as more rooms load, and removed as the previous rooms despawn.
local CollectionService = game:GetService("CollectionService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local function SpawnCoin(SpawnBox: BasePart)
local coinPile: Part = coinPiles[ math.random(#coinPiles) ]:Clone()
coinPile.Parent = SpawnBox.Parent
coinPile.CFrame = SpawnBox.CFrame
SpawnBox:Destroy()
coinPile.Destroying:Once(function()
— remove event
end
end
CollectionService:GetInstanceAddedSignal(“coinPileSpawn”):Connect(SpawnCoin)
for _, SpawnBox in ipairs(CollectionService:GetTagged(“coinPileSpawn”)) do
SpawnCoin(SpawnBox)
end
The destroy event comment you can remove if you want.
Sorry for the delay, I haven’t been feeling well.
Nothing I’ve done seems to fix the issue. However, the issue only happened with spawnboxes on initial load. So I added a delay of 5 seconds to the initial environment load so that I could remove the initial load function. It works now. Thank you for the help.
Also I think I made a mistake with the script. The destroy event doesn’t trigger because the coin is a clone. The script isn’t just spawning in the coins that are in workspace, the script is placing the coins in the room while it may still be in Server Storage because the tags reach there too. You may have to check if part is not decedent of server storage before adding coin.