LookVector to Mouse.Hit not actually consistent with characters looking direction

  1. What do you want to achieve?
    Have my character look towards the direction of the mouse
    image

  2. What is the issue?
    Mouse.Hit produces very erratic results, because it points to the cursor position relative to the camera, not the cursor position relative to the character, and thus an orientation mismatch occurs.

  3. What solutions have you tried so far?
    Not much. Currently, the script sets the y axis of mouse.hit.position to that of the rootparts when in use, but x and z are also affected due to mouse.hit being at potentially different depth.

I also attempted to create a “mouse catcher” part, which creates a large welded part right bellow the character, that would prevent mouse.hit from reaching lower parts, but this still has issues, where any parts of different elevation than just the floor will impact the looking direction in odd looking ways, so this went unused.

Current code:

RunService:BindToRenderStep("UpdateCharacterSprite", Enum.RenderPriority.Character.Value, function(delta)
	if not Humanoid or not Humanoid.Parent then return end
	
	local rootPos, mousePos = RootPart.Position, Mouse.Hit.Position
	mousePos = Vector3.new(mousePos.X, rootPos.Y, mousePos.Z)
	RootPart.CFrame = CFrame.lookAt(rootPos, Vector3.new(mousePos.X, rootPos.Y, mousePos.Z))
	
	local target, pos, normal = workspace:FindPartOnRayWithIgnoreList(Ray.new(RootPart.Position, Vector3.yAxis * -20), {Character})
	ShadowPart.CFrame = CFrame.new(pos, pos + normal) * CFrame.Angles(math.rad(-90), 0, 0)
	
	
	local angle = (RootPart.Orientation.Y - 45) % 360
	local angleIndex, frameIndex = math.floor(angle / 5) + 1, 0
	local flip = angleIndex > 36
	if flip then angleIndex = 72 - angleIndex end; if angleIndex < 1 then angleIndex = 1 end
	
	if Humanoid.MoveDirection ~= Vector3.zero then
		walkTick += delta * 3; if walkTick > 5 then walkTick = 1 end
		frameIndex = WALK_FRAMES[math.floor(walkTick)]
	else walkTick = 1 end
	if inAir then frameIndex = 3 end

	local column = (angleIndex - 1) % ANGLES_PER_ROW
	
	local rSize, rOff =
		Vector2.new(flip and -FRAME_SIZE or FRAME_SIZE, FRAME_SIZE),
		Vector2.new(column * 4 * FRAME_SIZE + frameIndex * FRAME_SIZE + if flip then FRAME_SIZE else 0, math.floor((angleIndex - 1) / ANGLES_PER_ROW) * FRAME_SIZE)
	BottomS.ImageRectSize, TopS.ImageRectSize, ArmsS.ImageRectSize, BottomS.ImageRectOffset, TopS.ImageRectOffset, ArmsS.ImageRectOffset = rSize, rSize, rSize, rOff, rOff, rOff
end)

How could I correct the LookVector to match where the cursor actually is relative to the character?

Try this (you’ll definitely need to adapt it to your own code)

local userInput = game:GetService("UserInputService")
local root = game.Players.LocalPlayer.Character.PrimaryPart
local camera = workspace.CurrentCamera

game:GetService("RunService").RenderStepped:Connect(function()
	
	local mouse = userInput:GetMouseLocation()
	local screenSize = script.Parent.AbsoluteSize
	-- this is parented under a ScreenGUI, possibly replace with whatever Vector2 gives you the screen size
	-- note the ScreenGUI's ScreenInsets property is set to None
	
	local mouseOffset = mouse - (screenSize / 2)
	local focusDistance = (camera.CFrame.Position - camera.Focus.Position).Magnitude
	
	local lookingPoint = camera.CFrame:ToWorldSpace(CFrame.new(mouseOffset.X, -mouseOffset.Y, -focusDistance)).Position
	root.CFrame = CFrame.lookAt(root.Position, Vector3.new(lookingPoint.X, root.Position.Y, lookingPoint.Z))
	
end)

Mouse.Hit is prone to cause problems because of how it interacts with 3D space, so ditching it and doing some minor mouse position math is more favourable.

1 Like

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