Optimizing Part Rotation for Performance

  1. What do you want to achieve? Keep it simple and clear!
  • I want to efficiently rotate 60 parts in my game to ensure minimal impact on FPS (frames per second).
  1. What is the issue? Include screenshots / videos if possible!
  • I’m unsure which method to use for rotating the parts. The methods I have tried are causing performance issues, and I’m looking for the most FPS-efficient solution.
  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
  • I’ve experimented with two methods:
    • Using TweenService to create a rotation tween for each part.
    • Using the RunService.Stepped event to manually update the CFrame of each part every frame.

Below are the code snippets for the methods I have tried:

-- Method 1: Using TweenService
local TweenService = game:GetService("TweenService")
local CoinRotationTweenInfo = TweenInfo.new(5, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut, -1, true)
local tweens = {}

for _, part in pairs(parts) do
    local tempTween = TweenService:Create(part, CoinRotationTweenInfo, {CFrame = part.CFrame * CFrame.Angles(0, math.rad(120), 0)})
    table.insert(tweens, tempTween)
    tempTween:Play()
end

-- Method 2: Using RunService.Stepped
game:GetService("RunService").Stepped:Connect(function()
    for _, part in pairs(parts) do
        part.CFrame = CFrame.new(part.Position) * CFrame.Angles(0, math.rad(part.Orientation.Y - 1), math.rad(90))
    end
end)

I would appreciate some guidance on which method is more FPS-efficient. If these methods aren’t optimal, any alternative suggestions would be really, really helpful!

Thank you in advance for your time and help!

Try using Lerp?

I think it is the best one for performance.

1 Like

This can be optimized further. Shocking, I know.

If all you’re doing is making a part spin forever, you can just use compound assignment and multiply the part’s CFrame by the rotation increment. Compound assignment is generally better performing.

a = a * b
--is the same as
a *= b

You also do not need to construct a new CFrame every time for each part on each frame. you can reuse the incrementing CFrame.

--main scope
local rot: CFrame = CFrame.Angles(0, math.rad(1), 0) --1 degree

--inside the loop
part.CFrame *= rot

However, if you want the rotation to be applied from worldspace (global rotation instead of local) you would have to do this instead:

part.CFrame = rot * part.CFrame

This is not the same as part.CFrame = part.CFrame * rot because matrix multiplication is not commutative and the order matters.

4 Likes

Hello Vernumeron,
First of all, thank you so much for taking the time to provide a detailed answer!
I tried implementing your suggestions, and yea, there was a significant improvement in performance! Thank you for pointing out the use of CFrame compound assignment, I wasn’t even aware of it before.
Thanks again for your help! I really appreciate it.
Best

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.