Need help with spaceship pitch controls

Hello all,

I have been working on a spaceship system controlled by the mouse using BodyGyro and BodyVelocity. Wherever the mouse is pointing the ship will move towards, and the ship can be rolled by pressing A or D.

local UIS = game:GetService("UserInputService")
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local shipPart = workspace.TestShip.PrimaryPart

local MAX_SPEED = 150
local SPEED = 50
local ACCELERATION = 1

local roll = 0
local rollFactor = 3

game:GetService("RunService").RenderStepped:Connect(function(dt)
	
	shipPart.BodyVelocity.Velocity = workspace.CurrentCamera.CFrame.LookVector * SPEED
	--shipPart.BodyGyro.CFrame = CFrame.new(workspace.CurrentCamera.CFrame.Position, workspace.CurrentCamera.CFrame.Position + workspace.CurrentCamera.CFrame.LookVector)
	shipPart.BodyGyro.CFrame = CFrame.new(mouse.Hit.Position, mouse.Hit.Position + mouse.Hit.LookVector)
	
	if roll == -360 or roll == 360 then roll = 0 end
	shipPart.BodyGyro.CFrame = shipPart.BodyGyro.CFrame * CFrame.fromEulerAnglesXYZ(0, 0, math.rad(roll))
	
	if workspace.CurrentCamera.CameraType ~= Enum.CameraType.Scriptable then
		workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable
	end
	
	local rotVel = shipPart.RotVelocity
	-- Rotate the vector to object space:
	rotVel = shipPart.CFrame:VectorToObjectSpace(rotVel)
	rotVel = rotVel * 0.01
	-- Set the camera's position:
	workspace.CurrentCamera.CFrame = shipPart.CFrame * CFrame.new(0, 5, 25) * CFrame.Angles(-rotVel.X, -rotVel.Y, -rotVel.Z)
	--workspace.CurrentCamera.CFrame = workspace.CurrentCamera.CFrame * CFrame.Angles(0, 0, math.rad(roll))
	
	if UIS:IsKeyDown(Enum.KeyCode.W) then
		SPEED = math.clamp(SPEED + ACCELERATION, 0, MAX_SPEED)
	end
	if UIS:IsKeyDown(Enum.KeyCode.S) then
		SPEED = math.clamp(SPEED - (ACCELERATION * 2), 0, MAX_SPEED)
	end
	if UIS:IsKeyDown(Enum.KeyCode.A) then
		--roll left
		roll = roll + rollFactor
	end 
	if  UIS:IsKeyDown(Enum.KeyCode.D) then
		--roll right
		roll = roll - rollFactor 
	end
end)

The issue is with the code I have currently, the ship cannot do a full 360 on the pitch axis. This is what I mean:
https://gyazo.com/0f186218a326a958341d5d7d330032d4

I have no idea where to go from here, and it has already taken me all day to get to this point due to my low-level maths. I am pretty sure this has something to do with mouse.Hit.LookVector when changing shipPart.BodyGyro.CFrame, but the math is beyond my knowledge.

It would be really helpful if you could please explain the math a little more abstract in your solution. Thanks!

1 Like

The problem is that the default camera controller doesn’t let you look more than ~85 degrees up or down. When the ship tries to pitch beyond that, the camera doesn’t follow which means the mouse.Hit CFrame doesn’t change either. Which is a great default for most games, but unfortunately doesn’t work in your situation where the camera sometimes needs to be upside down. You’ll have to make your own CameraScript or modify the default one.

3 Likes

Man, things just keep getting more complicated lol. Thanks for the reply

No problem. You could also try a control scheme that doesn’t need the mouse position to go above 90 degrees up/down