I am making a shotgun with raycasting and ATM the rays are all firing at different times making each hit happen roughly 1/4 of a second after the other.
shootEvt.OnServerEvent:Connect(function(player, mousePosition)
local directions = {}
for i = 1, shootCount.Value do
local offsetNumberX = math.random(spreadMin.Value, spreadMax.Value)
local offsetNumberY = math.random(spreadMin.Value, spreadMax.Value)
local offsetNumberZ = math.random(spreadMin.Value, spreadMax.Value)
local offset = Vector3.new(offsetNumberX, offsetNumberY, offsetNumberZ) / 100 * 0.25
table.insert(directions, (mousePosition - muzzle.WorldCFrame.Position).Unit + offset)
end
local origin = muzzle.WorldCFrame.Position
local ignoreTable = {tool, player.Character}
for i, bulletHole in pairs(workspace:GetDescendants()) do
if bulletHole.Name:match("Hole") then
table.insert(ignoreTable, bulletHole)
end
end
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.IgnoreWater = true
raycastParams.FilterDescendantsInstances = ignoreTable
local results = {}
for i, direction in ipairs(directions) do
local result = workspace:Raycast(origin, direction * math.random(rangeMin.Value, rangeMax.Value), raycastParams)
table.insert(results, result)
end
for i, result in pairs(results) do
local intersection = result and result.Position or origin + directions[i]
local distance = (origin - intersection).Magnitude
if result then
local part = result.Instance
local humanoid = part.Parent:FindFirstChild("Humanoid") or part.Parent.Parent:FindFirstChild("Humanoid")
local cframe = CFrame.lookAt(result.Position, result.Position + result.Normal)
if humanoid and part.Name ~= "Head" then
humanoid:TakeDamage(math.random(damageMin.Value, damageMax.Value))
elseif humanoid and part.Name == "Head" then
humanoid:TakeDamage(math.random(damageMin.Value, damageMax.Value) * 1.75)
end
createHitEffect(part, cframe)
end
end
end)
probably because of this it will take time to loop over everything in the workspace so instead put every bullet hole in a folder then use clearallchildren()
If I don’t ignore all descendants then when a bullet hole is shot, it will hit the hole, not the player.
Here is my full script (without variables) in case something above could be interfering:
function createHitEffect(part, cframe)
local partMaterial = part:FindFirstChild("Material")
if partMaterial then
local randomDecal = math.random(1, 2)
local chosenHole = holeFolder:FindFirstChild(partMaterial.Value .. "Hole")
local newBulletHole = chosenHole:Clone()
local holeWeld = newBulletHole:FindFirstChild("WeldConstraint")
newBulletHole:FindFirstChild("Decal" .. randomDecal).Transparency = 0
newBulletHole.Parent = workspace.BulletHoles
newBulletHole.CFrame = cframe
holeWeld.Part0 = part
holeWeld.Part1 = newBulletHole
newBulletHole.Anchored = false
newBulletHole.CanCollide = false
newBulletHole.CanTouch = false
if newBulletHole:FindFirstChild("ParticleAttachment") then
local particleAttachment = newBulletHole:FindFirstChild("ParticleAttachment")
for i, particles in pairs(particleAttachment:GetChildren()) do
if partMaterial.Value ~= "Humanoid" and particles:IsA("ParticleEmitter") and particles.Name ~= "Spark" then
local partColor = part.Color
particles.Color = ColorSequence.new{
ColorSequenceKeypoint.new(0, partColor),
ColorSequenceKeypoint.new(1, partColor)
}
end
particles.Enabled = true
wait(0.075)
particles.Enabled = false
end
end
if newBulletHole:FindFirstChild("Impact") then
newBulletHole.Impact:Play()
end
game.Debris:AddItem(newBulletHole, 30)
if part.Name == "Head" and partMaterial.Value == "Humanoid" then
part:FindFirstChild("face").Texture = "rbxassetid://12990317244"
end
end
end
shootEvt.OnServerEvent:Connect(function(player, mousePosition)
local directions = {}
for i = 1, shootCount.Value do
local offsetNumberX = math.random(spreadMin.Value, spreadMax.Value)
local offsetNumberY = math.random(spreadMin.Value, spreadMax.Value)
local offsetNumberZ = math.random(spreadMin.Value, spreadMax.Value)
local offset = Vector3.new(offsetNumberX, offsetNumberY, offsetNumberZ) / 100 * 0.25
table.insert(directions, (mousePosition - muzzle.WorldCFrame.Position).Unit + offset)
end
local origin = muzzle.WorldCFrame.Position
local ignoreTable = {tool, player.Character, workspace.BulletHoles:GetChildren()}
for i, bulletHole in pairs(workspace:GetDescendants()) do
if bulletHole.Name:match("Hole") then
table.insert(ignoreTable, bulletHole)
end
end
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.IgnoreWater = true
raycastParams.FilterDescendantsInstances = ignoreTable
local results = {}
for i, direction in ipairs(directions) do
local result = workspace:Raycast(origin, direction * math.random(rangeMin.Value, rangeMax.Value), raycastParams)
table.insert(results, result)
end
for i, result in pairs(results) do
local intersection = result and result.Position or origin + directions[i]
local distance = (origin - intersection).Magnitude
if result then
local part = result.Instance
local humanoid = part.Parent:FindFirstChild("Humanoid") or part.Parent.Parent:FindFirstChild("Humanoid")
local cframe = CFrame.lookAt(result.Position, result.Position + result.Normal)
if humanoid and part.Name ~= "Head" then
humanoid:TakeDamage(math.random(damageMin.Value, damageMax.Value))
elseif humanoid and part.Name == "Head" then
humanoid:TakeDamage(math.random(damageMin.Value, damageMax.Value) * 1.75)
end
createHitEffect(part, cframe)
end
end
end)
yes its definitely yielding, whenever you call a function the current thread is going to yield until the function completely finishes so you should change this line createHitEffect(part, cframe) to this
task.spawn() will create a new thread. also what i meant by ignoring descendants is that the ignore table will ignore the instance and everything inside of it so this
local ignoreTable = {tool, player.Character, workspace.BulletHoles:GetChildren()}
should be this
local ignoreTable = {tool, player.Character, workspace.BulletHoles}