Nothing like waking up in the morning to a bug you’ve been trying to fix for weeks.
For the next game that I’m working on, I have coins that are stored within ServerStorage and are then cloned into workspace. I’m using CollectionService to handle every coin in the game. The problem is that the coins won’t work unless their script is somehow delayed until they are cloned into the workspace. For the longest time, using wait(15) would have them work just fine as after 15 they’d already be in the workspace. Yesterday I tried to optimize this with the following code (because at some point wait() will also stop working):
if coin:IsDescendantOf(game.ServerStorage) then
repeat wait() until coin:IsDescendantOf(workspace)
end
No matter how I word it or where I put it, it doesn’t fully work. It will, however, print before the repeat, but never after.
Here’s all of the coin script:
local CollectionService = game:GetService("CollectionService")
local CoinScriptEvent = game.ReplicatedStorage.Events.GameEvents.CoinScriptEvent
-- if i put a wait(15) here, it'll work just fine
for i,coin in pairs(CollectionService:GetTagged("Coin")) do
-- this is the code im trying to get working
-- waits until the coin is inside workspace
if coin:IsDescendantOf(game.ServerStorage) then
repeat wait() until coin:IsDescendantOf(workspace)
end
local Players = game:GetService("Players")
local CoinGuiEvent = game.ReplicatedStorage.Events.GuiEvents.CoinGuiEvent
local coinGui = game.StarterGui.CoinGui
local coinSound = coin.Collect
local _isTouched = false
-- if touched by player, execute
coin.Touched:Connect(function(object)
if object:FindFirstAncestorWhichIsA("Model") then
if object.Parent:FindFirstChild("Humanoid") then
--found player
local RealPlayer = game.Players:GetPlayerFromCharacter(object.Parent)
if _isTouched == false then
-- not important so left out
end
end
end
end)
-- play animation until collected
function spinAnimation()
-- code here
end
task.defer(spinAnimation)
end
So this sounds like the start and end of your problem; the coins in the ServerStorage are cloned into the workspace. This means that there is always going to be a basic coin inside the ServerStorage that just never moves, and because it’s tagged, it’ll just keep repeating over and over.
So, here is a better layout concept, break it into 3 parts;
The coin’s code, this is specific to whatever object, but you house it inside a function called something like ‘‘CoinSpawn’’ and it does all your touched events and everything specific to each coin.
You use that existing loop you have there to find any coins that already exist in the game world. Theres lots of different reasons that coins might already be in the world, this just captures them if they are.
You use @dthecoolest’s suggestion and use CollectionService:GetInstanceAdded(“Coin”):Connect(CoinSpawn)
You can now create loads of different coins after this and they’ll all spawn with the code from the Coin spawn working.
What does this mean? Well, you can just state: if coin:IsDescendantOf(workspace) == false then return end
No need for loops and the like here.
Went ahead and combined 1. and 3. together and came up with this new script:
function CoinSpawn(coin)
if coin:IsDescendantOf(workspace) == false then
return
end
-- yadda yadda yadda
end
CollectionService:GetInstanceAddedSignal("Coin"):Connect(CoinSpawn)
It’s very strange. It works without the if statement. But the coin(s) were inside workspace when I was running the game. Did I put the if statement in the wrong spot?
A new coin has been added, lets pass that coin into this function
Is the coin somewhere in the workspace?
→ If it’s in the workspace, lets do something
→ If it’s not in the workspace, lets just return and finish.
The script you’ve got there should work whenever you add a new object with the tag.
I use something similar when I’m searching for objects with tags that can only exist in the workspace;
function CollectAllTaggedInGame(Tag) --Returns a full list of the objects, but only if they are children of the workspace.
local TheseObjects = game:GetService("CollectionService"):GetTagged(Tag) --Search for the given tag
local ThisList = {}
for key, object in pairs(TheseObjects) do --Iterate through the returned objects
if object:IsDescendantOf(workspace) then --So long as the object is a descendant of the workspace
table.insert(ThisList, object) --Add it to the given list
end
end
return ThisList
end