Using a character's Neck Motor6D to point it's Head at an object

I’m currently in the process of developing ‘laser eyes’. When activated, the player’s head should point at the target part (where the player clicks). To achieve this, I do:

local neckPos = neck.C0.p
local targetPos = laserTarget.Position
local lookCFrame = CFrame.new(neckPos, Vector3.new(targetPos.X, neckPos.Y, targetPos.Z))
neck.C0 = lookCFrame

image

When static, this works correctly:

However as soon as you start moving, the system falls apart:

Any idea why this happens and how the problem can be overcome?

4 Likes

The best way would arguably be to disable the Neck motor and use a constraint of some form, imho. (likely a HingeConstraint, if you want it to look like that) Right now, what you’re doing is conflicting with the Humanoid’s animation, and the Humanoid/AnimationController always ‘wins’.

I don’t think animations ‘fight’ for the motor, they seem to actually play based on the motor’s C0/C1.

Head bobbing from animation played while looking sideways
Longer video

What I believe your problem is that Neck.C0.p will always be (0, 0.8, 0), or at least really really close due to float precision. From this, the CFrame you make using the two vector constructor is always pointing from (0, 0.8, 0), towards laserTarget.Position, all in worldspace. The videos you posted seem to agree since the farther from spawn you moved, the less your head turned towards the mouse. Try:

local dir = (targetPos - Head.Position).Unit
local lookCFrame = CFrame.new(Vector3.new(), Character.PrimaryPart.CFrame:VectorToObjectSpace(dir))

Edit: I apparently didn’t know neck.C0 is actually (0, 0.8, 0)
Edit2: worldspace
Edit3: objectspace

9 Likes

Thanks, I’ve just tested and that does appear to be the problem!

For any future viewers, I’ve adapted the code slightly to prevent the head bobbing down:

local yDifference =  (head.CFrame.Y - neck.C0.Y)/4.5
local direction = (Vector3.new(targetPos.X, headPos.Y, targetPos.Z) - head.Position).Unit
local lookCFrame = CFrame.new(Vector3.new(), head.Parent.PrimaryPart.CFrame:VectorToObjectSpace(direction))
neck.C0 = lookCFrame * CFrame.new(0,yDifference,0)
4 Likes