NPC head follows the player

Hello everyone, I created an NPC and I want his head to follow the player at a certain distance(I tried to find how to do this, but either these options were outdated or they were not the same at all.). And I don’t know how to do it. I will be very grateful for your help!

9 Likes

I have a script saved up (from some video I watched), it should also work for your npc if you change some things

local char = script.Parent
local hrp = char:WaitForChild("HumanoidRootPart")
local head = char:WaitForChild("Head")
local neck = head:WaitForChild("Neck")

local function findClosestsPlayerHrp(dist)
	local closestHrp = nil
	for i, v in pairs(game.Players:GetChildren()) do
		local tChar = v.Character or v.CharacterAdded:Wait()
		local tHrp = tChar:FindFirstChild("HumanoidRootPart")
		if tHrp then
			local tmpDist = (tHrp.Position - hrp.Position).Magnitude
			if tmpDist < dist then
				closestHrp = tHrp
				dist = tmpDist
			end
		end
	end
	return closestHrp, dist
end

while wait() do
	local closestHrp, dist = findClosestsPlayerHrp(100)
	if closestHrp then
		local dir = (closestHrp.Position - hrp.Position).Unit
		local vecA = Vector2.new(dir.X, dir.Z)
		local vecB = Vector2.new(hrp.CFrame.LookVector.X, hrp.CFrame.LookVector.Z)
		local dotProd = vecA:Dot(vecB)
		local crossProd = vecA:Cross(vecB)
		local angle = math.atan2(crossProd, dotProd)
		
		local ht = closestHrp.Position.Y - hrp.Position.Y
		local UpDwnAngle = math.atan(ht/dist)
		
		neck.C0 = CFrame.new(neck.C0.Position) * CFrame.Angles(0, angle, 0)
			* CFrame.Angles(UpDwnAngle, 0, 0)
	end
end
5 Likes

O, it’s you again, good to see you. Infinite yield possible on ‘Workspace.Mark.Head:WaitForChild(“Neck”)’ writes this warning

2 Likes

Is your NPC a R6 or R15 Character? (Using the Roblox Rig Builder)

1 Like

I can’t send a short message. And my NPC in R6

1 Like

Oh that’s because R6 Rigs don’t contain the Neck Motor6d, you either change it to a R15 Character or you could try add a Motor6D to the Head and make Part0 be the torso and Part1 the Head

That’s the properties of R15:
image

1 Like

what should it look like in the script?

1 Like

Nevermind, it doesn’t really work on a R6 Character, I recommend you to use R15. I will experience it to make it possible for R6, but just for now make the character R15

2 Likes

By the way, I have a script for moving the character’s head depending on the camera. I have a game in R6 and this script works:

local mouse = plr:GetMouse()

local char = plr.Character or plr.CharacterAdded:wait()
local hum = char:WaitForChild("Humanoid")
local isR6 = hum.RigType == Enum.HumanoidRigType.R6
local head = char:WaitForChild("Head")
local root = char.HumanoidRootPart
local torso = isR6 and char.Torso or char.UpperTorso
local neck = isR6 and torso.Neck or head.Neck
local waist = not isR6 and torso.Waist

local neckC0 = neck.C0
local waistC0 = not isR6 and waist.C0

neck.MaxVelocity = 1/3

runService.RenderStepped:Connect(function ()

	if torso and head and ((isR6 and neck) or (neck and waist)) and cam.CameraSubject == hum then

		local camCF = cam.CFrame
		local headCF = head.CFrame

		local torsoLV = torso.CFrame.lookVector

		local dist = (headCF.p - camCF.p).magnitude
		local diff = headCF.Y - camCF.Y

		local asinDiffDist = math.asin(diff / dist)
		local whateverThisDoes = ((headCF.p - camCF.p).Unit:Cross(torsoLV)).Y

		if isR6 then
			neck.C0 = neck.C0:lerp(neckC0 * CFrame.Angles(-1 * asinDiffDist * headVerFactor, 0, -1 * whateverThisDoes * headHorFactor), updateSpeed)
		else
			neck.C0 = neck.C0:lerp(neckC0 * CFrame.Angles(asinDiffDist * headVerFactor, -1 * whateverThisDoes * headHorFactor, 0), updateSpeed)
			waist.C0 = waist.C0:lerp(waistC0 * CFrame.Angles(asinDiffDist * bodyVerFactor, -1 * whateverThisDoes * bodyHorFactor, 0), updateSpeed)
		end

	end
end)
3 Likes

I think this should be ok? No Motor 6d is needed and should be compatible with R6

local char = script.Parent
local hrp = char:WaitForChild("HumanoidRootPart")
local head = char:WaitForChild("Head")

local function findClosestsPlayerHrp(dist)
	local closestHrp = nil
	for i, v in pairs(game.Players:GetChildren()) do
		local tChar = v.Character or v.CharacterAdded:Wait()
		local tHrp = tChar:FindFirstChild("HumanoidRootPart")
		if tHrp then
			local tmpDist = (tHrp.Position - hrp.Position).Magnitude
			if tmpDist < dist then
				closestHrp = tHrp
				dist = tmpDist
			end
		end
	end
	return closestHrp, dist
end

while wait() do
	local closestHrp, dist = findClosestsPlayerHrp(100)
	if closestHrp then
		local dir = (closestHrp.Position - hrp.Position).Unit
		local vecA = Vector2.new(dir.X, dir.Z)
		local vecB = Vector2.new(hrp.CFrame.LookVector.X, hrp.CFrame.LookVector.Z)
		local dotProd = vecA:Dot(vecB)
		local crossProd = vecA:Cross(vecB)
		local angle = math.atan2(crossProd, dotProd)
		
		local ht = closestHrp.Position.Y - hrp.Position.Y
		local UpDwnAngle = math.atan(ht/dist)
		
		head.CFrame = CFrame.new(head.Position) * CFrame.Angles(0, angle, 0)
			* CFrame.Angles(UpDwnAngle, 0, 0)
		
		if head.Orientation.Y >= 101 or head.Orientation.Y <= -101 then
			head.Orientation = Vector3.new(0,0,0) -- this returns to the front, so it doesn't turn 360°
		end
	end
end
3 Likes

Sorry for the late answer. I couldn’t insert the video due to an error, but I can explain. The NPC’s body twitches very much, so he goes somewhere (He has animation if anything)

Could you upload the model and send it into here? So I can investigate it

Sorry for the stupid question, but how to export a model to rbxm format? Otherwise, the model is exported in obj format

You could send the model via the roblox page.
image
image
That link, paste that over here
image

1 Like

Wait no I am stupid, uhm basically do this that how you can do .rbxm


And just make a name and paste it onto here
image

Sorry for the confusion

It’s OK. Keep the file:

Mark.rbxm (30 KB)

So you said you made an animation for the guy, right?

That’s right. I made this animation.

If you have any type of Head movement, it always tries to continue the animation but since the script is running it twitches weirdly. I suggest you go into animation editor and remove all head keyframes and insert the new animation. Hopefully this helps!