Random item spawning efficiency

I have this loop that basically spawns food in at spawns. I just wanna make sure it’s an efficient piece of code. I just worried the RandomSpawn could technically keep getting the same spawn, and thus causing serious delays. My other problem is if all spawn points are filled, and you remove one item, it’d respawn almost instantly, as its the only free and available spot left

while true do
    task.wait(2)
    
    -- Find random spawn
    local SpawnPoint
    
    local AllSpawns = workspace.Foods:GetChildren()
    local RandomSpawn = AllSpawns[math.random(1, #AllSpawns)]
    
    if RandomSpawn:FindFirstChildWhichIsA("Model") then
        repeat
            RandomSpawn = AllSpawns[math.random(1, #AllSpawns)]
            task.wait()
        until not RandomSpawn:FindFirstChildWhichIsA("Model")
    end
    
    SpawnPoint = RandomSpawn
    
    if not SpawnPoint then continue end
    
    self:CreateFood(SpawnPoint)
end
2 Likes

This is all I could think of, it looks good to me!

(I removed the script because It sucked, lol)

For efficiency, I can see a possible improvement (like 0.001%).
What’s the point of SpawnPoint when you could just use RandomSpawn directly.
Some stuff just makes the code longer with the same functionality.

Here’s my rewrite

while task.wait(2) do
    local AllSpawns = workspace.Foods:GetChildren()
    local RandomSpawn

    repeat
        RandomSpawn = AllSpawns[math.random(1, #AllSpawns)]
        task.wait()
    until not RandomSpawn:FindFirstChildWhichIsA("Model")

    if not RandomSpawn then continue end
    
    self:CreateFood(RandomSpawn)
end

Seems good. One thing is instead of doing while true do use while task.wait(time) do instead of adding the wait inside the loop. No difference except it looks more cooler and 1 line less.

Just small point on your rewrite. Never, ever do while task.wait() do. The argument should always be conditional. Bad practice

2 Likes

It depends on the situation. While yes, true, try and use different things over while loops, if it always should be running at a certain pace, then you should probably use while task.wait() do

No, should never use while task.wait() do under ANY circumstances. If Roblox decides to make task.wait() return nothing, then all your while loops will break

What would you need to do if something happens and every 5 seconds it repeats itself? You would need to use while task.wait(). It’s a bit bias to walk into a code review and tell them to remove something without solid reasoning.

while true do
    -- do stuff
    task.wait(5)
end

I can comment on peoples suggestions if what they are suggesting is not the right way to go about things, and I just did say why it’s wrong

while task.wait() can be broken like any other loop. It saves a line and the wait is easier to change

local Number = 0

while task.wait(1) do
	Number += 1
	print(Number)
	if Number == 3 then
		break
	end
end

print("Ended!")

Output

1
2
3
Ended!

No, but you’re not understanding me. task.wait() only works cause ATM it returns something. However, Roblox could one day stop it from returning anything, and when/if they do, all your loops are broken, and will never run.

Also talked about here

1 Like

That is just a theory. Roblox has (If I am right) never mentioned doing so. Many games require this way to make important functions and it would be pointless to even do it anyways. I see your point, and I think this has gone off topic. We all have our opinions. This should stop.

1 Like

Roblox has always been keeping backwards compatibility (except when they force FilteringEnabled). They will never make them return anything else. If they want it to return something else, they will make a new function to replace it. Just like how they made task library to improve wait() spawn() delay() without risking (even a tiny chance) of breaking some games.

Now Roblox had no choice but to force FE as not forcing FE could lead to massive exploits and Roblox will be on the news. They broke old games to increase performance and game security so that was minor but I can see your point. Plus Roblox listened to the fans of removal of Experimental Mode (non FE) so we can thank Roblox for making such a important change!

1 Like

Just cause Roblox may keep backwards compatibility, doesn’t give a valid excuse to use poor practices. You don’t use deprecated items for this reason. Should always strive for making the best quality code as possible

3 Likes

Your right about using task.wait as a conditional being malpractice, however in some scenarios using task.wait is necessary to prevent the while from crashing the application. Its more of a matter of knowing when you need it, and whether theres a better solution than this

The best way to do something like this is:

  1. Use RunService instead of a while loop so that you can keep everything in-sync with the games update loop.

  2. Create a function to generate a spawn point that also stores points that have already been used and checks that list so that you dont get and duplicate points (Optionally you can set a limit on how many of those used points get stored so that you can reuse points eventually).

  3. Instead of using task.wait you can create a set of cooldown variables to determine when the item should be spawned

local RunService = game:GetService("RunService")

local SpawnRate = 1
local LastTimeSpawned = 0

RunService.Heartbeat:Connect(function()
    if LastTimeSpawned - tick() > SpawnRate then
        --Generate Random Point

        --Spawn Food

        --ResetTimer
        LastTimeSpawned = tick()
    end
end)

1 Like

That’s a lie that’s been told to you buddy, you can use while task.wait() do anytime you want, and if you want to disable the while loop you can just call break :man_shrugging:

Wait is not that great task.wait() is better but it shouldn’t be thrown in a ditch because of a video, if you look in the devforum you’ll find a post about that exact thing, where it was never mentioned you’d have to completely remove wait()/task.wait().