For loop running an additional time each time it is run

I’ve been working on a system wherein monsters drop coins on their death. So far, I’ve made a system that drops 1-3 coins each time a monster dies. These coins despawn after a few seconds, just before the monster despawns and respawns (they will take longer to respawn later, this is just for debugging).

However, every time the monster is killed, it randomly selects 1-3 coins and spawns them again, e.g. the first time it randomly selects 1-3, then spawns that amount of coins in, but the second time it does it twice, third time it does it three times and e.c.t.

I’m kinda confused about what this bug is, and can’t seem to fix it myself. Any help is massively appreciated!

Here’s my respawn script:

local RS = game:GetService("ReplicatedStorage")
local Drops = RS:FindFirstChild("Drops")
local Coin = Drops:FindFirstChild("Coin")

local RespawnTime = 4
local MonsterName = "LV1 Monster"
local RespawnPoint = Vector3.new(-218.865, 0.5, 204)

while wait(5) do
	Monster = script.Parent
	MonsterClone = Monster:Clone()
	
	Monster.Humanoid.Died:Wait()
	
	-- Spawns in 1 - 3 coins on mob death
	local CoinAmount = 0
	local CoinAmount = math.random(1,3)
	
	print(CoinAmount)
	
	for count = 1, CoinAmount do
		print("Coin spawned!")
		ClonedCoin = Coin:Clone()
		ClonedCoin.Parent = game.Workspace
		ClonedCoin:moveTo(Monster.Head.Position)
	end
	
	wait(RespawnTime)
	
	MonsterClone.Parent = game.Workspace.Mobs
	script.Parent = MonsterClone
	Monster:Destroy()
	
	MonsterClone:moveTo(RespawnPoint)
	MonsterClone.Humanoid.Health = MonsterClone.Humanoid.MaxHealth
	MonsterClone.Name = MonsterName
end

And here’s my coin script:

local players = game:GetService("Players")
local coin = script.Parent
local sound = coin.Sound
local IsCollected = coin.IsCollected

coin.Touched:Connect(function(Object) -- Activates when coin touched
	if Object.Parent:FindFirstChild("Humanoid") then
		local player = players:GetPlayerFromCharacter(Object.Parent)
		if player then -- Checks if is a player
			if IsCollected.value == false then
				IsCollected.Value = true
				player.PlayerStats.Coins.Value = player.PlayerStats.Coins.Value + 1 -- Adds coin
				sound:Play()
				wait(0.5)
				coin:Destroy()
			end
		end
	end
	wait(2) -- Wait then remove coin
	coin:Destroy()
end)
1 Like

I’ve noticed small syntactic problems. Firstly, you’re shadowing variables in your respawn script:

This would still return the randomly generated number, but could possibly be the reason your loop is repeating more than it should. Remove local CoinAmount = 0.

Secondly, in the coin script:

I have no idea how this hasn’t returned an error. It could just be a mistake while moving the script to the devforum, but I thought it was worth mentioning regardless.

CoinAmount = 0 was just something I was trying to see if it changed anything, forgot to remove it earlier, but it doesn’t change anything when removed.

Why would that return an error? It’s checking to see if the boolean value stored in the coin, determining if it has been collected, is false. This is to prevent the user getting the same coin multiple times, before it is removed.

It should be case sensitive though, right? You wrote value, not Value. In my experience, Roblox has always returned an error in this circumstance. Anyway, if it’s not a problem then it’s not a problem. I noticed no other problems with your code, I’m stumped.

I’ve tested the sort of system you had there, I didn’t see the issue. Could it be your luck?

Ah, didn’t realise the lower case V. It isn’t like that in the actual studio, so probs just a mistake when moving the script over here :stuck_out_tongue:

Cheers for the help anyway!

I believe the issue arises when cloning the monster at the start of your while loop, thereby creating multiple script instances that are incrementally performing the same operation.

1 Like

Good catch! Working on fixing it now…

Aye, I noticed it running an experiment with your code and noticed the following:

image

Is there a particular reason you would need the while loop in the first place if you are going to replace the model? I created a solution to this issue with the following code but it does not contain the while loop you had:

local RS = game:GetService("ReplicatedStorage")
local Drops = RS:FindFirstChild("Drops")
local Coin = Drops:FindFirstChild("Coin")

local RespawnTime = 4
local MonsterName = "LV1 Monster"
local RespawnPoint = Vector3.new(-218.865, 0.5, 204)

Monster = script.Parent

Monster.Humanoid.Died:Wait()

-- Spawns in 1 - 3 coins on mob death
local CoinAmount = 0
local CoinAmount = math.random(1,3)

print(CoinAmount)

for count = 1, CoinAmount do
	print("Coin spawned!")
	ClonedCoin = Coin:Clone()
	ClonedCoin.Parent = game.Workspace
	ClonedCoin:MoveTo(Monster.Head.Position)
end

Monster.Parent = nil

wait(RespawnTime)

local MonsterClone = Monster:Clone()
MonsterClone.Parent = workspace
MonsterClone.Humanoid.Health = MonsterClone.Humanoid.MaxHealth
MonsterClone:MoveTo(RespawnPoint)

Monster:Destroy()
script:Destroy()

This solution worked in solving the issue on my environment, hopefully it will have the same effect in yours.

The actual solution that I applied to the issue was to simply clone the model after the respawn time and destroy the script, preventing more than one from being present.

Edit: Revised the code (accidentally broke it when porting it to devforum editor oops)
Edit 2: Revised again, realized I messed up in combining my experimentation code with your original post’s code.

Thanks for the help! The while loop was something I didn’t think to remove from an earlier version of the model. I’ve slightly modified your solution, and now it works perfectly! Had to store the base for the clone in RS, to prevent cloning a model which is already broken. Cheers for the help!

local RS = game:GetService("ReplicatedStorage")

local Drops = RS:FindFirstChild("Drops")

local Coin = Drops:FindFirstChild("Coin")

local Mobs = RS:FindFirstChild("Mobs")

local MonsterBase = Mobs:FindFirstChild("LV1 Monster")

local RespawnTime = 4

local MonsterName = "LV1 Monster"

local RespawnPoint = Vector3.new(-218.865, 0.5, 204)

Monster = script.Parent

Monster.Humanoid.Died:Wait()

-- Spawns in 1 - 3 coins on mob death

local CoinAmount = 0

local CoinAmount = math.random(1,3)

print(CoinAmount)

for count = 1, CoinAmount do

print("Coin spawned!")

ClonedCoin = Coin:Clone()

ClonedCoin.Parent = game.Workspace

ClonedCoin:MoveTo(Monster.Head.Position)

end

wait(RespawnTime)

MonsterClone = MonsterBase:Clone()

MonsterClone.Parent = workspace

MonsterClone.Humanoid.Health = MonsterClone.Humanoid.MaxHealth

MonsterClone:MoveTo(RespawnPoint)

Monster:Destroy()

script:Destroy()
1 Like

Awesome. Glad I could help out.