So I have a script that has an NPC head looking at the player when they reach a certain distance. It works nicely, only, if I have the NPC facing one way, the head will look up and down correctly. However, once i rotate it 90 degrees in either a positive or negative direction it breaks. Instead of looking up and down according to the player, the NPC will rotate its head sideways. Example, instead of the eyes following me when i jump, their ear will look up. (Photos for ref).
Issue:
Roated:
Its taking the world CFrame value instead of the local. I just don’t know how to change it. Im a little dense with scripts from time to time.
Script:
local Neck = script.Parent.Neck
local NPC = script.Parent.Parent
function getClosestPlayer ()
local ClosestPlr, ClosestDist = nil, 20
for i, player in pairs(workspace:GetChildren()) do
if player:FindFirstChild("Humanoid") and player ~= NPC then
local distance = (NPC.PrimaryPart.Position - player.PrimaryPart.Position).Magnitude
if distance < ClosestDist then
ClosestPlr = player
ClosestDist = distance
end
end
end
return ClosestPlr
end
local cframe0 = Neck.C0
while true do
local player = getClosestPlayer()
if player then
local isInFront = NPC.PrimaryPart.CFrame:ToObjectSpace(player.PrimaryPart.CFrame).Z < 0
if isInFront then
local unit = - (NPC.PrimaryPart.CFrame.Position - player.PrimaryPart.Position).unit
Neck.C0 = cframe0 * CFrame.new(Vector3.new(0,0,0), unit) * CFrame.Angles(0,-math.rad(NPC.PrimaryPart.Orientation.Y),0)
end
end
wait()
end
local Neck = script.Parent.Neck
local NPC = script.Parent.Parent
function getClosestPlayer ()
local ClosestPlr, ClosestDist = nil, 20
for i, player in pairs(workspace:GetChildren()) do
if player:FindFirstChild("Humanoid") and player ~= NPC then
local distance = (NPC.PrimaryPart.Position - player.PrimaryPart.Position).Magnitude
if distance < ClosestDist then
ClosestPlr = player
ClosestDist = distance
end
end
end
return ClosestPlr
end
local cframe0 = Neck.C0
while true do
local player = getClosestPlayer()
if player then
local isInFront = NPC.PrimaryPart.CFrame:ToObjectSpace(player.PrimaryPart.CFrame).Z < 0
if isInFront then
local unit = - (NPC.PrimaryPart.CFrame.Position - player.PrimaryPart.Position).unit
Neck.C0 = cframe0 * CFrame.new(Vector3.new(0,0,0), unit - Vector3.new(0, unit.Y, 0)) * CFrame.Angles(0,-math.rad(NPC.PrimaryPart.Orientation.Y),0)
end
end
wait()
end
Basically there are two problems with the unit vector. When the NPC rotates, the perspective of his head changes so the target position must be in that perpective. The perspective is obtained from the HumanoidRootPart of the NPC, who is the one who rotates.
The other problem is that the unit vector must not start at the HumanoidRootPart but at the head for the rotation to be correct.
local unit = -(cframe0.Position - NPC.PrimaryPart.CFrame:PointToObjectSpace(player.PrimaryPart.Position)).unit