hello, I am not very good at cframes and so I am struggling over what I am sure is an easy problem for some. the problem I am having is that I am trying to align 2 models, and it is failing miserably because of the way the models have been made.
the way I am currently orientating them is by setting their primary part in a script. the problem is that yes, although the primary parts have the same rotation, the rest of the model does not. Because of the way the models have been built, the primary parts are not in the same location every time. This means while on one model the Primary part may be on the right side, the other may have it on the left. Because of this, I cannot find a way to orientate them properly.
I am assuming there is some form of solution using CFrame:ToWorldPosition() and CFrame:ToObjectPosition(). The problem is that my CFrame skills are lacking, and I have minimal knowledge on how ToObjectPostion and ToWorldPosition would be used in a scenario like this.
Use CFrame.Angles()
Take the target CFrame and do * CFrame.Angles(math.rad(90), 0, 0)
The first value I put in probably won’t work so mess with -90, 90 and change it’s value position.
You should only have a single slot with math.rad and the rest 0s
Yes, this works for some models. The problem is that it’s not a universal solution as a few of the models have their primary part on the left, some on the right, some on the front, some on the back. A hard set rotation modification works for some, but not others.
You could just insert a Vector3Value in each model and in the script just reference that for the number.
local SelectedStage = ...
local OffsetVector = SelectedStage.OffsetVector.Value
SelectedStage.PrimaryPart.CFrame = YourTargetCFrame * CFrame.Angles(
math.rad(OffsetVector.X),
math.rad(OffsetVector.Y),
math.rad(OffsetVector.Z)
)
You’ll need a little elbow grease and manually adjust the Vector3Value for each model but it’ll be worth it in the long run since you’ll only need to do it once per new stage.
I would change the PrimaryPart to be an invisible Part that is specifically placed to easily manage the placement of the Model.
You can get the same result without changing the PrimaryPart if that’s more convenient. You’ll still need some Parts that are supposed to overlap, so you probably won’t get around the “invisible marker parts” approach. Here’s a function that will move a specific Part of a Model to a CFrame:
local function SetModelPartCFrame(model, part, cframe)
assert(
model.PrimaryPart ~= nil,
("Model %s doesn't have it's PrimaryPart set!")
:format(model:GetFullName())
)
local primaryToPart = model.PrimaryPart:ToObjectSpace(part.CFrame)
model:SetPrimaryPartCFrame(cframe * primaryToPart)
end
I think that’s right but I can’t test it right now. Let me know if it gives weird results
You can use it like this:
--[[ Function to move a level model after a different level model ]]
local function PlaceLevelStartAtLevelEnd(levelToPlace, levelToPlaceOnto)
SetModelPartCFrame(
levelToPlace,
levelToPlace.LevelStartMarker,
levelToPlaceOnto.LevelEndMarker.CFrame
)
end
EDIT: You could combine this with Global’s suggestion to avoid the “marker parts”.
I think I figured it out! I used 2 parts, one at the start of the section I was placing on, one at the end of the previous section. Then, I made sure they both had their front face pointed toward the start/end pad. Then, when I wanted to place them, I just placed one on top of the other, then used CFrame:LookAt in order to orientate the new section. I am not sure if this explanation made sense, but it worked!
I would not have thought of this without your post, so I am giving you the solution. Thank you!