How do you use CFrame for the children of a model

Hey, I’ve just started learning LUA and scripting in general and I managed to encounter a problem today.

my question is how can I use CFrame for the Children of a model

For example if I want to use

game.Workspace.Part.CFrame = game.Workspace.Part.CFrame * CFrame.fromEulersAnglesXYZ(0,1,0)

But instead of part I wanted to do it for all the children of a model(Lets say its named model)

I tried doing:

for i,v in pairs(game:GetService(“Workspace”):FindFirstChild(“Model”):GetChildren()) do
v.CFrame = v.CFrame * Cframe.fromEulersAnglesXYZ(0,1,0)

but somehow it didn’t work for me. Would appreciate it if anyone could tell me what I have to do, Thanks!

3 Likes

If the model has a primary part, you can use SetPrimaryPartCFrame() as it’ll set the CFrame of every object in that model.

2 Likes

But I’ll be using a lot of models if I set a primary part its just gonna be for one model right?

1 Like

also how would use SetPrimaryPartCFrame() in this case? I tried a couple of ways but it didn’t work

1 Like

Are you trying to rotate the model as one, or rotate every child separately?

If you’re trying to rotate a model together, do as @mircostaff suggestion and use a primary part.

model:SetPrimaryPartCFrame(model.PrimaryPart.CFrame * CFrame.fromEulerAnglesXYZ(0,1,0)) 

This will rotate the primary part, then move everything else in the model to be the same as before, relative to the primary part.

If you just wanted to rotate everything in a model/folder, then you’re doing it right (loop through and set each one individually) - Keep in mind any welds you have in the model.

2 Likes

Yes im trying to make each child ritare separetly

But how can I do it without having to write a code for each individuall?

Reason is god knows how many parts I have inside that model, it’d take a life time. Plus ill be using it for Other models Aswell.

2 Likes

How many parts are we talking about here?
If you are trying to rotate enough parts for it to take eternity with code, I’ll take a guess that you have too many parts in the first place.

Anyways, there could be a few tricks you use here and there but you still need to loop through every part within the model and set its cframe however you want it.
I wrote a little function that loops through the model and any children within the children to apply the changes to them. Same thing you were doing but checks for children within the children:

local function change_model(item, change)
	if item:IsA("Part") then -- whatever conditions you want for if the item should be rotated
		item.CFrame = item.CFrame * change -- rotates/moves the part right here
	end
	
	for ind,child in pairs (item:GetChildren()) do -- check if there are any children inside
		change_model(child, change)
	end
end


change_model(model, CFrame.fromEulerAnglesXYZ(0,1,0))

Please note that the code you posted will not work due to a typo

Cframe.fromEulersAnglesXYZ

should be

CFrame.fromEulerAnglesXYZ

3 Likes

Hey there!

Looking at your code snippet in OP, it looks like a pretty small change in rotation of the model’s parts - which makes me think you’re actually wanting to repeatedly change the child/descendant objects of the model.

If that is indeed your goal here, and you want to rotate the model instead of individually on each brick in the model to rotate around itself, I would advice against using SetPrimaryPartCFrame.

But why? Look at the following video, and you’ll notice the results of misusing SetPrimaryPartCFrame for repeated use.

What happens here is that due to floating point errors with the CFrames (microscoping offsets in some decimal numbers due to how computers store those numbers), the result is that the parts will create visible gaps after you’ve used SetPrimaryPartCFrame on angles that don’t fit up with the world grid for a while.

There are several other solutions, but getting a single-property controllable model that you can move and rotate, you could create welds from a root part / primary part of the model to all other parts in the model, and just change the CFrame of that root part.
This way, the offsets from the root part to the other parts remains stored separately, and you’ll have Roblox handle the rest. You do want to unanchor the other parts while keeping the root part anchored, though.

If you want to do this entirely with code, here are some snippets you can make use of:

-- Creates Motors between the model's PrimaryPart and all other parts, while unanchoring the other parts.
-- This should only be called once, when initializing the model.
-- The variable "model" is assumed to be defined before this code block.

for _, part in next, model:GetDescendants() do -- Loop over all descendants in the model
    if part:IsA("BasePart") and part ~= model.PrimaryPart then -- Finds all parts, excluding the root part
        local joint = Instance.new("Motor")
        joint.C0 = model.PrimaryPart.CFrame:inverse() * part.CFrame -- Finds the current object-space offset for the root part to the other part
        joint.Part0 = model.PrimaryPart
        joint.Part1 = part
        joint.Parent = model.PrimaryPart
        part.Anchored = false -- Unanchor the other part to allow the joint to control its location
    end
end
-- Changes the rotation of the entire model in a loop, given the previous code block was called first.
-- The offsets of the bricks to the root part of the model remains the same.
-- The variable "model" is assumed to be defined before this code block.

while wait() do
    model.PrimaryPart.CFrame = model.PrimaryPart.CFrame * CFrame.Angles(0, 0.01, 0)
end

Other pros here is that you can use TweenService when moving the model.

4 Likes