Making rays all fire at the same time

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)

1 Like

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()

Wouldn’t ClearAllChildren() destroy all of the bullet holes?

I tried this and it’s still not fixed.

	local ignoreTable = {tool, player.Character, workspace.BulletHoles:GetChildren()}

you dont need :getchildren() because it will also ignore all descendants, also its probably because of this line

createHitEffect(part, cframe)

if its not instant its going to yield so you should probably wrap it in a task.spawn

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(function()
	createHitEffect(part, cframe)
end)

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}

2 Likes

Thank you!

i need more characters

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.