Scripting with or without coroutines?

My code raycasts down every heartbeat.

I have heard on other forums that coroutines are bad, I have 2 scripts doing the same thing but one with and the other one without coroutines, so now I want to know your opinion on which one I need to choose.

Option 1

mainScript

local bridgeMechanics = require(game:GetService("ServerScriptService").bridgeMechanics)
bridgeMechanicsCoroutine = coroutine.wrap(bridgeMechanics.run)
bridgeMechanicsCoroutine()
while true do
	print("other stuff")
	task.wait()
end

bridgeMechanicsScript

local bridgeMechanics = {}
local players = game:GetService("Players")

function bridgeMechanics.run()
	while true do
		-- Casting a ray
		local rayDirection = Vector3.new(0,-10,0)
		local rayParams = RaycastParams.new()
		rayParams.FilterDescendantsInstances = workspace.platforms:GetChildren()
		rayParams.FilterType = Enum.RaycastFilterType.Whitelist
		-- Stuff above is outside of the loop because it doesn't change
		for _,v in pairs(players:GetPlayers()) do
			if v.Character then
				local rayOrigin = v.Character.HumanoidRootPart.Position
				local raycastResult = workspace:Raycast(rayOrigin, rayDirection, rayParams)
				print(raycastResult)
			end
		end
		task.wait()
	end
end

return bridgeMechanics

Option 2

mainScript

local bridgeMechanics = require(game:GetService("ServerScriptService").bridgeMechanics)

while true do

bridgeMechanics.run()

print("other stuff")

task.wait()

end

bridgeMechanicsScript

local bridgeMechanics = {}
local players = game:GetService("Players")

function bridgeMechanics.run()
	-- Casting a ray
	local rayDirection = Vector3.new(0,-10,0)
	local rayParams = RaycastParams.new()
	rayParams.FilterDescendantsInstances = workspace.platforms:GetChildren()
	rayParams.FilterType = Enum.RaycastFilterType.Whitelist
	-- Stuff above is outside of the loop because it doesn't change
	for _,v in pairs(players:GetPlayers()) do
		if v.Character then
			local rayOrigin = v.Character.HumanoidRootPart.Position
			local raycastResult = workspace:Raycast(rayOrigin, rayDirection, rayParams)
			print(raycastResult)
		end
	end
end

return bridgeMechanics

Coroutines aren’t bad in performance (Obviously if you don’t use like a million of them). Coroutines are used to run stuff in another thread to not yield the current thread so you should choose Option 1 if you don’t want to yield your script’s thread.

The only bad thing is your infinite loop which can decrease performance but I don’t know it’s purpose so I will just recommend you to try to find a different way to do it.

Would it still decrease performance if it uses task.wait()?

It’s equivalent to RunService:Heartbeat:Wait()

Coroutines would still yield, they don’t run at the same time, they run one after the other.

To add on to this, I have also used coroutines for data persistence between loops.
I used it in a turn based rpg type game for certain effects from attacks to be able to run arbitrary code at the end of a turn, for a specified amount of turns.

1 Like

Yes but in practice, you won’t notice that. I used coroutines and haven’t see that when a thread yields, another will yield too.

Yes, it will since you are raycasting every frame (I’m not saying that task.wait is bad, just a bad use imo)
You should replace your loop with a “creative way” of doing what it does or simply just reduce the amount of work that it’s doing and increase the time each cycle takes.

Use coroutines and as long as you don’t have a million of them, you won’t have problems.

No idea how else could it check what’s below the player without raycasting.

I don’t want to use the “Touched” event because it is kinda bouncy, also, it isn’t necessarily what’s below the player.

In that case, it’s fine to raycast but not every frame, each 5 seconds should be fine.

5 seconds is too much, there is an object that needs to be updated when players stand on it, so I don’t want to make it wait for longer.

Oh, I thought you were making something like an anticheat lol. You should optimize the rest of your project so players won’t notice the perfomance decrease, meanwhile you don’t find better solutions, use your current solution.

1 Like

I see that you (and so do many other people in the forums) really need to know two things:

  1. You can’t guess performance. The only way to know how fast something runs is to benchmark it - via the microprofiler, benchmark plugins, or just via super precise os.clock timestamps. Most people commenting your performance are going to give you their opinion, but not facts.

  2. 99% of the things we code will have negligible performance impact - the limit of the engine for every frame is thousands of raycasts, near-millions of math operations and table queries, thousands of loop iterations, etc. Most of the time asking about performance is pointless, but if you must to ask - refer to point #1.

And yes, EVEN if you know some small piece of code is fast before scaling it up to hundreds or thousands times larger size, you still need to benchmark it when it’s scaled up (e.g same code running for 100 players)

3 Likes