My game features a lot of this (e.g. a door that slides open, a windmill etc.) but in online mode they tend to lag. How can I fix this?
How do I reduce CFrame animation lag?
1 answer
CFraming can be great for for short, simple block animations (e.x. teleporting a part, pointing a part towards a player). Though when it comes to complex, extensive operations (like updating the CFrame of a part 50 times per second) can create some major issues, especially in Unions and models.
To understand this a little better, let's look at an example. First, we have a server script that moves a block over .05 studs 40 times per second (40/s2). The script should look something like this:
Part = game.Workspace.Part --Part will equal an regular part that is located in the workspace
Z = 0 --will be a holding variable, represting the "Z" axis of our part
while x ~= 10 do --will keep repeating the script until x reaches 10
wait(.02) --this will repeat the loop 40 times per second
Z = Z+ .05 --we add .05 to Z (which adds .05 to our parts "Z" axis)
Part.Position = Part.Position + Vector3.new(0,0,Z) --now we set the Z position of the part to our variable "X"
end
Now moving this one part won't produce a large amount of lag, but when multiple parts our moving at a similar rate, then we have a problem. This is because when we change a
property(such as aposition) of an object, the data has to be transefered over thenetwork(internet) onto theclient(a player's computer) and right back through the network and finally onto theserveragain.
So how can we fix this?
Well in order to fix the problem, we need to limit as much data that's being transefered over from the network. So we'd add some a body mover that will create a smooth "animation" for that part, without all the lag. There are two main types that I reccomend: 1) BodyAngularVelocity and 2) BodyVelocity. These two types allow you two control the speed, position, and rotation of a part.
If we wanted to control these forces using a script, we'd do this:
BodyVelocity = Instance.new("BodyVelocity", game.Workspace.Part) --this will create new velocity for a part
Part = game.Workspace.Part --this is the part we're using
HoldVar = 0 --holding variable that will be used to control the # of times function will be run
game.Workspace.Part.Touched:connect(function(object) --we'll create a function that we'll check for if the part we're using has been touched
if object.Parent:FindFirstChild("Humanoid") ~= nil and HoldVar == 0 then --this checks for if the object that touched the part is a player and if our holding Variable is equal to 0
HoldVar = 1 --this sets the Holding Variable to 1 so that the function doesn't run multiple times
BodyVelocity.Velocity = Vector3.new(0,0,2) --This sets the velocity to a certain amount when the parts touched
end
end)
This discussion is preserved as it was. New answers, comments, and votes are closed.

4 comments
This is super helpful thanks, I have a question though, do the parts need to be unanchored for the BodyVelocity to work?
Just checked, is there a way to keep the part anchored and for it to move without using CFraming?
Sadly there isn't. Though when using BodyVelocity, you won't need it to be anchored, since you can add to the "MaxForce" and the "P" properties to cancel out gravity and any other forces.
By the way if you thought my answer was helpful, please consider accepting it and/or up voting it!