What do you want to achieve? Keep it simple and clear!
I need to highlight an object for a character customizer (just working on the highlighting at the moment)
What is the issue? Include screenshots / videos if possible!
pretty simply, ive got it to set a highlight based on what the mouse is pointing at but there is a major offset that seems?? to change when the camera rotates
What solutions have you tried so far? Did you look for solutions on the Creator Hub?
changed how it sees what the mouse is pointing at (currently using raycast- it doesnt look like the offset changes depending on what method i use though)
RunService.Heartbeat:Connect(function(delta)
local mousePosition = UserInputService:GetMouseLocation()
local mouseX = mousePosition.X
local mouseY = mousePosition.Y
local ray = camera:ViewportPointToRay(mouseX, mouseY)
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {}
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.IgnoreWater = true
local result = Workspace:Raycast(ray.Origin, ray.Direction * 1000, raycastParams)
if result and result.Instance then
local target = result.Instance
if target:GetAttribute("IsItem") == true then
highlight.Adornee = target
else
highlight.Adornee = nil
end
else
highlight.Adornee = nil
end
end)
above is my code (not including the basic defining parts- if those need to be included as well do tell me) and im honestly at a loss for where to go from here
Well, I just slightly changed your script to target any part and added the variables I needed to get your code to work and I’m getting no offset at all. Works perfectly. (my only real change to your logic was instead of checking “IsItem” I just check if target then
The only thing I can think of (which seems super unlikely) is if you somehow have the wrong camera, or if you somehow overwrite the highlight elsewhere. The change I made should have no effect on the script.
hm. actually. would this potentially be because of the things im highlighting being meshes? with how offset it is i dont think its likely but it just came to mind
It may be. I think raycasting uses the collision shape, and collision shapes often are wrong because it’s expensive to match a mesh, so you have to change the collision mesh to the precise mode otherwise it may actually just be a box.
The problem is the ray-to-mouse highlight is offset and shifts with the camera rotation
You are building the ray with raw GetMouseLocation pixels, but that includes the GUI inset, (top bar) so the ray isn;'t actually aligned to the 3D view, when the camera moves the mismatch looks like a drifting/rotating offset
Here’s how to fix it, pretty simple:
use camera:ScreenPointToRay(x, y) (it handles insets).
or ubtract the inset before ViewportPointToRay
So:
local p = UserInputService:GetMouseLocation() - game:GetService("GuiService"):GetGuiInset()
local ray = workspace.CurrentCamera:ViewportPointToRay(p.X, p.Y)
Update on the RENderStopped frame, not the Heartbeat, set the highlight.Adornee to a BASEPART or a FindFirstAncestorWhichIsA(“MOdel”) if you want the whole model
Also, blacklist LocalPlayer.Character and UI/FX parts to avoid any false hits, that’ll hopefully remove the offset
It shouldn’t be. GetMouseLocation() doesn’t take the inset into account, but niether does :ViewportPointToRay() so it should cancel out. Also it worked perfectly on my system when I tested it.
neither of those ended up workign unfortunately. only other thing i can think of is that the player is a bit off from everything i need to highlight due to how ive got it set up, would that mess with it?
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
local UserInputService = game:GetService("UserInputService")
local highlight = game:GetService("ReplicatedStorage"):WaitForChild("Highlight")
local camera = Workspace.CurrentCamera
RunService.Heartbeat:Connect(function(delta)
local mousePosition = UserInputService:GetMouseLocation()
local mouseX = mousePosition.X
local mouseY = mousePosition.Y
local p = UserInputService:GetMouseLocation() - game:GetService("GuiService"):GetGuiInset()
local ray = workspace.CurrentCamera:ViewportPointToRay(p.X, p.Y)
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {}
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.IgnoreWater = true
local result = Workspace:Raycast(ray.Origin, ray.Direction * 1000, raycastParams)
if result and result.Instance then
local target = result.Instance
if target then
highlight.Adornee = target
else
highlight.Adornee = nil
end
else
highlight.Adornee = nil
end
end)
Huh. I guess that’s probably not going to really change much. Honestly the only thing I can think of is if you are changing the camera at some point (never even tried changing the current camera myself). If you do change the camera to another instance though it won’t update the camera since you set it once out of the loop.
local RS = game:GetService("RunService")
local UIS = game:GetService("UserInputService")
local GS = game:GetService("GuiService")
local cam = workspace.CurrentCamera
local player = game.Players.LocalPlayer
-- one Highlight in Workspace
local hl = (workspace:FindFirstChild("DebugHighlight") or Instance.new("Highlight"))
hl.Name = "DebugHighlight"
hl.DepthMode = Enum.HighlightDepthMode.AlwaysOnTop
hl.Parent = workspace
-- tiny red debug dot
local dot = (workspace:FindFirstChild("RayDot") or Instance.new("Part"))
dot.Name, dot.Anchored, dot.CanCollide, dot.Size, dot.Color, dot.Material =
"RayDot", true, false, Vector3.new(0.2,0.2,0.2), Color3.new(1,0,0), Enum.Material.Neon
dot.Parent = workspace
RS.RenderStepped:Connect(function()
local p = UIS:GetMouseLocation() - GS:GetGuiInset() -- viewport coords
local ray = cam:ViewportPointToRay(p.X, p.Y) -- or use ScreenPointToRay with NO inset
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Blacklist
params.FilterDescendantsInstances = {player.Character, hl} -- avoid self hits
local res = workspace:Raycast(ray.Origin, ray.Direction * 2000, params)
if not res then hl.Adornee = nil return end
dot.CFrame = CFrame.new(res.Position)
hl.Adornee = res.Instance -- EXACT part hit
end)
Try this, if the red dot is where the cursor hits but the white outline is offset, it’s a adorneee pivot issue
So try hl.Adornee = res.Instance only (no parent model)
If you need the whole model, fix pivots first:model:PivotTo(model:GetPivot()), or highlight a dedicated hitbox part.
Now, if the red dot itself is off it is a camera/ mouse timing, do you have a custom camera?
And what comes to my head:
Parent the highlight to workspace, not left in RS
Racast blacklist includes FX/UI and the player
Skinned meshes can have weird bounds, so just highlight a simple part when possible
well, this is enlightening at the least. i do not have a custom camera, unless you mean changing the camera subject / having the camera type be custom (although the image is with the camera simply set to orbital with a different focus than the player)
ok so yeah since the red dot itself is offet, that means its a ray build issue, not the actual highlight, with a orbital camera, use screen cords, not the viewport, try this exact swap:
RS.RenderStepped:Connect(function()
local cam = workspace.CurrentCamera
local p = UIS:GetMouseLocation() -- NO inset subtraction
local ray = cam:ScreenPointToRay(p.X, p.Y) -- ScreenPointToRay handles insets
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Blacklist
params.FilterDescendantsInstances = {player.Character}
local res = workspace:Raycast(ray.Origin, ray.Direction*2000, params)
dot.CFrame = res and CFrame.new(res.Position) or dot.CFrame
hl.Adornee = res and res.Instance or nil
end)
and, if it still drifts do a baseline check using th eengine picker:
local m = player:GetMouse()
RS.RenderStepped:Connect(function()
if m.Target then
dot.CFrame = CFrame.new(m.Hit.Position) -- should sit under cursor
end
end)
Now:
If GetMouse().Hit is correct but the ray isn’t that means it’s a camera/coord math error, keep the ScreenPointToRay and do not subtract the inset
If GetMouse().Hit is also offset, something is intercepting, bad, like a mouse locked center, a customer cursor scaling, or some sort of UI/ViewportFrame overaly, also make sure the Hightlight is parented to the Workspace and again very important blacklist your character and any FX parts
just to double check- if the ray isnt working correctly is there anything im supposed to be changing? its a little late im having truble understanding mb
So:
If the ray itself isnt lining up (red dot from earlier is off) you only need to change one thing in the code:
swap ViewportPointToRay for ScreenPointToRay and remove the inset subtraction.
That fixes the offset caused by camera types like Orbital.
Here:
local p = UserInputService:GetMouseLocation()
local ray = camera:ScreenPointToRay(p.X, p.Y)
And if that still doesnt work try this:
local mouse = game.Players.LocalPlayer:GetMouse()
print(mouse.Hit.Position)
If that hit matches where youre pointing, the problem isnt the ray anymore its something else, but most of the time, so 90%, switching to ScreenPointToRay solves it, so just pray that it’s the first