Making NPC's head face player correctly no matter their rotation/orientation

YRiNDOVMbt
As you can see, I want the NPC’s neck to rotate so their head is facing the player character. The gif above is how its supposed to look. Now, this works, except when I rotate the entire NPC. When I rotate the NPC, this happens:

yHmKiE18R8
This function works when the NPC is facing a certain way, but if you rotate the NPC it doesn’t take it to account and doesn’t work as intended. I’m not very good at math or cframes so I have no idea the solution to this.

Here is the script.

local CameraDirection = CFrame.new(NPC.PrimaryPart.Position,PlayerCharacter.PrimaryPart.Position).lookVector
local Neck = self.Model:FindFirstChild("Neck", true)
local YOffset = Neck.C0.Y

local Goal = CFrame.new(0, YOffset, 0) * CFrame.Angles(0, -math.asin(CameraDirection.x), 0) * CFrame.Angles(math.asin(CameraDirection.y), 0, 0)

local tweenInfo = TweenInfo.new(.2,Enum.EasingStyle.Quad,Enum.EasingDirection.Out)
local Tween = TweenService:Create(Neck, tweenInfo, {C0 = Goal})
Tween:Play()
15 Likes

I found the solution after a few hours of GRUELING pain

local CameraDirection = (CFrame.new(self.hrp.Position,self.PC.PrimaryPart.Position):inverse() * self.hrp.CFrame ).lookVector * -1
31 Likes

YOU ARE SUCH A GOD!!!

Thank you wish, u help me after 3 days of slamming my head into CFrame.Angles

6 Likes

Holy crap thank you so much… been banging my massive forehead into my desk for days

2 Likes

Wow bandi learning programming yay.

1 Like

When I use the Goal variable in your original post with this CameraDirection it doesn’t work. Did you change the Goal variable aswell?

4 Likes

super late here’s what i personally did for anyone thats still looking, the logic’s a bit different but i messed around and made it work

(also it’s in typescript but the logic should be the same)

RunService.RenderStepped.Connect(() => {
			const cameraDirection = new CFrame(charHRP.Position, playerCharacter.PrimaryPart!.Position)
				.Inverse()
				.mul(charHRP.CFrame)
				.LookVector.mul(1);
			const Yoffset = Neck.C0.Y;

			const goal = new CFrame(0, Yoffset, 0)
				.mul(CFrame.Angles(0, math.asin(cameraDirection.X), 0))
				.mul(CFrame.Angles(math.asin(cameraDirection.Y), 0, 0))
				.mul(CFrame.Angles(math.rad(-90), 0, math.rad(180)));

			const tweenInfo = new TweenInfo(0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out);
			const tween = TweenService.Create(Neck, tweenInfo, { C0: goal });
			tween.Play();
		});

1 Like