Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
2

How to move a model to absolute position but keep the rotations intact?

Asked by
elomage 12
5 years ago

I can move CFrame of the primary part of my model, but after moving to absolute coordinates the rotation of the model is reset. Is there a neat way to preserve it, or do I really need to save the angles and reapply them after the move?

Note, I can do a relative move by (11,11,11) like this:

local model = workspace.model
local ppcf = model:GetPrimaryPartCFrame()
model:SetPrimaryPartCFrame( ppcf + Vector3.new(11,11,11) )

But when doing the absolute coordinates (22,22,22) the rotation is lost:

model:SetPrimaryPartCFrame( CFrame.new() + Vector3.new(22,22,22) )

One solution that comes to mind is to get all the components of the CFrame, change the (x, y, z) and send the components back to the primary part.

local x, y, z, m11, m12, m13, m21, m22, m23, m31, m32, m33 = ppcf:components()
x = 22
y = 22
z = 22
model:SetPrimaryPartCFrame( CFrame.new( x, y, z, m11, m12, m13, m21, m22, m23, m31, m32, m33 ) )

But that seems to be too cumbersome... Is there a better, more elegant or efficient way?

1
Because you're doing CFrame.new() which creates a new cframe and then adding a v3? Add it to the current CFrame. xPolarium 1388 — 5y
0
If I add to the current, it will move to a relative location. I want to specify an absolute location. I suppose another approach is to subtract the primary part position vector from the relative shift vector to achieve absolute shift.. elomage 12 — 5y

2 answers

Log in to vote
0
Answered by
Fifkee 2017 Community Moderator Moderation Voter
5 years ago
Edited 5 years ago

The solution you came up with is indeed viable, but inefficient. Good job, though.

I'd keep the rotations by using :ToEulerAnglesXYZ() inside of a CFrame.Angles. :ToEulerAnglesXYZ() basically returns the rotation values of a CFrame grouping.


local Model = Instance.new('Model', workspace) for i = 0, 5 do wait() local x=Instance.new('Part', Model) x.CFrame = CFrame.new(math.random(1,15),math.random(1,30),math.random(1,45)) * CFrame.Angles(math.random(1,360),math.random(1,360),math.random(1,360)) x.Anchored=true; x.CanCollide=false; end Model.PrimaryPart = Model:GetChildren()[math.random(1,#Model:GetChildren())] wait(5) Model:SetPrimaryPartCFrame( CFrame.new(15,30,45) * CFrame.Angles( Model:GetPrimaryPartCFrame():toEulerAnglesXYZ() --Grab the Primary Part CFrame using :GetPrimaryPartCFrame(), then convert the CFrame using the toEulerAnglesXYZ() function. ) )
Ad
Log in to vote
1
Answered by 5 years ago
Edited 5 years ago

Your second idea could work, but you're right- there's a simpler way to do it. The issue with the first bit of code isn't setting it to an absolute value, it's adding CFrame.new() to the value rather than doing anything with the original CFrame. You can do this much simpler by just adding the absolute value to the original value and subtract the original value's Vector3 (see below for an example).

local modelCFrame = model:GetPrimaryPartCFrame()
model:SetPrimaryPartCFrame(modelCFrame - modelCFrame.Position + Vector3.new(2,7,1))

Edit: I'm not sure about the efficiency, but it's definitely more readable and looks cleaner.

0
Ha, I've been late all dayyy. Better than a comment tho. xPolarium 1388 — 5y
0
just type a half finished answer with the code and edit in an explanation adding an "Edit:" to make it look like it was a minor edit User#22604 1 — 5y
0
lol ^. Also, it should be perfectly fine efficiency-wise. SummerEquinox 643 — 5y

Answer this question