Hello, I am attempting to create a smoother “Orientation Alignment” behavior.
I whipped up this custom class for a NPC system I’m working on that allows me to have characters (and other things, really. This is a wide catch-all type thing.)
This is my Watching Method for my Alignment class. It gets the job done but I’m positive there are many better (and more effective ways) of doing this.
function AlignmentH:SetWatching(Target : BasePart | Vector3 | CFrame | nil)
if self.Watching == Target then return false end
self.Watching = Target
-- Cleanup existing watcher thread
if self.WatchThread then
self.WatchThread:Disconnect()
self.WatchThread = nil
end
-- If Target is nil, remove AlignOrientation & invisible part
if Target == nil then
for _, v in {AOName, APName} do
if self[v] then
self[v]:Destroy()
self[v] = nil
end
end
return true
end
-- Ensure we have an AlignOrientation and an attachment part
if not self[AOName] then
self[AOName] = self.Janitor:AddToCleanup(Instance.new("AlignOrientation", self.Rig.PrimaryPart))
self[AOName].RigidityEnabled = true
self[AOName].Name = AOName
self[AOName].Attachment0 = self.Rig.PrimaryPart.RootAttachment
self[APName] = self.Janitor:AddToCleanup(General.CreatePart({
Name = APName,
Size = Vector3.new(0,0,0),
CanCollide = false,
CanTouch = false,
CanQuery = false,
Transparency = 1,
Anchored = true,
Parent = self.Rig.PrimaryPart,
}))
self[AOName].Attachment1 = self[APName].Attachment
end
-- Handle different target types
self.WatchThread = self.Janitor:AddToCleanup(RunS[if RunS:IsClient() then "RenderStepped" else "Heartbeat"]:Connect(function()
local targetPosition
if typeof(Target) == "Instance" and Target:IsA("BasePart") then
targetPosition = Target.Position
elseif typeof(Target) == "Vector3" then
targetPosition = Target
elseif typeof(Target) == "CFrame" then
targetPosition = Target.Position
else
return
end
-- Ensure NPC looks at the target position while keeping the same Y height
local newOrientation = CFrame.new(self.Rig.PrimaryPart.Position, Vector3.new(targetPosition.X, self.Rig.PrimaryPart.Position.Y, targetPosition.Z))
self[APName].CFrame = newOrientation
end))
return true
end
I’m well aware Roblox’s physics objects (and just Roblox’s physics in general) run at 60 FPS, which is very noticeable on higher powered hardware. However, I haven’t found a smoother way to update the orientation of a character rig without it being completely stuck in the air without utilizing these instances.