I’ve been trying to make a rocket ship animation using CFrame math but I’m having issues with the way it rotates at the beginning of the launch. It works by calculating its position every frame and then having it face towards where it was on the previous frame. Unfortunately it makes these sharp 90 degree turns at the beginning. Is there a different CFrame constructor I could use to prevent this?
You could either try providing an up argument to CFrame.lookAt, or manually calculating the rotation matrix yourself via CFrame.fromMatrix. Could you share what your script looks like now?
It’s a pretty big script, but this is the main function that deals with the positioning.
local frameConnection = RunService.Heartbeat:Connect(function(deltaTime: number)
local deltaA = deltaTime / FLY_TIME
currentA = math.min(currentA + deltaA, 1)
local easedA = TweenService:GetValue(currentA, EASING_STYLE, EASING_DIRECTION)
local currentPivot = getCurrentPivot()
local newPos = bezier(positions, easedA)
local previousPos = currentPivot.Position
local finalPivot = CFrame.new(newPos, previousPos)
if currentA < ROTATE_THRESHOLD then -- follow the look vector
rocketModel:PivotTo(finalPivot)
else -- easing into landing position
local currentRotation = currentPivot.Rotation
local finalRotation = endPos.Rotation
rotateSpeed += ROTATE_ACCELERATION
local newRotation = currentRotation:Lerp(finalRotation, rotateSpeed * deltaTime)
rocketModel:PivotTo(CFrame.new(newPos) * newRotation)
end
end)
Try using codes like this:
local lastLookVector = nil
local frameConnection = RunService.Heartbeat:Connect(function(deltaTime)
local deltaA = deltaTime / FLY_TIME
currentA = math.min(currentA + deltaA, 1)
local easedA = TweenService:GetValue(currentA, EASING_STYLE, EASING_DIRECTION)
local newPos = bezier(positions, easedA)
if currentA < ROTATE_THRESHOLD then
if lastLookVector then
local newLook = (newPos - lastPosition).Unit
local smoothedLook = lastLookVector:Lerp(newLook, 0.25)
local pivot = CFrame.new(newPos, newPos + smoothedLook)
lastLookVector = smoothedLook
rocketModel:PivotTo(pivot)
else
lastLookVector = Vector3.new(0, 0, -1)
end
else
local currentRotation = rocketModel:GetPivot().Rotation
local finalRotation = endPos.Rotation
rotateSpeed += ROTATE_ACCELERATION
local newRotation = currentRotation:Lerp(finalRotation, rotateSpeed * deltaTime)
rocketModel:PivotTo(CFrame.new(newPos) * newRotation)
end
lastPosition = newPos
end)