Delayed Raycast

Hello! I’m trying to make a gun that has a delayed shot. When the user presses a button, then it waits a bit while playing a sound, then it shoots where the mouse currently is… I have been trying to make this for a while but I have no idea on how do delay the raycast. Here is my current script:

Local script
local Tool = script.Parent
local Handle = Tool:WaitForChild("Handle")
local Remote = Tool:WaitForChild("Remote")

local Mouse = nil

local Active = false

Tool.Equipped:Connect(function(m)
    Mouse = m
    Mouse.Icon = "rbxasset://textures/GunCursor.png"
end)

Tool.Unequipped:Connect(function()
    Active = false
    Mouse = nil
end)

Tool.Activated:Connect(function()
    if Active == true then return end
    Active = true
    
    repeat
        wait()
        local Target = Mouse.Target
        if Target ~= nil then
            if Target.Parent:IsA("Accessory") or Target.Parent:IsA("Tool") or Target.Transparency >= 1 then
                Mouse.TargetFilter = Mouse.Target
            end
        end
        
        Remote:FireServer(Mouse.Hit.p)
        
    until Active == false
    
end)

Tool.Deactivated:Connect(function()
    if Active == false then return end
    Active = false
end)
Server sided script
local Tool = script.Parent
local Handle = Tool:WaitForChild("Handle")
local Remote = Tool:WaitForChild("Remote")

local ProjectilePosition = Handle:WaitForChild("ProjectilePosition")
local MuzzlePE = ProjectilePosition:WaitForChild("MuzzlePE")
local Smoke = script:WaitForChild("SmokePE")

local Character
local Player
local Humanoid

local GunshotSFX = Handle:WaitForChild("GunshotSFX")
local Music = Handle:WaitForChild("Music")

local Debounce = false

local IG = {}

function Equipped()
	Character = Tool.Parent
	Player = game.Players:GetPlayerFromCharacter(Character)
	Humanoid = Character:WaitForChild("Humanoid")

	table.insert(IG,Character)
	Music:Play()
end

function Unequipped()
	Music:Stop()
end

function Raycast(MousePosition)
	local RayLaser = Ray.new(ProjectilePosition.WorldCFrame.Position, (MousePosition - ProjectilePosition.WorldCFrame.Position).unit * 300)
	local Hit, Position = game.Workspace:FindPartOnRayWithIgnoreList(RayLaser, IG)

	if Hit ~= nil then
		if Hit.Parent:IsA("Accessory") or Hit.Transparency >= 1 or Hit.Parent:IsA("Tool") then
			table.insert(IG,Hit)
			return Raycast(MousePosition)
		end
	end	

	local BulletHole = Instance.new("Part")
	BulletHole.BrickColor = BrickColor.new("Really black")
	BulletHole.Anchored = true
	BulletHole.CanCollide = false
	BulletHole.Massless = true
	BulletHole.Shape = Enum.PartType.Ball
	BulletHole.Size = Vector3.new(.25,.25,.25)
	BulletHole.CFrame = CFrame.new(Position,ProjectilePosition.WorldPosition)
	BulletHole.Name = "BulletHole"
	BulletHole.Parent = game.Workspace
	
	
	
	if Hit ~= nil then
		local Weld = Instance.new("WeldConstraint")
		Weld.Parent = BulletHole
		Weld.Part0 = BulletHole
		Weld.Part1 = Hit
		BulletHole.Anchored = false
		local CloneSmoke = Smoke:Clone()
		CloneSmoke.Parent = BulletHole
		CloneSmoke.Color = ColorSequence.new(Hit.Color)
		CloneSmoke:Emit(15)
	end
	game.Debris:AddItem(BulletHole,5)



	local Attachment = Instance.new("Attachment")
	Attachment.Name = "A1"
	Attachment.Parent = BulletHole

	local Beam = Instance.new("Beam")
	Beam.Width0 = .25
	Beam.Width1 = .25
	Beam.FaceCamera = true
	Beam.Color = ColorSequence.new(Color3.fromRGB(255, 255, 127))
	Beam.Parent = ProjectilePosition
	Beam.Attachment0 = ProjectilePosition
	Beam.Attachment1 = Attachment

	game.Debris:AddItem(Beam,.05)

	if Hit ~= nil then
		local EnemyHumanoid = Hit.Parent:FindFirstChild("Humanoid")
		if EnemyHumanoid ~= nil then
			if BulletHole ~= nil then
				local Attachment1 = Instance.new("Attachment")
				Attachment1.Name = "A1"
				Attachment1.Parent = Hit
				Attachment1.WorldPosition = Attachment.WorldPosition
				Beam.Attachment1 = Attachment1

				game.Debris:AddItem(Attachment1,1)

				BulletHole:Destroy()
			end
			local EnemyPlayer = game.Players:GetPlayerFromCharacter(EnemyHumanoid.Parent)
			if EnemyPlayer and not Player.Neutral and not EnemyPlayer.Neutral and Player.TeamColor == EnemyPlayer.TeamColor then
				return
			end
			EnemyHumanoid:TakeDamage(99999)
		end
	end
end

Remote.OnServerEvent:Connect(function(FiredPlayer,MousePosition)
	if Humanoid.Health == 0 then return end
	if FiredPlayer ~= Player then return end
	if Debounce == true then return end
	Debounce = true
	Humanoid.WalkSpeed = 5
	script.Parent.Handle.Sound:Play()
	wait(3)
	script.Parent.Handle.Sound:Stop()
	MuzzlePE:Emit(5)
	local GunshotSFXClone = GunshotSFX:Clone()
	GunshotSFXClone.Parent = ProjectilePosition
	GunshotSFXClone:Play()
	game.Debris:AddItem(GunshotSFXClone, 2)
	
	local PointLight = ProjectilePosition.PointLight:Clone()
	PointLight.Parent = ProjectilePosition
	PointLight.Enabled = true
	game.Debris:AddItem(PointLight,.05)

	Raycast(MousePosition)
	Humanoid.WalkSpeed = 16
	wait(10)
	script.Parent:Destroy()
	Debounce = false
end)

Tool.Equipped:Connect(Equipped)
Tool.Unequipped:Connect(Unequipped)
``````lua
local Tool = script.Parent
local Handle = Tool:WaitForChild("Handle")
local Remote = Tool:WaitForChild("Remote")

local ProjectilePosition = Handle:WaitForChild("ProjectilePosition")
local MuzzlePE = ProjectilePosition:WaitForChild("MuzzlePE")
local Smoke = script:WaitForChild("SmokePE")

local Character
local Player
local Humanoid

local GunshotSFX = Handle:WaitForChild("GunshotSFX")
local Music = Handle:WaitForChild("Music")

local Debounce = false

local IG = {}

function Equipped()
	Character = Tool.Parent
	Player = game.Players:GetPlayerFromCharacter(Character)
	Humanoid = Character:WaitForChild("Humanoid")

	table.insert(IG,Character)
	Music:Play()
end

function Unequipped()
	Music:Stop()
end

function Raycast(MousePosition)
	local RayLaser = Ray.new(ProjectilePosition.WorldCFrame.Position, (MousePosition - ProjectilePosition.WorldCFrame.Position).unit * 300)
	local Hit, Position = game.Workspace:FindPartOnRayWithIgnoreList(RayLaser, IG)

	if Hit ~= nil then
		if Hit.Parent:IsA("Accessory") or Hit.Transparency >= 1 or Hit.Parent:IsA("Tool") then
			table.insert(IG,Hit)
			return Raycast(MousePosition)
		end
	end	

	local BulletHole = Instance.new("Part")
	BulletHole.BrickColor = BrickColor.new("Really black")
	BulletHole.Anchored = true
	BulletHole.CanCollide = false
	BulletHole.Massless = true
	BulletHole.Shape = Enum.PartType.Ball
	BulletHole.Size = Vector3.new(.25,.25,.25)
	BulletHole.CFrame = CFrame.new(Position,ProjectilePosition.WorldPosition)
	BulletHole.Name = "BulletHole"
	BulletHole.Parent = game.Workspace
	
	
	
	if Hit ~= nil then
		local Weld = Instance.new("WeldConstraint")
		Weld.Parent = BulletHole
		Weld.Part0 = BulletHole
		Weld.Part1 = Hit
		BulletHole.Anchored = false
		local CloneSmoke = Smoke:Clone()
		CloneSmoke.Parent = BulletHole
		CloneSmoke.Color = ColorSequence.new(Hit.Color)
		CloneSmoke:Emit(15)
	end
	game.Debris:AddItem(BulletHole,5)



	local Attachment = Instance.new("Attachment")
	Attachment.Name = "A1"
	Attachment.Parent = BulletHole

	local Beam = Instance.new("Beam")
	Beam.Width0 = .25
	Beam.Width1 = .25
	Beam.FaceCamera = true
	Beam.Color = ColorSequence.new(Color3.fromRGB(255, 255, 127))
	Beam.Parent = ProjectilePosition
	Beam.Attachment0 = ProjectilePosition
	Beam.Attachment1 = Attachment

	game.Debris:AddItem(Beam,.05)

	if Hit ~= nil then
		local EnemyHumanoid = Hit.Parent:FindFirstChild("Humanoid")
		if EnemyHumanoid ~= nil then
			if BulletHole ~= nil then
				local Attachment1 = Instance.new("Attachment")
				Attachment1.Name = "A1"
				Attachment1.Parent = Hit
				Attachment1.WorldPosition = Attachment.WorldPosition
				Beam.Attachment1 = Attachment1

				game.Debris:AddItem(Attachment1,1)

				BulletHole:Destroy()
			end
			local EnemyPlayer = game.Players:GetPlayerFromCharacter(EnemyHumanoid.Parent)
			if EnemyPlayer and not Player.Neutral and not EnemyPlayer.Neutral and Player.TeamColor == EnemyPlayer.TeamColor then
				return
			end
			EnemyHumanoid:TakeDamage(99999)
		end
	end
end

Remote.OnServerEvent:Connect(function(FiredPlayer,MousePosition)
	if Humanoid.Health == 0 then return end
	if FiredPlayer ~= Player then return end
	if Debounce == true then return end
	Debounce = true
	Humanoid.WalkSpeed = 5
	script.Parent.Handle.Sound:Play()
	wait(3)
	script.Parent.Handle.Sound:Stop()
	MuzzlePE:Emit(5)
	local GunshotSFXClone = GunshotSFX:Clone()
	GunshotSFXClone.Parent = ProjectilePosition
	GunshotSFXClone:Play()
	game.Debris:AddItem(GunshotSFXClone, 2)
	
	local PointLight = ProjectilePosition.PointLight:Clone()
	PointLight.Parent = ProjectilePosition
	PointLight.Enabled = true
	game.Debris:AddItem(PointLight,.05)

	Raycast(MousePosition)
	Humanoid.WalkSpeed = 16
	wait(10)
	script.Parent:Destroy()
	Debounce = false
end)

Tool.Equipped:Connect(Equipped)
Tool.Unequipped:Connect(Unequipped)

As you see I’m working with remotes N stuff. The current shoots where the player had the Mouse the moment they clicked. But I want it to shoot where their mouse is after the delay. Can anyone help?

4 Likes

Normally with gun systems you do the raycasting on the client for better user experience and then sent the info like hit instance, position and normal via remoteevent to the server to handle.
The delay is most likely because you’re doing the raycasting and sounds on the server which has a delay between it and clients.

1 Like

u should do client replication for the visual effects, use :FireAllClients and listen on a local script

No I want it delayed. I just don’t know how to delay a raycast.

use task.wait(delay) before running the function on the server

My problems is not the delay part. My problem is the raycast part. I don’t know how to delay the raycast if the trigger sends the location of the mouse and that activates the functions. I updated the post so it’s more clear of what I want.

Still can’t find the solution sadly.

If I understand you correctly, the script is supposed to do the following:

You click with the tool activated > it waits and plays a sound > when the sound is over, the position of the mouse is sent to the server > Raycasts

Did I understand it right?

(I am soon on my pc and will then look for the solution)

Hey Torba, Im not entirely sure what you mean. I have two different scripts that may do what you want to achieve:

1. You click with the tool equipped and 1 second later it fires: | Local Script
local Tool = script.Parent
local Handle = Tool:WaitForChild("Handle")
local Remote = Tool:WaitForChild("Remote")

local Mouse = nil

Tool.Equipped:Connect(function(m)
	Mouse = m
	Mouse.Icon = "rbxasset://textures/GunCursor.png"
end)

Tool.Unequipped:Connect(function()
	Mouse = nil
end)

Tool.Activated:Connect(function()
	print("now clicked")
	task.wait(1.5)
	local Target = Mouse.Target
	if Target ~= nil then
		if Target.Parent:IsA("Accessory") or Target.Parent:IsA("Tool") or Target.Transparency >= 1 then
			Mouse.TargetFilter = Mouse.Target
		end
	end

	if Tool.Equipped then
		Remote:FireServer(Mouse.Hit.p)
		print("now firing")
	end
end)
2. You click and it fires when you let go: | Local Script
local Tool = script.Parent
local Handle = Tool:WaitForChild("Handle")
local Remote = Tool:WaitForChild("Remote")

local Mouse = nil

local Active = false

Tool.Equipped:Connect(function(m)
    Mouse = m
    Mouse.Icon = "rbxasset://textures/GunCursor.png"
end)

Tool.Unequipped:Connect(function()
    Active = false
    Mouse = nil
end)

Tool.Activated:Connect(function()
    if Active == true then return end
    Active = true
    
    repeat
		wait()
        local Target = Mouse.Target
        if Target ~= nil then
            if Target.Parent:IsA("Accessory") or Target.Parent:IsA("Tool") or Target.Transparency >= 1 then
                Mouse.TargetFilter = Target
            end
        end
        
        
    until Active == false
	
	if Active == false then
		print("now letting go")
		Remote:FireServer(Mouse.Hit.p)
	end
end)

Tool.Deactivated:Connect(function()
    if Active == false then return end
    Active = false
end)

As mentioned above, I am not sure exactly what you are trying to achieve. If these solutions don’t fit, please let me know.

You can make a RemoteFunction in ReplicatedStorage and use that to get client mouse, smth like this

-- client
local RF = game:GetService("ReplicatedStorage").RemoteFunction
local player = game:GetService("Players").LocalPlayer

RF.OnClientInvoke = function()
    return player:GetMouse().Hit
end
-- server
local RF = game:GetService("ReplicatedStorage").RemoteFunction

local mouseposition = RF:InvokeClient(player)

-- the rest of your code here

yes yes sorry for the late reply.

Yes well my problem is with these solutions that the sound is in the server-sided part because i want it to warn other players that a shot will be coming, so i want it to be like this: The person activates the tool, soud will be played, after 3 ticks the gun shoots where the current player is. But for this ill need two remote functions and i tried it before but somehow failed??

Well it seems like i think i did somethink wrong but it may be the sollution.

IM getting an error called:
“Argument 1 missing or nil” on the lines where “local mouseposition = RF:InvokeClient(player)” is.

I moddified the Sevrer sided part like so:

Remote.OnServerEvent:Connect(function(FiredPlayer)
if Humanoid.Health == 0 then return end
if FiredPlayer ~= Player then return end
if Debounce == true then return end
local GunshotSFXClone = GunshotSFX:Clone()
GunshotSFXClone.Parent = ProjectilePosition
Debounce = true
Humanoid.WalkSpeed = 5
script.Parent.Handle.Sound:Play()
wait(3)
script.Parent.Handle.Sound:Stop()
MuzzlePE:Emit(5)
GunshotSFXClone:Play()
GunshotSFX:Play()
game.Debris:AddItem(GunshotSFXClone, 2)

local PointLight = ProjectilePosition.PointLight:Clone()
PointLight.Parent = ProjectilePosition
PointLight.Enabled = true
game.Debris:AddItem(PointLight,.05)
local RF = game:GetService("ReplicatedStorage").RemoteFunction
local mouseposition = RF:InvokeClient(player)
Raycast(mouseposition)
Humanoid.WalkSpeed = 16
wait(10)
script.Parent:Destroy()
Debounce = false

end)

And the local script like so:

local Tool = script.Parent
local Handle = Tool:WaitForChild(“Handle”)
local Remote = Tool:WaitForChild(“Remote”)

local Mouse = nil

local Active = false

local RF = game:GetService(“ReplicatedStorage”).RemoteFunction
local player = game:GetService(“Players”).LocalPlayer

RF.OnClientInvoke = function()
return player:GetMouse().Hit
end

Tool.Equipped:Connect(function(m)
Mouse = m
Mouse.Icon = “rbxasset://textures/GunCursor.png”
end)

Tool.Unequipped:Connect(function()
Active = false
Mouse = nil
end)

Tool.Activated:Connect(function()
Remote:FireServer()
end)

Tool.Deactivated:Connect(function()
if Active == false then return end
Active = false
end)

The error you’re getting appears as you don’t have the player on the server. You sent FiredPlayer as the instance for the player so maybe you try replacing the line with:

local mouseposition = RF:InvokeClient(FiredPlayer)

This should prevent the error from happening if you properly send the player to the script.
However, as mentioned before, I don’t know if the script will work just by looking at it

1 Like

It seems to work but now its saying

unit is not a valid member of CFrame

at

local RayLaser = Ray.new(ProjectilePosition.WorldCFrame.Position, (MousePosition - ProjectilePosition.WorldCFrame.Position).unit * 300)

Sorry i just never worked with guns and raycasts before. Also tahnk you for comming back. I also could give you the whole model if you would like to help me.

As the error code is saying, Unit cannot be used on a CFrame.
Therefore, you can simply delete the “.unit” in the script.

If you get another error, you could create a new experience, paste in the gun and then add me to the experience. Usually, I wouldn’t do this but you’re already looking for a solution for 30 days, so it would be an exception. If you decide to do this, send me a friend request on discord. My username is philtecs

1 Like

Yeah sorry to make you do this but i keep ending up with errors. I added you.
Thank you for going out of the way to help me this far. I really appriciate it.

I accepted, you can create an experience, paste the gun into it and then add me. I’ll look into it then.

1 Like

Made a place with name “Colab”
the tool is in StarterPack

Which gun is it? Is it railcannon or upgraded sniper?

1 Like