NPC Head looking Toward player

Im trying to make the NPCs head turn toward the player but it is looking the oposite way of the player?

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)
		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) 
		end
	end
end
1 Like

Your script is very hard to read. I went ahead and made a new version of your script with legible variables. It also works. Here it is:

local char = script.Parent
local npcRoot = char:WaitForChild("HumanoidRootPart")
local npcHead = char:WaitForChild("Head")

local function findClosestPlayerRoot(dist)
	local closestRoot = nil
	for i, player in pairs(game.Players:GetChildren()) do
		local playerChar = player.Character or player.CharacterAdded:Wait()
		local playerRoot = playerChar:FindFirstChild("HumanoidRootPart")
		if playerRoot then
			local newDist = (playerRoot.Position - npcRoot.Position).Magnitude
			if newDist < dist then
				closestRoot = playerRoot
				dist = newDist
			end
		end
	end
	return closestRoot, dist
end

while true do
	wait(0.5)
	local closestRoot, dist = findClosestPlayerRoot(100)
	if closestRoot then
		-- #### all unnecessary, sorry......
		--local direction = (closestRoot.Position - npcRoot.Position).Unit
		--local vecA = Vector2.new(direction.X, direction.Z)
		--local vecB = Vector2.new(npcRoot.CFrame.LookVector.X)
		--local dotProd = vecA:Dot(vecB)
		--local crossProd = vecA:Cross(vecB)
		--local angle = math.atan2(crossProd, dotProd)

		--local height = closestRoot.Position.Y - npcRoot.Position.Y
		--local UpDownAngle = math.atan(height/dist)

		npcHead.CFrame = CFrame.new(npcHead.Position, closestRoot.Position)

		if npcHead.Orientation.Y >= 101 or npcHead.Orientation.Y <= -101 then
			npcHead.Orientation = Vector3.new(0,0,0) 
		end
	end
end

I did minimal changes to the code outside of the variables and a few tweaks. You can see I cut off a big chunk at the bottom. I did that because you went through a very complicated process to find the direction for the head to look at. Honestly, that is probably why your code wasn’t working. Simply too complicated to fix, let alone read.

Thankfully, if you do CFrame.new(), you can do a second parameter to define the position you want to look at. Here is an example:

CFrame.new(pos1,pos2) -- pos1 and pos2 are Vector3 values

Have a nice day. Please take the time to make your code easy to understand, for the sake of yourself and others.

1 Like

Thanks, but the Npcs head is snapping and not moving smoothly like i had it before, and when i move to far to the right of it, it snaps to the other side?

1 Like

P.S. You’ll want to figure out another way to update the head’s position. My recommendation: Don’t do a loop that runs forever. Instead, try running a script on the client that updates the head position whenever the player moves AND is within 100 studs of the NPC. That should get you much better performance.

Also, you got some problems with the npcHead orientation whenever you reset it AND continue the loop (check the code bit at the bottom). I’ll let you solve that one yourself.

1 Like

Yes. I set the the loop to run every 0.5 seconds. Obviously, this is choppy, but all I wanted to demonstrate was that it was working. I recommend you find another way to run the loop besides just setting a wait() since it may cause performance issues.

Also, the head snapping when you move around it is because of the code snippet at the end, specifically this:

if npcHead.Orientation.Y >= 101 or npcHead.Orientation.Y <= -101 then
	npcHead.Orientation = Vector3.new(0,0,0) 
end

This happens because it will continue to update the head’s position, even when you are behind the NPC (because of your forever loop). It also happens because it will keep setting the CFrame of the head towards the player before checking if it will snap its neck. As a result, it snaps its neck over and over. Not very healthy if you ask me. Perhaps only set the position if they are in front, instead of correcting after it is already set?

1 Like

I changed the numbers to 180 and 0 my mistake!

2 Likes

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