How to: Clone Model, Move all parts to player position, without changing the angle it faces

Hey guys, I don’t know if it’s me being tired or what but I have this model spell thing that worked perfectly when I was casting it at it’s location.

But when I SetPrimaryPartCFrame to the torso of the my Player.Character.FindFirstChild(“UpperTorso”) CFrame, or Position etc, the model primary part ends up flipping like 90 degrees.

So rather than spreading out like a doughnut on the ground, it turns sideways like a bike wheel. The primary part is a cylinder and is meant to spread out like a flat shock wave.

I tried changing orientation, the X to 90, but it didn’t work, then the Y and it set it to -90 for some reason. Then tried 90 on Z but it made the Y 180 and set Z back to 0 for some reason.

local P = game.ServerStorage.Spells

local ClickDetector = Instance.new("ClickDetector")

ClickDetector.Parent = script.Parent

ClickDetector.MouseClick:Connect(function(Player)
	local Humanoid = Player.Character:FindFirstChild("UpperTorso")
	local Clone = P.Spell1:Clone()
	Clone.Parent = script.Parent
	local NewPosition = CFrame.new(Humanoid.Position)
	Clone:SetPrimaryPartCFrame(NewPosition)
end)

Not sure what I’m doing wrong here. Probably something obvious that I just can’t seem to fathom. Can’t see the forest through the trees you know?

How do I get it to clone the model (that works fine where it’s located) and move all the parts to the player position without messing with the angle it’s facing?

1 Like

I guess set the position to the humanoidrootpart instead.

1 Like

Alright, forewarning, usually when I deal with CFrames I get bamboozled by my programs. A lot.

But here’s what I think the issue is (emphasis on think).

The new position CFrame might be setting the orientation (not just the position) of your primary part to the humanoid position because you haven’t specified the CFrame orientation when setting it for the clone.

For example, if you used the more elaborate constructor that takes in the position and the look vector, you can specify which direction it is facing.

Alternatively, you could set the whole matrix yourself using the long CFrame constructor. This will ensure your desired orientation is met, but it’s a lot of extra work.

Again, I get my ankles broken by CFrames a lot, but hopefully this helps.

1 Like

The simple answer is Model:SetPrimaryPartCFrame(CFrame.new(UpperTorso.Position))

Essentially, a CFrame isn’t just another form of a Vector3 value. A CFrame contains both a position Vector3 and a Rotation/Orientation Vector3. When you set the PrimaryPartCFrame to the CFrame of the UpperTorso, you are setting the PrimaryPartPosition to the UpperTorso’s position, but also the UpperTorso’s rotation.

Tl:DR to get around this, simple reconstruct the CFrame by using CFrame.new(UpperTorso.Position) this will create a new CFrame using the UpperTorso’s position without using the UpperTorso’s rotation.

local NewPosition = CFrame.new(Humanoid.Position)
Clone:SetPrimaryPartCFrame(NewPosition)

Above, you are creating a new CFrame with the UpperTorso’s Position. Nothing else. This means it will have a default orientation (or, 0 radians on all axis)

You can make it face a certain direction using the second parameter of CFrame.new():

This example will position the model at the given position, facing straight upward (relative to the primary part)

local cframe = CFrame.new(position, position + Vector3.new(0,1,0))
model:SetPrimaryPartCFrame(cframe)

If you want to preserve the orientation of the model (which may or may not be the best way to solve your issue), you can extract it’s orientation and create a new CFrame using it, as such:

local currentCframe = model.PrimaryPart.CFrame -- ensure there's a primary part before indexing PrimaryPart properties, or error.
local rX, rY, rZ = currentCframe:ToOrientation() -- the x, y, z rotation values in radians (currentCframe:toEulerAnglesYXZ() would produce the same result here)

local newCframe = CFrame.new(position) * CFrame.fromOrientation(rX, rY, rZ) -- CFrame.new(position) makes a new CFrame with only the position, fromOrientation makes a new CFrame with only orientation. Multiplying them adds them together.
model:SetPrimaryPartCFrame(newCframe)
5 Likes

Yep that second one did the trick.

I printed out the ToOrientation and then just used CFrame.fromOrientation(0, 0, 1.57). Saves it having to look since all the models are the same.

Thank you!

1 Like