How to optimally use RunService?

I’m making a module to simulate drops of liquid, and to give them physics I use RunService since it’s more predictable than just using the physics engine.

In reality, I’m remaking it, since if I’m gonna use it somewhere, I need it to be performant.
I’m sure a lot of things could be done better, and if you have any improvement suggestions I’d love to hear them.

But my question is, in terms of efficiency and performance, what would be the ideal method?

  • A single Heartbeat connection that handles all of the droplets

  • Multiple Heartbeat connections, one for each droplet

This is my current code, as I said any advice is welcome however I’d love any info on my current question.

-- # Initialize

	local drops = BFunctions.GetTableOfDrops()
	local DropProps = {}
	
	for index, droplet in drops do
		local props = {
			Velocity = Config.Velocity
		}
		
		DropProps[droplet] = props
		
		droplet.Position = Config.Position
	end
	
	local rayFilter = {table.unpack(Config.excludeList or {}), table.unpack(drops), CacheFolder}
	local RaycastParameters = RaycastParams.new()
	RaycastParameters.FilterType = Enum.RaycastFilterType.Exclude
	RaycastParameters.FilterDescendantsInstances = rayFilter
	RaycastParameters.RespectCanCollide = true

	-- # Main Connection

	local _connection
	
	local tbl_Droplets = {}
	local tbl_CFrames = {}
	
	ServiceFunctions.BulkParentTo(drops, CacheFolder)

	_connection = RunService.Heartbeat:Connect(function(_t, dt)
		
		table.clear(tbl_Droplets)
		table.clear(tbl_CFrames)
		
		-- · Droplet Loop
		
		for index, droplet in drops do
			local props = DropProps[droplet]
			
			local newPos = droplet.Position + props.Velocity * dt
			local ray = workspace:Raycast(droplet.Position, newPos - droplet.Position, RaycastParameters)

			-- TODO: Do stuff with Raycast

			table.insert(tbl_Droplets, droplet)
			table.insert(tbl_CFrames, CFrame.new(newPos) * CFrame.Angles(droplet.CFrame.Rotation:ToEulerAnglesXYZ()))
			
			props.Velocity += Vector3.new(0, -80, 0) * dt
		end
		
		-- · Update
		
		workspace:BulkMoveTo(tbl_Droplets, tbl_CFrames, Enum.BulkMoveMode.FireCFrameChanged)
			
	end)

Any advice? :grimacing:

I would recommend using a single RunService connection for all the dropplets simulation, as a dozen droplets needs a dozen connection, leading to more overhead.

And since everything is in a single connection, you have more control if you want to pause or resume the simulation.

Use multiple connections only if:

  • Each droplet has a unique, complex logic that cant be batched.
  • For some reason, the droplets need different update rates (Hearbeat, PreSimulation).

Additionally, you can run the simulation on a seperate thread for performance.
See Parallel Luau.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.