Theres some free models that can do this but if you want to know you can use also you can look at one of the free models scripts place it at npc model and it should work
CFrame.LookAt(NpcPosition,Lookatposition)
local Players = game:GetService("Players")
local LookAtPlayerRange = 25
local PartToLookAt = "Head"
local LookBackOnNil = true
local HeadHorFactor = 1
local HeadVertFactor = 0.7
local BodyHorFactor = 0.6
local BodyVertFactor = 0.6
local UpdateSpeed = 0.3
local UpdateDelay = 0.05
local Ang = CFrame.Angles
local aTan = math.atan
local Body = script.Parent
local Head = Body:WaitForChild("Head")
local Hum = Body:WaitForChild("Humanoid")
local Core = Body:WaitForChild("HumanoidRootPart")
local IsR6 = (Hum.RigType.Value==0)
local Trso = (IsR6 and Body:WaitForChild("Torso")) or Body:WaitForChild("UpperTorso")
local Neck = (IsR6 and Trso:WaitForChild("Neck")) or Head:WaitForChild("Neck")
local Waist = (not IsR6 and Trso:WaitForChild("Waist"))
local NeckOrgnC0 = Neck.C0
local WaistOrgnC0 = (not IsR6 and Waist.C0)
local function getClosestPlayer()
local closest_player, closest_distance = nil, LookAtPlayerRange
for i, player in pairs(workspace:GetChildren()) do
if player:FindFirstChild("Humanoid") and player ~= Body and Players:GetPlayerFromCharacter(player) then
local distance = (Core.Position - player.PrimaryPart.Position).Magnitude
if distance < closest_distance then
closest_player = player
closest_distance = distance
end
end
end
return closest_player
end
local function rWait(n)
n = n or 0.05
local startTime = os.clock()
while os.clock() - startTime < n do
game:GetService("RunService").Heartbeat:Wait()
end
end
local ErrorPart = nil
local function GetValidPartToLookAt(Char, bodypart)
local pHum = Char:FindFirstChild("Humanoid")
if not Char and pHum then return nil end
local pIsR6 = (pHum.RigType.Value==0)
local ValidPart
if bodypart == "Torso" or bodypart == "UpperTorso" then
if pIsR6 then ValidPart = Char:FindFirstChild("Torso") else ValidPart = Char:FindFirstChild("UpperTorso") end
else ValidPart = Char:FindFirstChild(bodypart) end
if ValidPart then return ValidPart else
if ErrorPart ~= bodypart then
warn(Body.Name.." can't find part to look: "..tostring(bodypart))
ErrorPart = bodypart
end
return nil end
end
local function LookAt(NeckC0, WaistC0)
if not IsR6 then
Neck.C0 = Neck.C0:lerp(NeckC0, UpdateSpeed/2)
Waist.C0 = Waist.C0:lerp(WaistC0, UpdateSpeed/2)
else
Neck.C0 = Neck.C0:lerp(NeckC0, UpdateSpeed/2)
end
end
game:GetService("RunService").Heartbeat:Connect(function()
rWait(UpdateDelay)
local TrsoLV = Trso.CFrame.lookVector
local HdPos = Head.CFrame.p
local player = getClosestPlayer()
local LookAtPart
if IsR6 and Neck or Neck and Waist then
if player then
LookAtPart = GetValidPartToLookAt(player, PartToLookAt)
if LookAtPart then
local Dist = nil;
local Diff = nil;
local is_in_front = Core.CFrame:ToObjectSpace(LookAtPart.CFrame).Z < 0
if is_in_front then
Dist = (Head.CFrame.p-LookAtPart.CFrame.p).magnitude
Diff = Head.CFrame.Y-LookAtPart.CFrame.Y
if not IsR6 then
LookAt(NeckOrgnC0*Ang(-(aTan(Diff/Dist)*HeadVertFactor), (((HdPos-LookAtPart.CFrame.p).Unit):Cross(TrsoLV)).Y*HeadHorFactor, 0),
WaistOrgnC0*Ang(-(aTan(Diff/Dist)*BodyVertFactor), (((HdPos-LookAtPart.CFrame.p).Unit):Cross(TrsoLV)).Y*BodyHorFactor, 0))
else
LookAt(NeckOrgnC0*Ang((aTan(Diff/Dist)*HeadVertFactor), 0, (((HdPos-LookAtPart.CFrame.p).Unit):Cross(TrsoLV)).Y*HeadHorFactor))
end
elseif LookBackOnNil then
LookAt(NeckOrgnC0, WaistOrgnC0)
end
end
end
end
end)
1 comment
i can provide gifs if required