CFrame Plane Turning

Ok so I have my script, im trying to make it move, and after like 5 second it starts to turn like a plane would. I want it to keep turning till about a 45 degree angle, and keep moving for another 5 sec then repeat the same thing over again.

I have this script, its not completed but it doesnt work, no error.

I hope this makes sense

If you want it to first just move and then move and rotate smoothly at the same time, and then keep repeating these, maybe the script below will work. However, it might be a good idea to weld the other parts to the PrimaryPart of the model and normally change the CFrame of the PrimaryPart. It’s been mentioned somewhere that :SetPrimaryPartCFrame can eventually offset the parts when used repetitively.
Edit: The way I calculate the CFrames isn’t super accurate either, so I made some changes to this. Now, when it has rotated 360 degrees, it will reset the CFrame to the original. Unfortunately, this only works properly when the angle is a value that, when multiplied by 2^(some natural number), is 90 degrees. Sorry if that was a confusing explanation.

local Runservice = game:GetService("RunService")

local MOVE_WITHOUT_ROTATE_TIME = 5
local MOVE_WITH_ROTATE_TIME = 5
local SPEED = 300
local ROTATION_TARGET_ANGLE_DEG = 45

--game.Players.PlayerAdded:Wait().CharacterAdded:Wait()
wait(5)

local thingy = workspace.Model -- script.Parent

local startCf = thingy:GetPrimaryPartCFrame()

local rotationTargetAngleRad = math.rad(ROTATION_TARGET_ANGLE_DEG)
local currentAngle = 0
local totalAngle = 0

local totalMoveTime = 0
local rotateStartTime = totalMoveTime+MOVE_WITHOUT_ROTATE_TIME
local rotateEndTime = rotateStartTime+MOVE_WITH_ROTATE_TIME

local _, delta = nil, 0

while true do
	local angleToAdd, deltaWithRotation, endTurning
	if totalMoveTime > rotateStartTime and totalMoveTime < rotateEndTime then
		if currentAngle == 0 then
			deltaWithRotation = totalMoveTime-rotateStartTime
			angleToAdd = deltaWithRotation*rotationTargetAngleRad/MOVE_WITH_ROTATE_TIME
		else angleToAdd = delta*rotationTargetAngleRad/MOVE_WITH_ROTATE_TIME
		end
		currentAngle += angleToAdd
	elseif totalMoveTime > rotateEndTime then
		deltaWithRotation = delta-(totalMoveTime-rotateEndTime)
		angleToAdd = rotationTargetAngleRad-currentAngle
		endTurning = true
		currentAngle = 0
		rotateStartTime = rotateEndTime+MOVE_WITHOUT_ROTATE_TIME
		rotateEndTime = rotateStartTime+MOVE_WITH_ROTATE_TIME
	end
	local primaryCf = thingy:GetPrimaryPartCFrame()
	if angleToAdd then
		totalAngle += angleToAdd
		local angleCf = CFrame.Angles(0, angleToAdd, 0)
		if deltaWithRotation then
			if endTurning then -- rotating, ending the rotation
				if math.abs(math.pi*2-totalAngle) < rotationTargetAngleRad/2 then
					totalAngle = 0
					thingy:SetPrimaryPartCFrame(startCf)
				else thingy:SetPrimaryPartCFrame(primaryCf*angleCf*CFrame.new(0, 0, delta*SPEED))
				end
			else -- rotating, starting the rotation
				local moveCf, moveCf2 = CFrame.new(0, 0, (delta-deltaWithRotation)*SPEED), CFrame.new(0, 0, deltaWithRotation)
				thingy:SetPrimaryPartCFrame(primaryCf*moveCf*angleCf*moveCf2)
			end
		else -- rotating, but not ending or starting the rotation
			thingy:SetPrimaryPartCFrame(primaryCf*angleCf*CFrame.new(0, 0, delta*SPEED))
		end
	else thingy:SetPrimaryPartCFrame(primaryCf*CFrame.new(0, 0, delta*SPEED))
	end
	_, delta = Runservice.Stepped:Wait()
	totalMoveTime += delta
end
1 Like

I think you should use body movers. Body gyro for turning. Body thrust, Body Force, or Body Position for moving. Using :SetPrimaryPartCFrame can offset parts and can make the plane go through objects.

It works but it goes backwords.

I removed some minuses. Does it now work? If it also rotates to wrong direction, put a minus before angleToAdd in the line

local angleCf = CFrame.Angles(0, angleToAdd, 0)