The reason I ask is because SetPrimaryPartCFrame gradually causes a model to “explode” which is really bad for my usecase. I’m using 3DSkybox by @ITBV and I have things that rotate within it.
The problem is, is this model gradually degrades overtime.
I was wondering if there was some way to rotate a model without using SetPrimaryPartCFrame, or if there was a way to solve the problem of the model breaking apart while still using SPPCF.
You could weld all of the parts to the primary part and just set that primary part’s CFrame in a circle. Because they are welded to the primary part, they can follow the primary part’s rotation.
There’s still a solution in that! You can rotate your center part and then offset the rest of the parts relative to that center that you turned, or you can bring the model out of the ViewportFrame temporarily to set its rotation before placing it back in. Wouldn’t recommend the latter though unless you have a way of making this kind of transition fairly invisible.
The reason that models explode is due to floating point error, which builds up over many CFrame changes. You’ll want to use a custom SetPrimaryPartCFrame function which stores the original offset between the each part and the primary part, then moves each part in the model but keeping the stored relative CFrame.
Prior to the rotation, you can get the position of all the parts relative to the primary part. Then use a for loop to put all the parts back in to that relative position to it once it moves?
What I have found?
There was a solution where you have to apply welds to the PrimaryPart and then using SetPrimaryPartCFrame or simply use CFrame on the main part which is welded. Make sure you unanchor them and that there’s nothing that can break the joints of it.
Addendum: I think Motor6D will fix it without anchoring.
Sources & Links
There have been multiple posts about it.
This code rotates a model in workspace called “Model” and keeps track of each part’s original CFrame relative to the primary part, as described by @ExtremeBuilder15. It has been tested.
local function toParts(model, origin)
local baseParts = {}
local toLocalOrigin = origin:Inverse()
for i, child in next, model:GetDescendants() do
if child:IsA 'BasePart' then
baseParts[child] = toLocalOrigin * child.CFrame
end
end
return baseParts
end
local function rotate(rotation, origin, baseParts)
for part, localCF in next, baseParts do
part.CFrame = origin * rotation * localCF
end
end
local model = workspace.Model
local origin = model.PrimaryPart.CFrame
local baseParts = toParts(model, origin)
-- 1 rotation / sec around y axis
local step = CFrame.fromAxisAngle(Vector3.new(0, 1, 0), 2 * math.pi / 60)
local rotation = CFrame.new()
game:GetService('RunService'):BindToRenderStep(
'Rotation Test',
Enum.RenderPriority.Camera.Value,
function()
rotation = step * rotation
rotate(rotation, origin, baseParts)
end
)