Blood Particle on Hit
Key RequiredUniversal

Blood Particle on Hit

Universal ScriptAzScripterAzScripter 2.9K views 1.5K executesUpdated Nov 30, 2025
5.0/ 5(4 votes)
40100% Positive
Lua Script•147 lines (4812 chars)
local Players=game:GetService("Players")
local RunService=game:GetService("RunService")
local TweenService=game:GetService("TweenService")
local Workspace=game:GetService("Workspace")
local player=Players.LocalPlayer

local BLOOD_TEXTURE_PARTICLE="rbxassetid://102626391021863"
local BLOOD_DECAL_TEXTURE="rbxassetid://11890766147"
local BASE_RATE=80
local DAMAGE_MULTIPLIER=0.04
local MIN_ADD=0.4
local MAX_ADD=4.0
local MAX_TOTAL_DURATION=10.0
local RATE_MULTIPLIER=150
local BURST_MULTIPLIER=3.2
local PUDDLE_CHANCE=0.7
local PUDDLE_COUNT=2
local PUDDLE_SIZE_MIN=1.5
local PUDDLE_SIZE_MAX=4.0
local PUDDLE_LIFETIME=45

local function createBloodPuddle(position)
	local puddleSize=math.random(PUDDLE_SIZE_MIN*10,PUDDLE_SIZE_MAX*10)/10
	local rayOrigin=position+Vector3.new(0,5,0)
	local rayDirection=Vector3.new(0,-50,0)
	local raycastParams=RaycastParams.new()
	raycastParams.FilterType=Enum.RaycastFilterType.Blacklist
	raycastParams.FilterDescendantsInstances={player.Character}
	local raycastResult=Workspace:Raycast(rayOrigin,rayDirection,raycastParams)
	if not raycastResult then return end
	local hitPosition=raycastResult.Position
	local hitNormal=raycastResult.Normal
	local puddlePart=Instance.new("Part")
	puddlePart.Name="BloodPuddle"
	puddlePart.Size=Vector3.new(puddleSize,0.01,puddleSize)
	puddlePart.Material=Enum.Material.SmoothPlastic
	puddlePart.Transparency=1
	puddlePart.CanCollide=false
	puddlePart.Anchored=true
	puddlePart.CanQuery=false
	puddlePart.Parent=Workspace
	local rightVector=Vector3.yAxis:Cross(hitNormal).Unit
	local upVector=hitNormal
	puddlePart.CFrame=CFrame.fromMatrix(hitPosition+Vector3.new(0,0.005,0),rightVector,upVector)
	local decal=Instance.new("Decal")
	decal.Name="BloodDecal"
	decal.Texture=BLOOD_DECAL_TEXTURE
	decal.Face=Enum.NormalId.Top
	decal.Transparency=0
	decal.Parent=puddlePart
	local fadeInfo=TweenInfo.new(PUDDLE_LIFETIME,Enum.EasingStyle.Quad,Enum.EasingDirection.Out)
	local fadeTween=TweenService:Create(puddlePart,fadeInfo,{Size=Vector3.new(0,0,0)})
	local decalTween=TweenService:Create(decal,fadeInfo,{Transparency=1})
	fadeTween:Play()
	decalTween:Play()
	fadeTween.Completed:Connect(function()
		puddlePart:Destroy()
	end)
end

local function setupBlood(character)
	local humanoid=character:WaitForChild("Humanoid")
	local root=character:WaitForChild("HumanoidRootPart")
	local attach=Instance.new("Attachment")
	attach.Name="BloodAttachment"
	attach.Parent=root
	local blood=Instance.new("ParticleEmitter")
	blood.Name="BloodFlow"
	blood.Parent=attach
	blood.Texture=BLOOD_TEXTURE_PARTICLE
	blood.Color=ColorSequence.new(Color3.fromRGB(139,0,0))
	blood.Transparency=NumberSequence.new({
		NumberSequenceKeypoint.new(0,0),
		NumberSequenceKeypoint.new(0.4,0.1),
		NumberSequenceKeypoint.new(1,0.7)
	})
	blood.Size=NumberSequence.new({
		NumberSequenceKeypoint.new(0,0.7),
		NumberSequenceKeypoint.new(0.5,0.5),
		NumberSequenceKeypoint.new(1,0.1)
	})
	blood.Lifetime=NumberRange.new(1.4,3.2)
	blood.Rate=BASE_RATE
	blood.Speed=NumberRange.new(4,14)
	blood.SpreadAngle=Vector2.new(90,90)
	blood.VelocitySpread=360
	blood.Acceleration=Vector3.new(0,-48,0)
	blood.Drag=1.5
	blood.RotSpeed=NumberRange.new(-400,400)
	blood.LightEmission=0.95
	blood.ZOffset=0.1
	blood.Enabled=false
	local bleedEndTime=0
	local bleedConnection=nil
	local function updateBleed()
		local remaining=math.max(0,bleedEndTime-tick())
		if remaining<=0 then
			blood.Enabled=false
			blood.Rate=BASE_RATE
			if bleedConnection then
				bleedConnection:Disconnect()
				bleedConnection=nil
			end
		else
			blood.Rate=BASE_RATE+remaining*RATE_MULTIPLIER
		end
	end
	local lastHealth=humanoid.Health
	humanoid.HealthChanged:Connect(function(health)
		if health<lastHealth then
			local damage=lastHealth-health
			local emitAmount=math.clamp(damage*BURST_MULTIPLIER,40,180)
			blood:Emit(emitAmount)
			local addedDuration=math.clamp(damage*DAMAGE_MULTIPLIER,MIN_ADD,MAX_ADD)
			local now=tick()
			if bleedEndTime>now then
				bleedEndTime=bleedEndTime+addedDuration
			else
				bleedEndTime=now+addedDuration
			end
			bleedEndTime=math.min(bleedEndTime,now+MAX_TOTAL_DURATION)
			blood.Enabled=true
			if not bleedConnection then
				bleedConnection=RunService.Heartbeat:Connect(updateBleed)
			end
			updateBleed()
			if math.random()<PUDDLE_CHANCE then
				local puddleCount=math.clamp(math.floor(damage/20),1,PUDDLE_COUNT)
				for i=1,puddleCount do
					local offset=Vector3.new(math.random(-2,2),0,math.random(-2,2))
					task.spawn(function()
						createBloodPuddle(root.Position+offset)
					end)
				end
			end
		end
		lastHealth=health
	end)
	character.AncestryChanged:Connect(function()
		if bleedConnection then bleedConnection:Disconnect() end
	end)
end

player.CharacterAdded:Connect(setupBlood)
if player.Character then
	setupBlood(player.Character)
end

Features & Information

Features: - Customized Script - ejects blood particles if the player takes damage Tags: blood, damage, bleed, particles, vfx, gore, combat, blood splatter, hit effect, script, realistic blood, health, on hit, visual effects, pvp, fps, horror, fighting, action, simple blood, damage fx
#Blood#Particles#Damage#Bleed#Gore

Community Comments (4)

m4arm4arNov 30, 2025

Cool

zxcvzxcvNov 30, 2025

seems good

bigstinky67bigstinky67Dec 5, 2025

ik this is random but could you make a metal sonic script if you don't have the time it's ok

nacuatristramjrnacuatristramjrMay 18, 2026

How do I execute

More Scripts for Universal Scripts