How would I go about adding Blood Stains?

I’d like to recreate the blood stain effect when damaged like an many other games. Basically, when a player takes damage, it’ll spawn a decal of a blood stain on the floor (or wall if close enough). I’m not really sure how to go about adding this though? Any help would be appreciated.

1 Like

You can use Instance.new() to create a part under the player (a red circle) when it takes damage.

Yes, but how would I know the exact Y position of the floor to make sure the blood isn’t floating above the player?

What I would do is set the Instance.New() to be unanchored and put it below the player. It will fall to the floor this way.

game.Players.PlayerAdded:Connect(function(Player)
	Player.CharacterAdded:Connect(function(Character)
		local Humanoid = Character:WaitForChild("Humanoid")
		local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
		local LastHealth = Humanoid.Health
		Humanoid:GetPropertyChangedSignal("Health"):Connect(function()
			if LastHealth > Humanoid.Health then
				local raycastParams = RaycastParams.new()
				raycastParams.FilterDescendantsInstances = {Character}
				raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
				local raycastResult = workspace:Raycast(HumanoidRootPart.Position, Vector3.new(0, -10, 0), raycastParams)
				if raycastResult then
					coroutine.wrap(function()
						for i = 1, math.random(1, 4) do
							wait(0.15)
							local Blood = Instance.new("Part")
							local RandomSize = math.random(1, 5)
							Blood.Size = Vector3.new(RandomSize, 0.1, RandomSize)
							Blood.Anchored = true
							local RandomOffset = Vector3.new(math.random(-2, 2), 0, math.random(-2, 2))
							Blood.CFrame = CFrame.new(raycastResult.Position + RandomOffset)
							Blood.Name = "Blood"
							Blood.Color = Color3.fromRGB(147, 0, 0)
							Blood.TopSurface = Enum.SurfaceType.SmoothNoOutlines
							Blood.CanCollide = false
							Blood.Parent = Character
							local Mesh = Instance.new("SpecialMesh")
							Mesh.MeshType = Enum.MeshType.Sphere
							Mesh.Parent = Blood
							coroutine.wrap(function()
								wait(1.5)
								game:GetService("TweenService"):Create(Blood, TweenInfo.new(2), {Transparency = 1}):Play()
								wait(2)
								Blood:Destroy()
							end)()
						end
					end)()
				end
			end
			LastHealth = Humanoid.Health
		end)
	end)
end)

raycast down from the HumanoidRootPart then use raycastResult.Positon to get where it hit the floor

Thanks! I’ll make sure to try this out. :smiley: