Make a Part face towards another using Angles

I’m trying to make a part located at the Green Sphere (an attachment), face towards the White Sphere (a Part) using 3 angles.
What I currently have

Yes, I’m aware I could do

Part.CFrame = CFrame.New(GreenSphere.WorldPosition, WhiteSphere.Position)

but I want to be able to clamp the angles, which I wouldn’t know how to do using that method.

I also tried simply applying all the angles like so

Part.CFrame = GreenSphere.WorldCFrame * CFrame.Angles(AngleX, AngleY, AngleZ)

But this doesn’t behave in the way I intend it to.

Do you have a video/screenshot of the issue?

Nevermind, I see you do have one

Using the angle method works for me, the green attachment might be already rotated which would throw it off

Try:

Part.CFrame = CFrame.new(GreenSphere.WorldPosition) * CFrame.Angles(AngleX, AngleY, AngleZ)

You can use CFrame:ToOrientation() then clamp the angles in orientation form which I have done in my turret controller to reconstruct the CFrame with the newer clamped angles.

Also are you angles in orientation terms or eulerangles XYz terms the order of operations the angles are applied is a big deal and a commong problem on #help-and-feedback:scripting-support

Unfortunately I need everything to be relative to the attachments rotation, for example, AngleY will Yaw a part towards the White Sphere when applied like this:

Part.CFrame = GreenSphere.WorldCFrame * CFrame.Angles(0, AngleY, 0)

If I only use the Green Sphere’s position, it will no longer be relative. The problem I’m having is when I apply each angle by them selves, it works as intended:

Part.CFrame = GreenSphere.WorldCFrame * CFrame.Angles(0, 0, AngleZ)

Will pitch a part towards the White Sphere.

Part.CFrame = GreenSphere.WorldCFrame * CFrame.Angles(AngleX, 0, 0)

Will roll a part towards the White Sphere.
But everything gets funky when all are applied together.

You would want to generate a CFrame relative to the attachment then
You could probably just take the lookat CFrame and multiply that by the inverse of the world CFrame of the attachment

So

local x,y,z = (attachment.WorldCFrame:Inverse()*CFrame.new(attachment.WorldPosition,lookPosition)):ToEulerAnglesXYZ()
thing.CFrame = attachment.WorldCFrame*CFrame.Angles(x,y,z)

Clamp which angles, and how much?

Do you want to clamp within a cone?

What is this for?

Edit: you might find this helpful, it’s a similar problem applied to the shoulder joint.

1 Like

So I tried to implement the solution to a similar problem and I not sure if I did it correctly, but it turns out like this:


	local TestOffset = SocketAttachment.WorldCFrame:PointToObjectSpace(LastPositionPart.Position)
	
	local TestYaw = math.atan2(-TestOffset.Z, TestOffset.X)
	local TestPitch = math.atan(TestOffset.Unit.Y)
	
	BallAttachment.WorldCFrame = SocketAttachment.WorldCFrame * CFrame.Angles(0, 0, TestPitch) * CFrame.Angles(0, TestYaw, 0)
	AngleDebugMain.CFrame = BallAttachment.WorldCFrame * CFrame.new(AngleDebugMain.Size.X/2, 0, 0)

I couldn’t find a word for it at the time but

Do you want to clamp within a cone?

is exactly what I’m trying to do. The cone would be relative to the position and rotation of the green attachment, sort of like a socket constraint.


You are using an angles solution? I dislike angles as they have weird behavior like orientation goes from 180 to -180 which causes those bugs.

Also what you are doing looks like inverse kinematics. Check it out, even if it’s not related it’s got cool CFrame tricks there which might help.

I have already implemented ballsocket constraints:

Ballsocket constraint related part
	local centerAxis = axisAttachment.WorldAxis
	local currentCenterAxis = jointAttachment.WorldAxis
	local angleDifference = VectorUtil.AngleBetween(currentCenterAxis, centerAxis)

	local constraintUpperAngle = math.rad(jointConstraintInfo.UpperAngle) or math.rad(45)

	--out of bounds constrain it to world axis of the socket
	if angleDifference > constraintUpperAngle then
		local axis = currentCenterAxis:Cross(centerAxis)
		local angleDifference = angleDifference - constraintUpperAngle
		local newCenterAxisWithinBounds = rotateVectorAround(currentCenterAxis, angleDifference, axis)
		self.rotateJointFromTo(motor6d, currentCenterAxis, newCenterAxisWithinBounds, part0CF.RightVector)
	end

If I can use BallSocketConstraints to set the limits, this would be what I’m looking for.