So I’m gonna assume your using the lookAt function, in that case all you need too do is change the 2nd argument which is the target, create a new vector3 without the Y position of your character
Usually you would not set the CFrame directly every frame as you will loose physics. Humanoids automatically apply a force to stand upright.
To get around this I recommend using a constraint you want to use the new align orientation constraint. Make sure that it has enough force to rotate the character.
You can use basic trigonometry to solve for the angle that your NPC needs to look. math.atan2(dX,dZ)
Where dX is difference in X axis and dX is difference in Z axis.
you can apply a rotation to a CFrame using CFrame.Angles or CFrame.FromOrientation. You will need to convert to radians if using the former.
SideNote: if you want the very very simple fix you can set the Y value to Humanoid.HipHeight + 1 for the NPC. If you are not on flat ground you can put th Humanoid.RootPart.Position.Y for the Y axis look at.:
Thank you, I appreciate the answer. While I would normally be willing to do the extra work to get optimal results, I actually do need CFrame for this so the simple fix you stated worked beautifully.
Also, just curious, How’d you get the “Composer” label on your account? I see people with tags like that all the time and always wondered how they got 'em.
For information like that in the future you can refer to #forum-help
They are called flairs. To get one simply navigate to your Profile then go to Preferences. Under Account you will see a dropdown for the flairs for all groups that you have joined. If you do not see the option dropdown, you will need to join a group. On mobile you can view and join groups using the hamburger menu button in the top right.