Okay, so I was reading some posts on devforum on how body movers are deprecated, and i’m wondering, should I use them or not? If not, what would be a good replacement for moving a character, rotating a character, or even setting a character in a certain CFrame? Any help would be appreciated!
Body movers are not deprecated, they are only legacy. Roblox has introduced constraints, and those are recommended instead.
I had a similar question a few months back, check out There's no indication that legacy BodyMovers are deprecated - #8 by Ozzypig
I use constraints over bodymovers 90% of the time, they’re usually easier to use, and work better
Basic pet follow system example
apologies for the not very detailed examples, but it gets the point across
BodyPosition> has to be setup and requires a loop
AlignPosition > setup once and done, no loops
BodyPosition [Legacy Body Mover]
local bodyPosition = pet.BodyPosition
while true do
bodyPosition.Position = characterPrimary.CFrame * CFrame.new(0, 3, -3)
wait()
end
AlignPosition [Constaint]
local alignPosition = pet.AlignPosition
local basePetAttachment = pet.BaseAttachment -- align position attachment0
local petOffsetAttachment = characterPrimary.PetOffsetAttachment -- align position attachment1
petOffsetAttachment.Position = Vector3.new(0, 3, -3) -- relative to character primary, it's not WorldPosition
AI movement example
Here’s some code from a basic AI system I’m working on, I had a goal attachment parented to a dummy part, and I can use that as the attachment1 for my constaints (align position and orientation)
local Players = game:GetService("Players")
local OFFSET = 5
local npc = script.Parent
local humanoidRootPart = npc.HumanoidRootPart
humanoidRootPart:SetNetworkOwner(nil) -- if this isn't done, network swapping will cause a bit of jittering
local originPosition = humanoidRootPart.Position
local animations = npc.Animations
local walkAnimation = animations.WalkAnimation
local idleAnimation = animations.IdleAnimation
-- because attachments require a part parent
local attachmentHolderPart = Instance.new("Part")
attachmentHolderPart.CanCollide = false
attachmentHolderPart.Anchored = true
attachmentHolderPart.Transparency = 1
attachmentHolderPart.Size = Vector3.new(0, 0, 0)
attachmentHolderPart.Position = Vector3.new(99999, 99999, 99999)
attachmentHolderPart.Parent = workspace
local baseAttachment = Instance.new("Attachment", humanoidRootPart)
local goalAttachment = Instance.new("Attachment", attachmentHolderPart)
local NPCPosition = Instance.new("AlignPosition")
NPCPosition.ApplyAtCenterOfMass = true
NPCPosition.MaxForce = 1000000
NPCPosition.MaxVelocity = 16
NPCPosition.Responsiveness = 35
NPCPosition.Attachment0 = baseAttachment
NPCPosition.Attachment1 = goalAttachment
NPCPosition.Parent = humanoidRootPart
local NPCOrientation = Instance.new("AlignOrientation")
NPCOrientation.MaxTorque = 20000
NPCOrientation.Responsiveness = 15
NPCOrientation.Attachment0 = baseAttachment
NPCOrientation.Attachment1 = goalAttachment
NPCOrientation.Parent = humanoidRootPart
local currentlyWalking = false
local currentTarget = npc.Target
-- anims
local function enterWalk()
currentlyWalking = true
idleAnimation.Value = false
walkAnimation.Value = true
end
local function enterIdle()
currentlyWalking = false
walkAnimation.Value = false
idleAnimation.Value = true
end
-- moving
local function moveTo(goalPosition)
goalAttachment.WorldPosition = goalPosition
end
local function lookAt(goalPosition)
goalAttachment.WorldCFrame = CFrame.new(goalAttachment.WorldPosition, goalPosition)
end
-- position helpers
local function setVectorY(vector, y)
return Vector3.new(vector.X, y, vector.Z)
end
local function follow(target)
if not target then return end
local targetPart = target:IsA("Model") and target.PrimaryPart or target
local lastPosition = setVectorY(humanoidRootPart.Position, 3)
local function update()
local currentPosition = setVectorY(humanoidRootPart.Position, 3)
local targetPosition = setVectorY(targetPart.Position, 3)
local direction = (currentPosition - targetPosition).Unit
local goalPosition = targetPosition + direction * OFFSET
moveTo(goalPosition)
lookAt(targetPosition)
local mag = (lastPosition - currentPosition).Magnitude
if not currentlyWalking and mag > .1 then
enterWalk()
elseif currentlyWalking and mag <= .1 then
enterIdle()
end
lastPosition = currentPosition
end
while currentTarget.Value == target do
update()
wait()
end
end
moveTo(originPosition)
currentTarget.Changed:Connect(follow)
I’d say use constraints over bodymovers when you can, but there are some cases where I prefer to use bodymovers, they tend to have Vector3 forces like which is useful when you want to exert more force on a particular axis, and this isn’t usually possible with constraints AFAIK (correct me if I’m wrong, I’d love to be able to do this with AlignPos/AlignOrientation)