mouse.Hit versus camera.CFrame.LookVector

I have no idea why that’s happening. You mention in your main post in this topic that this is a viewmodel. Are you doing any substitutions for the camera’s position or similar?

This is the actual gun not the viewmodel. I am doing this on the tool first because the viewmodel requires everything to be perfect for it to work and it is much easier to make the final product on the tool itself first and then transfer that over to the viewmodel.

Can you make a duplicate model with the bare minimum components that does the same thing and provide the file? You might need to replace parts of the model and remove other things so nothing juicy is shared.

1 Like

Yeah there’s definitely no reason to do that here because I just tested this

task.wait(4)
local ray = workspace.CurrentCamera:ScreenPointToRay(game.Players.LocalPlayer:GetMouse().Hit.Position.X, game.Players.LocalPlayer:GetMouse().Hit.Position.Y)

local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.FilterDescendantsInstances = {}

local raycastresult = workspace:Raycast(ray.Origin, ray.Direction * 400, raycastParams)

game.Players.LocalPlayer.Character:SetPrimaryPartCFrame(CFrame.new(ray.Origin))

on a local script in playerscripts and it is barely moving my player, when I replace origin with raycastresult.Position, the raycastresult returns attempt to index nil with position. Keep in mind i’m just letting my mouse sit in the middle of the screen when doing this. Unless you actually need to click the button for it to detect? I don’t think that’s how getmouse works though. I think it can detect the mouse position regardless of whether it is being clicked or not.

I would have to say this script itself is not using screenpointtoray correctly, I could be wrong but if you have an example file of it actually working when you run this code, that would be great because I can’t seem to do anything productive with it

I surely could put a test place, to be quite frankly honest I could just share it with you, the tool itself is something I personally created but the rest of it is things that other smarter developers have already made successful versions of and they just don’t want other people to follow in their footsteps so they never tell people how they did it…

Let me know which you prefer. If you insist I do it I’ll just paste it into a different tool and let you see the whole thing so you see what’s going wrong with it

Your script is perfect, the scope is small and if you can reproduce the issue with it then there’s no idea to reveal more at the time. I’m scribbling something together right now for you.

1 Like

Thank you so much. In the meanwhile I need to go eat lunch. Take your time with it no need to rush. I really appreciate you and I hope this post prevents other people from running into these same issues

I wasn’t aware which would be more useful so I slightly changed one to do something else:

Part Spawner
local ContextActionService = game:GetService("ContextActionService")
local Workspace = game:GetService("Workspace")
local Players = game:GetService("Players")

local localPlayer = Players.LocalPlayer
local mouse = localPlayer:GetMouse()

local function onContextAction(actionName: string, userInputState: Enum.UserInputState, inputObject: InputObject)
	if actionName ~= "markClick" then
		return
	elseif userInputState ~= Enum.UserInputState.Begin then
		return
	end
	
	local currentCamera = Workspace.CurrentCamera
	-- i have inputobject available but we're using mouse today!!
	local ray = currentCamera:ScreenPointToRay(mouse.X, mouse.Y)
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Exclude
	raycastParams.FilterDescendantsInstances = { localPlayer.Character }
	
	local raycast = Workspace:Raycast(ray.Origin, ray.Direction * 1000, raycastParams)
	if not raycast then
		return
	end
	
	local part = Instance.new("Part")
	part.Shape = Enum.PartType.Ball
	part.Size = Vector3.new(.5, .5, .5)
	part.Position = raycast.Position
	part.Anchored = true
	part.CanCollide = false
	part.TopSurface = Enum.SurfaceType.Smooth
	part.Parent = Workspace
end

ContextActionService:BindAction("markClick", onContextAction, false, Enum.UserInputType.MouseButton1)

Teleporter
local ContextActionService = game:GetService("ContextActionService")
local Workspace = game:GetService("Workspace")
local Players = game:GetService("Players")

local localPlayer = Players.LocalPlayer
local mouse = localPlayer:GetMouse()

local function onContextAction(actionName: string, userInputState: Enum.UserInputState, inputObject: InputObject)
	if actionName ~= "markClick" then
		return
	elseif userInputState ~= Enum.UserInputState.Begin then
		return
	end
	
	local character = localPlayer.Character
	if not character then
		return -- we can't teleport nothing
	end
	
	local currentCamera = Workspace.CurrentCamera
	-- i have inputobject available but we're using mouse today!!
	local ray = currentCamera:ScreenPointToRay(mouse.X, mouse.Y)
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Exclude
	raycastParams.FilterDescendantsInstances = { localPlayer.Character }
	
	local raycast = Workspace:Raycast(ray.Origin, ray.Direction * 1000, raycastParams)
	if not raycast then
		return
	end
	
	character:MoveTo(raycast.Position)
end

ContextActionService:BindAction("markClick", onContextAction, false, Enum.UserInputType.MouseButton1)

The teleporter uses MoveTo which is why I’m bumped above the Rig. With PivotTo, I’d be shoved next to it when I click on the floor under its arm.

1 Like

Wouldn’t camera:ViewportPointToRay() be more suitable for this, I’ve noticed through testing that, as noted on the documentation, the GUIInset affects ScreenPointToRay and it’s position is slightly lower on the y-axis than the actual mouse’s position

1 Like

The coordinates from Mouse are inset, just like ScreenPointToRay is. If you used coordinates from a GUI with default insets or something similar, then ViewportPointToRay would be the right choice to account for that.

2 Likes

Hmm, interesting, I need to play around and see which is more accurate to the mouse, because I could swear ViewportPointToRay seemed more accurate

1 Like

I’m not saying it isn’t. Both methods are accurate in different situations. I have a sneaking suspicion that the Rope Bridge game got this wrong since rockets go a bit lower than where you aim.

2 Likes

This is the reason this was happening.

game.Players.LocalPlayer:GetMouse().X --Correct

--Describes the X(horizontal) component of the mouse's position on the screen

game.Players.LocalPlayer:GetMouse().Hit.Position.X --Incorrect

--Describes the 3D position of the CFrame

This thread should help everyone who is facing the same or similar issues with this. Thank you so much for the help. I hope you become very successful. You have some incredible coding and problem solving skills my friend :slight_smile:

2 Likes

So, I tested, and it seems ViewportPointToRay is more accurate

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Player = game:GetService("Players").LocalPlayer
local Camera = workspace.CurrentCamera
local raycastParams = RaycastParams.new()
raycastParams.RespectCanCollide = true
raycastParams.FilterType = Enum.RaycastFilterType.Exclude

local template = nil
do
	template = Instance.new("Part")
	template.Material = Enum.Material.Neon
	template.TopSurface = Enum.SurfaceType.Smooth
	template.BottomSurface = Enum.SurfaceType.Smooth
	template.Size = Vector3.one
	template.BrickColor = BrickColor.new("Really red")
	template.Anchored = true
	template.CanCollide = false
	template.CanTouch = false
	template.CanQuery = false
	template.Massless = true
	template.CastShadow = false
	local Light = Instance.new("PointLight")
	Light.Parent = template
	Light.Color = template.Color
	Light.Range = template.Size.Magnitude / 2
	Light.Shadows = true
end

local Clone = nil

RunService:BindToRenderStep("mouseTest",Enum.RenderPriority.Input.Value,function()
	if not (Clone and Clone.Parent == workspace) then
		Clone = template:Clone()
		Clone.Parent = workspace
	end
	local mousePos2D = UserInputService:GetMouseLocation()
	local mouseRay = Camera:ViewportPointToRay(mousePos2D.X,mousePos2D.Y)
	local mousePos3D = nil
	local raycastResult = workspace:Raycast(mouseRay.Origin,mouseRay.Direction * 1000,raycastParams)
	if raycastResult then
		mousePos3D = raycastResult.Position
	else
		mousePos3D = ((mouseRay.Origin + mouseRay.Direction) - mouseRay.Origin).Unit * 1000
	end
	Clone.CFrame = CFrame.new(mousePos3D)
end)

I used this script to basically generate a part and keep it locked to the mouse, here’s the results:

Using ScreenPointToRay, I got:


With ViewportPointToRay, I got:

Overall, for getting the mouse’s exact position in 3d Worldspace, it seems ViewportPointToRay is the most accurate

1 Like

I just fixed my script only to realize that it is still inaccurate. Thank goodness you came in here and helped. Thank you so much my friend.

1 Like

Glad I could be of help (character limit)

It’s still not working. I just put your script into mine and the same thing happens. I believe it is because I’m doing it on fireallclients that no matter what I do there will always be an inaccuracy? I’m so beyond frustrated with this I really thought this was the solution and i’m sure for this purpose it is but for actual bullet raycasting it’s still not detecting it. I really don’t want to have to send my entire weapon system here but if I have to I will because at this point i don’t think i have any other choice

1 Like

First let me just send you a video here so you can see

1 Like