So, I’ve made a blood system for my game. When the player is damaged it will shoot a few blood drops at the point of impact. These blood drops are simply spheres with a vectorforce, but here comes the issue. When they touch a surface they are supposed to shoot a raycast onto said surface so it can spawn a bloodsplat part, but, they are not consistently accurate on where they spawn it.
An example of the issue may also be observed in my YouTube devlog if you pause the video and go frame by frame when the blooddrops hit the ground. ( said issue is extremely prominent at 0:26 - 0:40)
Here is the designated function responsible for handling said bloodrops and bloodsplats.
function goremodule.BloodDrop(bullethole, character, amount)
for i = 1, amount, 1 do
local blooddropclone = blooddrop:Clone()
blooddropclone.Parent = workspace
blooddropclone.CFrame = bullethole.CFrame
blooddropclone.VectorForce.Force = Vector3.new(math.random(-4, 4) / 6, math.random(2, 3) / 3, math.random(4, 6) / 10 * -1)
blooddropclone.Anchored = false
debris:AddItem(blooddropclone.VectorForce, 0.05)
debris:AddItem(blooddropclone, 5)
blooddropclone.Touched:Connect(function(op)
if op.Parent then
if op.Name ~= "Tracer" and op.Name ~= "Flesh" and op.Parent ~= character and op.Parent ~= "Holster" and op.Name ~= "BloodDrop" and op.Name ~= "Hitbox" and op.Name ~= "Handle" and not op:FindFirstChild("blood") then
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = {blooddropclone, character}
local og = blooddropclone.Position
local dir = (op.Position - blooddropclone.Position).Unit
local mag = (op.Position - blooddropclone.Position).Magnitude
local raycast = workspace:Raycast(og, dir * mag, params)
if blooddropclone.Anchored == false then
local sounds = game.ReplicatedStorage.GoreAssets.Sounds.BloodSplat:GetChildren()
local soundclone = sounds[math.random(1, #sounds)]:Clone()
soundclone.Parent = blooddropclone
soundclone:Play()
debris:AddItem(soundclone, 0.5)
end
if raycast and not raycast.Instance.Parent:FindFirstChild("Humanoid") and raycast.Instance.Name ~= "ViewBullet" and raycast.Instance.Name ~= "ViewMag" and raycast.Instance.Name ~= "Handle" and raycast.Instance.Name ~= "Holster" and raycast.Instance.Name ~= "Hitbox" then
local blood = raycast.Instance:FindFirstChild("blood")
if blood then
local bloodtween = tweenservice:Create(raycast.Instance, tweeninfo1, {Size = raycast.Instance.Size + Vector3.new(0.2, 0.2, 0)})
bloodtween:Play()
bloodtween.Completed:Connect(function()
bloodtween:Destroy()
end)
else
local bloodsplat = bloodsplats[math.random(1, #bloodsplats)]
local bloodsplatclone = bloodsplat:Clone()
bloodsplatclone.Parent = raycast.Instance
bloodsplatclone.Position = raycast.Position
blooddropclone.CollisionGroup = "Default"
local radsize = math.random(1, 2)
bloodsplatclone.Size = Vector3.new(radsize, radsize, 0.001)
local randomAngle = math.random() * 2 * math.pi
local randomRotation = CFrame.Angles(0, 0, randomAngle)
local attach = Instance.new("Attachment", bloodsplatclone)
bloodsplatclone.CFrame = CFrame.new(bloodsplatclone.Position, bloodsplatclone.Position + raycast.Normal) * randomRotation
bloodsplatclone.BloodWeld.Part1 = raycast.Instance
local smallpuff = game.ReplicatedStorage.GoreAssets.Blood.BloodSplashParticles.Splats:Clone()
smallpuff.Parent = attach
smallpuff:Emit(math.random(32, 67))
debris:AddItem(smallpuff, 5)
if op.Anchored == true then
bloodsplatclone.BloodWeld:Destroy()
bloodsplatclone.Anchored = true
end
task.wait(55)
debris:AddItem(bloodsplatclone, 5)
local decal = bloodsplatclone:FindFirstChild("Decal")
if decal then
local tween = tweenservice:Create(bloodsplatclone.Decal, TweenInfo.new(2), {Transparency = 1})
tween:Play()
tween.Completed:Connect(function()
tween:Destroy()
end)
end
end
end
blooddropclone.Anchored = true
blooddropclone.CanCollide = false
blooddropclone.CanQuery = false
blooddropclone.Transparency = 1
end
end
end)
end
end
Anybody’s assistance is greatly appreciated.