NPC Head movement is snappy

Hello!

I have a script from a tutorial that is supposed to make a NPC’s head follow wherever you are. It works, but the way it does is just, weird… It snaps its head to where the player is instead of smoothly turning when it detects a player:

local char = script.Parent
local head = char:WaitForChild("Torso")
local hrp = char:WaitForChild("HumanoidRootPart")
local neck = char.Torso:WaitForChild("Neck")
local xOffSet = neck.C0.X
local yOffSet = neck.C0.Y
local zOffSet = neck.C0.Z

local function getClosestPlayerHrp(dist)
	local closestHrp = nil
	for i,v in ipairs(workspace:GetChildren()) do
		local human = v:FindFirstChild("Humanoid")
		local torso = v:FindFirstChild("Torso") or v:FindFirstChild("HumanoidRootPart")
		if human and torso and v.Name ~= script.Parent.Name then
			local tmpHrp = v:FindFirstChild("Torso") or v:FindFirstChild("HumanoidRootPart")
			local tmpDist = (tmpHrp.Position - hrp.Position).Magnitude      
			if tmpHrp and tmpDist < dist then
				closestHrp = tmpHrp
				dist = tmpDist
			end
		end
	end
	return closestHrp, dist
end

while wait(0) do
	local closestHrp, dist = getClosestPlayerHrp(10) --unit of studs
	if closestHrp then
		local cframe0 = neck.C0
		local dir = (closestHrp.Position - hrp.Position).Unit
		local vecA = Vector2.new(hrp.CFrame.LookVector.X, hrp.CFrame.LookVector.Z)
		local vecB = Vector2.new(dir.X, dir.Z)
		local dotValue = vecB:Dot(vecA)
		local crossValue = vecB:Cross(vecA)
		local ht = hrp.Position.Y - closestHrp.Position.Y
		local upAngle = math.atan(ht/dist)

		local angle = math.atan2(crossValue, dotValue)
		if angle > math.pi/3 then
			angle = math.pi/3
		elseif angle < -math.pi/3 then
			angle = -math.pi/3
		end

		neck.C0 = CFrame.new(neck.C0.Position) * CFrame.Angles(-upAngle, angle, 0) * CFrame.Angles(math.rad(-90), 0, math.rad(-180))
	else
		neck.C0 = CFrame.new(neck.C0.Position) * CFrame.Angles(math.rad(-90), 0, math.rad(-180))
	end
end

Video:

How can I make it so that it doesn’t just snap into place?

1 Like