An easier way to use AlignOrientation

Since BodyGyro was deprecated a year or two ago, I have seen many posts about people trying to use AlignOrientation having trouble.

A much popular and suggested way is to create an invisible part, position it around the character to where the alignorientation turns toward it using two attachments, apply attachment0 to the primary part and attachment1 to the invisible part, and the invisible part is placed so the primarypart turns to where it looks toward your target. Sometimes finding the correct accurate location can be a bit harder for newer scripters, and so I will share an easier way to use AlignOrientation.

For people who haven’t heard of AlignOrientation, it is a constraint that has replaces BodyGyro, after BodyGyro was deprecated. Keep in mind you can still use BodyGyro, however response times may be slower, and bugs could happen. Align orientation is used with two attachments, however it can be used with CFrames, which makes it SIGNIFICANTLY easier.

How to do this?

Well, you need position1 (the origin of the alignorientation), and position2(the target position of the alignorientation). You want to set alignorientation to oneAttachment mode, like so:

local alignOrientation=Instance.new('AlignOrientation', parent)
local orientationAttachment=Instance.new('Attachment', parent)

alignOrientation.Attachment0=orientationAttachment

alignOrientation.Mode=Enum.OrientationAlignmentMode.OneAttachment

Now that we have our alignorientation set to one attachment, and the one attachment is inside our origin basepart, we want to go ahead and create an angle finder function:


local alignOrientation=Instance.new('AlignOrientation', parent)
local orientationAttachment=Instance.new('Attachment', parent)

alignOrientation.Attachment0=orientationAttachment

alignOrientation.Mode=Enum.OrientationAlignmentMode.OneAttachment

local function findAngle(positionA, positionB)
     local CF=CFrame.new(positionA, positionB)
     local targetX, targetY, targetZ=CF:ToEularAnglesXYZ()
     local finalizedAngle=CFrame.Angles(targetX, targetY, targetZ)
     return finalizedAngle
end

I’ll run an example. Let’s say there’s a part in the workspace, and you want the part to face the player’s mouse. I’ll run this on a localscript to just provide an example.

local part=Instance.new('Part', workspace)
local attachment=Instance.new('Attachment', part)
local alignOrientation=Instance.new('AlignOrientation', part)

alignOrientation.Attachment0=attachment
alignOrientation.Mode=Enum.OrientationAlignmentMode.OneAttachment

local function findAngle(positionA, positionB)
     local CF=CFrame.new(positionA, positionB)
     local targetX, targetY, targetZ=CF:ToEulerAnglesXYZ()
     local finalizedAngle=CFrame.Angles(targetX, targetY, targetZ)
     return finalizedAngle
end

local mouse=game.Players.LocalPlayer:GetMouse()

local runService=game:GetService'RunService'

runService.RenderStepped:Connect(function()
    alignOrientation.CFrame=findAngle(part.Position, mouse.Hit.Position)
end)

This code will make the part face the mouse.

Make sure your parts are not anchored.

If there’s any suggestions for this post, please comment and I’ll gladly add them.

Thanks for reading :smiley:

24 Likes

Slight mistake, sorry for realizing it just now, it’s supposed to be :ToEulerAnglesXYZ not :ToEularAnglesXYZ

Hi, is there any reason why you have to make a separate function just to get the angles instead of using
alignOrientation.CFrame=CFrame.lookAt(part.Position, mouse.Hit.Position)
or
alignOrientation.CFrame=CFrame.new(part.Position, mouse.Hit.Position)

3 Likes

I suppose it would be a preference. In some personal cases I don’t know why lookAt hasn’t worked. I find that the function always works 100% of the time.

Edit:
Also, to allow the change of only one axis on the AO if needed.

2 Likes