Rotating Character towards mouse but not choppy

My goal is to have the character look at the mouse smoothly and consistently

the issue is that if a player hovers over different objects the rotation can get choppy

local RunService = game:GetService("RunService")

local player = game.Players.LocalPlayer
local character = script.Parent
local primary = character.PrimaryPart
local mouse = player:GetMouse()
mouse.TargetFilter = character

local bodyGyro = Instance.new("BodyGyro")
bodyGyro.Parent = primary
bodyGyro.D = 40
bodyGyro.P = 10000
bodyGyro.MaxTorque = Vector3.new(4000000, 4000000, 4000000)

while true do
	
	local mousePos = mouse.Hit.Position
	local primaryPos = primary.Position
		
	local lookatPos = Vector3.new(mousePos.X, primaryPos.Y, mousePos.Z)
	bodyGyro.CFrame = CFrame.new(primaryPos, lookatPos)
	
	RunService.Heartbeat:Wait()
	
end

I know a solution to this is to make a new ray and have an ignore list, but I’d rather not have to add things to a list every time I update the map, or update a whitelist if I go that route

is there a way to do this without mouse.Hit, or a way to make mouse.Hit work properly without a ignore/whitelist?

9 Likes

Reduce bodyGyro.P

This determines how aggressively the player tries to rotate.

2 Likes

the issue still exists, it just turns slower

1 Like

You want to ignore players entirely?

1 Like

I really want to ignore everything and just have the character look towards the direction of the mouse and not towards parts

1 Like

The reason for the snap is that you are relying on mouse.Hit.Position which will ‘snap’ when your mouse hovers over different parts.

1 Like

Here is your solution:
Calculate a 3D ray from 2D camera origin and mouse position. With your mouse ray, calculate the ray-plane intersection from the plane formed by the characters y-position. Just give a normal going straight up if the character is assumed to always be standing upright. Use the plane intersection position as the ‘looking’ direction.

https://jody.jp/pics/images/webm/DacM3r9.webm

Here is your code:

local Camera = workspace.CurrentCamera
local Player = game:GetService("Players").LocalPlayer
local Mouse = Player:GetMouse()
local RunService = game:GetService("RunService")

wait(0.5)

local player = game.Players.LocalPlayer
local character = player.Character
local primary = character.PrimaryPart

local bodyGyro = Instance.new("BodyGyro")
bodyGyro.Parent = primary
bodyGyro.D = 40
bodyGyro.P = 10000
bodyGyro.MaxTorque = Vector3.new(4000000, 4000000, 4000000)

local function rayPlane(planepoint, planenormal, origin, direction)
	return -((origin-planepoint):Dot(planenormal))/(direction:Dot(planenormal))
end

while true do
	local ray = Camera:ScreenPointToRay(Mouse.X, Mouse.Y)
	local t = rayPlane(Player.Character.Head.Position, Vector3.new(0, 1, 0), ray.Origin, ray.Direction)
	
	local primaryPos = primary.Position
		
	local plane_intersection_point = (ray.Direction * t) + ray.Origin
	bodyGyro.CFrame = CFrame.new(primaryPos, plane_intersection_point)
	
	RunService.Heartbeat:Wait()
	
end
29 Likes

exactly what I needed thanks a lot, works like a charm :wink:

to anyone looking at the post for the same issue, if you want the character to only look towards the x and z position you can do

bodyGyro.CFrame = CFrame.new(primaryPos, Vector3.new(plane_intersection_point.X, primaryPos.Y, plane_intersection_point.Z))
5 Likes

Sorry to bump this post but after trying your code out I noticed that if I aim in the sky or somewhere very far away my character looks in the opposite direction. Any idea why?

2 Likes

how would I format the script in order to add that?

1 Like
local Camera = workspace.CurrentCamera
local Player = game:GetService("Players").LocalPlayer
local Mouse = Player:GetMouse()
local RunService = game:GetService("RunService")

wait(0.5)

local player = game.Players.LocalPlayer
local character = player.Character
local primary = character.PrimaryPart

local bodyGyro = Instance.new("BodyGyro")
bodyGyro.Parent = primary
bodyGyro.D = 40
bodyGyro.P = 10000
bodyGyro.MaxTorque = Vector3.new(4000000, 4000000, 4000000)

local function rayPlane(planepoint, planenormal, origin, direction)
	return -((origin-planepoint):Dot(planenormal))/(direction:Dot(planenormal))
end

while true do
	local ray = Camera:ScreenPointToRay(Mouse.X, Mouse.Y)
	local t = rayPlane(Player.Character.Head.Position, Vector3.new(0, 1, 0), ray.Origin, ray.Direction)
	
	local primaryPos = primary.Position
		
	local plane_intersection_point = (ray.Direction * t) + ray.Origin
	bodyGyro.CFrame = CFrame.new(primaryPos, Vector3.new(plane_intersection_point.X, primaryPos.Y, plane_intersection_point.Z))
	
	RunService.Heartbeat:Wait()
	
end

I think this was it, but it’s been a long time so I don’t remember clearly

and @Paintertable sorry for the late response, I do not sorry
@jody7777 wrote that bit of code, so if you still need help they would be one the to ask

7 Likes

is this code for the “x” and “z” axis only?, because thats all I want

5 Likes