Help With Gun Raycasting

Hey there,

I am trying to make a FPS gun viewmodel arms. I encountered a problem after inserting the viewmodel where the ray is being casted from the gun straight forward instead of being casted from the gun to wherever the mouse hits. At least I think the problem is with raycasting.

Here is a video & picture of what I mean:

https://gyazo.com/fc629a8d694e0e3324f9754060c6f76a

As you can see, the when I shot the gun, the CURSOR is pointing into the air, while the gun is pointed straight towards the wall. Because the cursor is pointed in the air, it should not have print Pink. I think this is a ray problem because even though the cursor is pointed in the air, the gun itself is pointed right to the wall.

I have been stuck on this problem for about 2 days now. I’ve already tried things such as changing some ray values and trying to debug with print. However these have not led me to the solution yet. I’d appreciate it if you could help me.

Here is my ray casting serve sided code:

local remoteEvent = game.ReplicatedStorage:WaitForChild("RayCast")
local Debris = game:GetService("Debris")

remoteEvent.OnServerEvent:Connect(function(player, fromP, toP)
	local RayCast = Ray.new(fromP, (toP-fromP).unit * -100)
	local Part, Position = game.Workspace:FindPartOnRay(RayCast, player.Character, false, true)
	if Part then
		print(Part.Name)
		local hum = Part.parent:FindFirstChild("Humanoid")
		if hum then
			hum:TakeDamage(30)
		end
	end
end)

Here is my code for the whole gun and viewmodel itself:

local arms = game.ReplicatedStorage.DefaultViewport:Clone()
local gun = arms.Pistol
local run = game:GetService("RunService")
local gunFlash = arms:WaitForChild("Pistol").GunFlash
local gunReload = gun.Handle["Gun Reload"]
local gunShoot = gun.Handle["Gun Shot"]
local emptyGun = gun.Handle["Pistol Empty Clip"]
local Players = game:GetService("Players")
local plr = Players.LocalPlayer
local Chr = plr.Character or plr.CharacterAdded:Wait()
local Hum = Chr:WaitForChild("Humanoid")
local Ammo = gun.Ammo
local debounce = false
local mouse = plr:GetMouse()
local cam = workspace.Camera
local RayCastEvent = game.ReplicatedStorage:WaitForChild("RayCast")
local AnimationTracks = Chr.Humanoid:GetPlayingAnimationTracks()

arms.Parent = cam

for i, v in pairs(arms:GetDescendants()) do
	if v:IsA("MeshPart") then
		v.Transparency = 1
	end
end

script.Parent.Equipped:Connect(function()
	local mouse = plr:GetMouse()
	for i, v in pairs(arms:GetDescendants()) do
		if v:IsA("MeshPart") then
			v.Transparency = 0
		end
	end
	
	plr.CameraMode = Enum.CameraMode.LockFirstPerson
	
	local FPSARMS = cam:WaitForChild("DefaultViewport")
	FPSARMS.LeftArm.Transparency = 0
	FPSARMS.RightArm.Transparency = 0
	
	local hum = arms.Humanoid
	local anim = arms.Animation
	local loadAnim = hum:LoadAnimation(anim)
	
	local Shootanim = arms.ShootAnimation
	local loadShoot = hum:LoadAnimation(Shootanim)
	
	loadAnim:Play()
	
	run.RenderStepped:Connect(function()
		arms:SetPrimaryPartCFrame(cam.CFrame * CFrame.new(0,0.3,-1) * CFrame.Angles(0,0,0))
		if Chr.Humanoid.MoveDirection == Vector3.new(0,0,0) then
			if not table.find(AnimationTracks, loadAnim) then
				loadAnim:Play()
			end
		else
			if table.find(AnimationTracks, loadAnim) then
				loadAnim:Stop()
			end
		end
	end)
	
	--mouse.Icon = "http://www.roblox.com/asset/?id=5028661403"
	
	mouse.Button1Down:Connect(function()
		if Ammo.Value > 0 then
			if not debounce then
				debounce = true
				
				RayCastEvent:FireServer(arms.Pistol.GunFlash.Position, mouse.Hit.p)
				print(arms.Pistol.GunFlash.Position)
				wait()
				gunShoot:Play()
				loadShoot:Play()
				gunFlash.Flash.Enabled = true
				gunFlash.Flash.Enabled = true
				wait(0.1)
				gunFlash.Flash.Enabled = false
				gunFlash.Flash.Enabled = false
				Ammo.Value = Ammo.Value - 1
				wait(0.6)
				debounce = false
			end
		else
			emptyGun:Play()
		end
	end)
	
	local UIS = game:GetService("UserInputService")
	local reloadDebounce = false
	local isEquipped = true
	
	UIS.InputBegan:Connect(function(key, gameProcessed)
		if gun.Equipped then
			if not gameProcessed then
				if key.UserInputType == Enum.UserInputType.Keyboard and not reloadDebounce then
					if isEquipped == true then
						local keycode = key.KeyCode
						if keycode == Enum.KeyCode.R then
							reloadDebounce = true
							gunReload:Play()
							gunReload.Ended:Wait()
							Ammo.Value = 8
							wait(2)
							reloadDebounce = false
						end
					else
						
					end
				end
			end
		end
	end)
end)

script.Parent.Unequipped:Connect(function()
	for i, v in pairs(arms:GetDescendants()) do
		if v:IsA("MeshPart") then
			v.Transparency = 1
		end
	end
	plr.CameraMode = Enum.CameraMode.Classic
	mouse.Icon = ""
	plr.CameraMinZoomDistance = 15
	plr.CameraMinZoomDistance = 0.5
end)
1 Like

Well it’s because the ray is hitting the wall, as you can see when you created the ray you made the origin come from the gun, you should do it from the camera. and same goes for the the ray cast.

(local Pos = game.Workspace.CurrentCamera.CFrame.Position) -- You'll have to send this from the client since server can't get CurrentCamera
Ray.new(Pos, player.Character.HumanoidRootPart.CFrame.LookVector * 100)

That should work, if it doesn’t then it’s a different issue and sorry for wasting your time, This will simulate the same effect your going for

3 Likes

Like @StraightScared said, if your ray’s origin is the gun’s barrel then it’s possible that the ray can hit objects that the player’s cursor isn’t over. A lot of games cast their rays from the position of the player’s camera to avoid issues like yours, so try that. Add the ability to aim down sights if you want a raycast that’s accurate to the gun’s barrel while still being accurate to the player’s cursor.

I will try that, hopefully it works. Thank you!

Like this?

remoteEvent.OnServerEvent:Connect(function(player, fromP, toP, Pos)
    local RayCast = Ray.new(Pos, player.Character.HumanoidRootPart.CFrame.LookVector * 100)
    local Part, Position = game.Workspace:FindPartOnRay(RayCast, player.Character, false, true)
    if Part then
        print(Part.Name)
        local hum = Part.parent:FindFirstChild("Humanoid")
        if hum then
            hum:TakeDamage(30)
        end
    end
end)

I won’t need this anymore correct?

local RayCast = Ray.new(fromP, (toP-fromP).unit * -100)

I don’t know about this, I only design games on roblox studio. Only programmers can know the code of the pass :slight_smile:

Hire me if you cannot design the pistol

Yep, you won’t need that anymore but that script should work

Hmm, but where will the ray go now?

You should be using workspace:Raycast(Origin, Direction, RaycastParams) instead of the deprecated version FindPartOnRay. You can also visualize a ray by creating a part and setting its size to Vector3.new(0.1,0.1, (Origin-RaycastResult.Position)) and offsetting it with CFrame.

1 Like