Blood Engine - A blood engine system

As @TimeFrenzied said, you dont have to unpack the table as it does that process for you in the module.

Don’t use the module on the server, as I have forgotten to make it so the module uses the heartbeat event instead of the renderstepped event for server-use.

Im still getting the error… that didnt fix the root cause when i called it using a client script.

Error: ReplicatedStorage.BloodEngine:110: invalid argument #1 to ‘unpack’ (table expected, got nil)

Can you show me the .new() line inside of the module?

function number, RandomOffset: boolean, Speed: number, DripDelay: number, DripVisible: boolean, FilterInstances: {})
	local self = setmetatable({}, BloodEngine)

	-- Creates a folder for drips if necessary
	local DripsFolder = Terrain:FindFirstChild("DripsFolder") or"Folder", Terrain)
	DripsFolder.Name = DripsFolder.Name == "DripsFolder" and DripsFolder.Name or "DripsFolder"

	-- Create and initialize the RaycastParams object outside of the function
	local raycastParams =
	raycastParams.FilterType = Enum.RaycastFilterType.Exclude

--This is line 110
	raycastParams.FilterDescendantsInstances = {DripsFolder, Unpack(FilterInstances)}
	raycastParams.IgnoreWater = true

	-- Assign class variables
	self.Settings = {
		DripLimit = Limit or Constants.Limit,
		Speed = Speed or Constants.Speed,
		DripDelay = DripDelay or Constants.DripDelay,
		RandomOffset = RandomOffset or Constants.RandomOffset,
		DripVisible = DripVisible or Constants.DripVisible

	self.Drips = {}
	self.DripsFolder = DripsFolder
	self.RaycastParams = raycastParams

	-- Assign other variables
	local Distance = Constants.Distance
	self._Random =

	-- Connect a single function to the Heartbeat event of the RunService
		-- If no drips exist, stop managing. Saves Performance.
		if (#self.Drips <= 0) then

		-- Iterate over all drips in the drips table
		for Index, DripArray in self.Drips do
			-- Retreive information
			local -- Unpack information
			DripInstance: MeshPart,
			EndSound: Sound,
			BasePart: BasePart,
			IsPool: boolean = Unpack(DripArray)

			-- Perform a raycast from the position of the part in the direction of its velocity and find the closest part to the drip
			local result = workspace:Raycast(DripInstance.Position,, -Distance, 0), self.RaycastParams)

			-- Check if the result is not nil and if the hit object is not the basePart
			if DripInstance and result and result.Instance ~= BasePart and not IsPool then
				-- Move the part to the hit position
				DripArray.IsPool = true
				DripInstance.Anchored = true
				DripInstance.CanCollide = false
				DripInstance.Transparency = DripPart.Transparency
				DripInstance.CFrame = * CFrame.Angles(0, 0, 0)

				-- Grow the size of the part over time to create a blood pool
				local Info =, Enum.EasingStyle.Cubic)
				local RandomTweenIncrement = self._Random:NextNumber(3, 5) / 5
				local CurrentSize = DripInstance.Size
				local SizeGoal =, self._Random:NextNumber(1, 10) / 100, RandomTweenIncrement)
				local Tween = TweenService:Create(DripInstance, Info, {Size = SizeGoal})

				-- Play size tween and start the ending sound

				-- Decrease the size and transparency of the part after a few seconds have passed
				-- Then destroy and delete it from the blood parts dataset
				local DefaultTweenInfo =, Enum.EasingStyle.Quad)
				local DefaultTween = TweenService:Create(DripInstance, DefaultTweenInfo, {Transparency = 1, Size =, 0.01, 0.01)})

				task.delay(self._Random:NextNumber(10, 15), function()

						-- Remove the drip instance from existance and from the Drips dataset
						table.remove(self.Drips, Index)

		-- Check if the number of blood parts exceeds the bloodLimit
		if #self.Drips > self.Settings.DripLimit then
			-- Decrease the size and transparency of the part after a few seconds have passed
			-- Then destroy and delete it from the blood parts dataset
			local OldestDrip: MeshPart? = table.remove(self.Drips, #self.Drips)

			local DefaultTweenInfo =, Enum.EasingStyle.Quad)
			local DefaultTween = TweenService:Create(OldestDrip, DefaultTweenInfo, {Transparency = 1, Size =, 0.01, 0.01)})



	return self

That’s an outdated version of the module, I assume its from the source code on GitHub since I forgot to update it.

So is the github code updated or do I use the RBLX model link instead?

Use the Roblox model for now. And may I ask did you use the BloodEngine file provided with the latest release on GitHub?

1 Like

I would assume so?
I’m on the main branch but I see the BloodModule file in the src folder has not been updated for 3 weeks. Maybe a commit issue?

Edit: I see the new code as a release on the sidebar. Sorry for the inconvenience.

1 Like

Report back to me if its the same as the src code, just to make sure its not outdated and if you still encounter bugs.

Thanks! everything works good now!

1 Like

Hey, I have a Issue with the Blood Module. Its said attempt to index nil with ‘Emit’

And when i’m trying to do in a LocalScript There is no Blood. How Do i fix that ?

i fixed the issue. Its Working now

What did you do to fix it ?


Please share your code. It is possible your blood instance has missing information or isn’t fully formed.

We cannot provide assistance without a baseline to see what error you can be having.

I’m guessing Emit is nil because you tried to use the module on the server, which doesn’t wont work.

Blood Engine • V0.0.5

↳ General Changes

Included a showcase place on the GitHub repository.
Added a more efficient way to change the settings: UpdateSettings.

Is there a way to do this on the server?

umm, where is the .rbxl showcase place?


There is, but why would you want to do this? Just wondering.