Npc refuses to look at player

I’m trying to make it so once the player speaks to an npc the npc would turn their head to look at the player however once this event is triggered the npc would only in one direction and i’m not sure how to fix this issue.

	local rawCF = (CFrame.new(npc.Head.Position,game.Players.LocalPlayer.Character.PrimaryPart.Position):Inverse() * npc.HumanoidRootPart.CFrame ).lookVector * -1
	
	local X_Limitations = math.clamp(rawCF.X, -41, 163)
	local Y_Limitations = math.clamp(rawCF.Y, -41, 163)
	local Z_Limitations = math.clamp(rawCF.Z, -41, 163)
	
	local GoalCF = Vector3.new(X_Limitations, Y_Limitations,Z_Limitations)
	
	game:GetService("TweenService"):Create(npc.Head, TweenInfo.new(0.3), {Orientation = GoalCF}):Play() 

image

8 Likes

Make Y_Limitations negative of what it previously was.

1 Like

Doesn’t seem to change much of anything.

1 Like

Hello buddy! I am here to help you fix your bug! Okay, so firstly, just to let you know, I am a beginner in scripting, so I am not 100% sure. But I will do my best.

Okay, so I remade your script, and I hope it helps!

game.Players.LocalPlayer.Character.TalkedToNpc
script.Parent.Head.CFrame = CFrame.new(game.Players.LocalPlayer.Character.PrimaryPart.CFrame, game.Players.LocalPlayer.Character.Head)
wait(0.1) -- Wait to allow the player time to move out of the way
npc.Head.CFrame = game.Players.LocalPlayer.Character.Head.CFrame
wait(0.5) -- Wait for the NPC to turn around
npc.HumanoidRootPart.CFrame = Vector3.Lerp(npc.HumanoidRootPart.CFrame, Vector3.new(game.Players.LocalPlayer.Character.Head.CFrame.X, y, game.Players.LocalPlayer.Character.Head.CFrame.z), 0.5)

I hope it helps! If it does, make sure to mark my comment as solution :white_check_mark:

3 Likes

I don’t think the issue lays in the limitations but the calculation of rawCF itself, can you try something like, really haven’t tested this myself in studio but can you try:

local rawCF = CFrame.lookAt(npc.Head.Position, game.Players.LocalPlayer.Character.PrimaryPart.Position)

He seems to just look the same angle but just upwards more. I’ll try moving around the limitations to see if that might have something to do with this.
image

1 Like

Did my re-written script work? I am a newbie in scripting, and I just wanted to help.

It does work but it isn’t what I’m trying to achieve.

I am sorry, I understood it wrong! :sad:
What effect are you trying to achieve?

Something like this where the npc turns their head to the player.
image

Oooooh now I think I got it! Okay so I made a small script that smoothly rotates the NPC’s head. Try it and let me know! :cool:

local tweenService = game.ReplicatedStorage.TweenService.new()
local tween = tweenService:Create(game.Workspace.Head, TweenInfo.new(1, en.EaseOutQuad), {CFrame=CFrame.Angles(math.rad(180), 0, 0)})

I hope it helps! If it does, make sure to mark my comment as solution :white_check_mark:

local DesiredCF = CFrame.new(NPCHead.Position, PlayerHead.Position)

local Info = TweenInfo.New(Time, Direction, Style)
local Tween = TweenService:Create(NPCHead, Info, {
[“CFrame”] = DesiredCF })

Tween:Play()

Wrote on mobile, have not tested. If you want to clamp Y axis replace PlayerHead.Position with Vector3.new(PlayerHead.Position.X, NPCHead.Position.Y, PlayerHead.Position.Z)

1 Like

This has some work to do, so lets start from the beginning. You can use the CFrame value directly to tween the head and do not have to convert it into an Orientation.

Your code to find rawCF is wonky, and ill go over it.

local rawCF = (CFrame.new(npc.Head.Position,game.Players.LocalPlayer.Character.PrimaryPart.Position):Inverse() * npc.HumanoidRootPart.CFrame ).lookVector * -1

It finds the CFrame.LookAt between the npc’s head and the players HumanoidRootPart, then Inverses it (converts all positive numbers negative and all negative numbers positive in the CFrame), adds an offset to that, and then grabs a directional vector.


Instead, you can cut down almost all of it into a single CFrame

local rawCF = CFrame.new(npc.Head.Position, game.Players.LocalPlayer.Character.Head.Position)

This CFrame is the same constructor as CFrame.LookAt, which as the name might apply, transforms one CFrame to look at another. It also comes with a 3rd parameter that describes the UpVector, but thats defaulted to (0,1,0) which works in this case. It returns a CFrame that is rotated to look at the goal


then to add limits, you can use Vector3.new:Angle() to find an angle between the Original LookVector, and the one that it wants to go to.

local GoalCF = CFrame.new() 
if Angle < DesiredAngle then
   GoalCF = rawCF
else
   GoalCF = npc.Head.CFrame--if it limits, then dont move the head
end

That does mean that the head travels in a cone instead of a limited x and y angle, but if you need a limited x and y Orientation, you can always convert a CFrame’s Rotation into Orientation using:

local x,y,z = CFrame.new:ToOrientation() --descibes the x,y,z angles that make up the rotation in radians.

so some psuedo code to put it all together goes like this:

--varibles
local MaxAngle = 45
local OrigonalCFrame = npc.Head.CFrame

--calculation
local rawCF = CFrame.new(npc.Head.Position, game.Players.LocalPlayer.Character.Head.Position)

local GoalCF = CFrame.new() 
local Angle = OrigonalCFrame.LookVector:Angle(rawCF.LookVector)

if Angle < math.deg(Angle) then
   GoalCF = rawCF
else
   GoalCF = npc.Head.CFrame--if it limits, then dont move the head
end

game:GetService("TweenService"):Create(npc.Head, TweenInfo.new(0.3), {CFrame = GoalCF}):Play()

Sorry its sloppy, I wrote this in a rush. Hope this helps!:grin:

1 Like

Is the front face correct? Just seems that if nothing is working and it always points the wrong way even when simple, but maybe it’s actually working and the face is wrong.

Yup, I love the solution. I wanted to add that some added constraints would have to be added to my solution but yours is well detailed and perfectly written.

1 Like

Yes, It doesn’t matter where i stand.

Ive seen youve used Orientation in the script, but I’ve never actually seen you convert the CFrame to Orientation.

I didnt see you Use Motor6D.C1 or C0
so you can replace the first like with

local rawCF=Vector3.new(CFrame.new(npc.Head.Position,game.Players.LocalPlayer.Character.Head.Position):ToOrientation())

Edit:

[quote="HP5C, post:1, topic:2443555, username:HP5C"]

(npc.Head.Position,game.Players.LocalPlayer.Character.PrimaryPart.Position):Inverse() * npc.HumanoidRootPart.CFrame ).lookVector * -1

local X_Limitations = math.clamp(rawCF.X, -41, 163)
local Y_Limitations = math.clamp(rawCF.Y, -41, 163)
local Z_Limitations = math.clamp(rawCF.Z, -41, 163)
[/quote]


I forgot to mention but on this part You may have to apply math.rad() to each of the arguments. because Orientation is in radiants instead of the degrees.
1 Like

:ToOrientation() outputs a singular number i’ve already tried it.

This does work however whenever the head’s or anything under the npc’s cframe changes it moves the entire model. I think if i edit it a little i might get it to work how its supposed to.

It actually returns 3 numbers, which you have to make 3 variables to catch