Should i still be using bodymovers?

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!

2 Likes

Body movers are not deprecated, they are only legacy. Roblox has introduced constraints, and those are recommended instead.

3 Likes

I had a similar question a few months back, check out There's no indication that legacy BodyMovers are deprecated - #8 by Ozzypig

1 Like

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 image 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)

19 Likes