How do I make a flying vehicle?

I’ve been experimenting on making flying vehicles but I don’t know how to do it.

What I image is that the flying vehicle is always floating. The movement I imagine is definitely feasible, which the vehicle moves up and down based on your camera’s LookVector. This means that if you look up, you will go up once you request to move forward. The flying car rotates towards the direction you’re going, like how your character does when you move in a certain direction. I’ve done many things, such as using body velocity, and linear velocity.

I have three things to consider right now.

  • How would you make the vehicle know where to turn, based on the movement you provided
  • How to make the vehicle move in any direction, which includes up and down
  • How can I apply all of the above while keeping the vehicle floating

Take a look at the code inside of this Tool. I used it for the basis of my flying system.

for $1,250 Robucks?.. ouch… isnt there one in the Toolbox?

I’ve been going through the scripts and I don’t understand the math behind it. Do you know how I would be able to write something like this? I don’t understand how this works or why it works.

function Fly()
	
	if not ToolEquipped or not CheckIfAlive() then
		Flying = false
	else
		Flying = not Flying
	end
	
	if Flying and ToolEquipped and CheckIfAlive() then
		
		local Cloud = InvokeServer("Fly", {Flying = true})
		
		Momentum = (Torso.Velocity + (Torso.CFrame.lookVector * 1000) + Vector3.new(0, 3, 0))
		Momentum = Vector3.new(Clamp(Momentum.X, -15, 15), Clamp(Momentum.Y, -15, 15), Clamp(Momentum.Z, -15, 15))
		
		local FlightGyro = Instance.new("BodyGyro")
		FlightGyro.Name = "FlightGyro"
		FlightGyro.P = (10 ^ 4.5)
		FlightGyro.maxTorque = Vector3.new(FlightGyro.P, FlightGyro.P, FlightGyro.P)
		FlightGyro.cframe = Torso.CFrame
		FlightGyro.Parent = Torso
		
		local FlightVelocity = Instance.new("BodyVelocity")
		FlightVelocity.Name = "FlightVelocity"
		FlightVelocity.velocity = Vector3.new(0, 0, 0)
		FlightVelocity.P = (10 ^ 4)
		FlightVelocity.maxForce = (Vector3.new(1, 1, 1) * (10 ^ 6))
		FlightVelocity.Parent = Torso
		
		for i, v in pairs(Controls) do
			Controls[i].Value = 0
		end
		
		Humanoid.AutoRotate = false
		Humanoid.PlatformStand = true
		
		spawn(function()
			InvokeServer("ToggleSound", true)
		end)
		
		while Flying and CheckIfAlive() and ToolEquipped do

			--print(Humanoid.MoveDirection)
			
			local Camera = game:GetService("Workspace").CurrentCamera
			
			local CoordinateFrame = Camera.CoordinateFrame
			local Movement = Vector3.new(0, 0, 0)
			--[[local ControlVector = Vector3.new((Controls.Left.Value + Controls.Right.Value), (math.abs(Controls.Forward.Value) * 0.2), (Controls.Forward.Value + Controls.Backward.Value))
			if ControlVector.Magnitude > 0 then
				Movement = CoordinateFrame:vectorToWorldSpace(ControlVector.Unit * Speed.Current)
			end]]
			if Humanoid.MoveDirection.magnitude > 0 then
				local localControlVector = CFrame.new(Vector3.new(0,0,0),CoordinateFrame.lookVector*Vector3.new(1,0,1)):vectorToObjectSpace(Humanoid.MoveDirection+Vector3.new(0,.2,0))
				Movement = CoordinateFrame:vectorToWorldSpace(localControlVector.Unit * Speed.Current)
			end
			Momentum = ((Momentum * Inertia) + Movement)
			TotalMomentum = math.min(Momentum.Magnitude, Speed.Max)
			local MomentumPercent = (TotalMomentum / Speed.Max)
			if TotalMomentum > Speed.Max then
				TotalMomentum = Speed.Max
			end
			if Cloud then
				local Mesh = Cloud:FindFirstChild("Mesh")
				if Mesh then
					spawn(function()
						InvokeServer("SetMesh", MomentumPercent)
					end)
				end
			end
			spawn(function()
				InvokeServer("SetSound", MomentumPercent)
			end)
			local Tilt = ((Momentum * Vector3.new(1, 0, 1)).unit:Cross(((LastMomentum * Vector3.new(1, 0, 1)).unit))).y
			if tostring(Tilt) == "-1.#IND" or tostring(Tilt) == "1.#IND" or Tilt == math.huge or Tilt == -math.huge or tostring(0 / 0) == tostring(Tilt) then
				Tilt = 0
			end			
			local AbsoluteTilt = math.abs(Tilt)
			if AbsoluteTilt > 0.06 or AbsoluteTilt < 0.0001 then
				if math.abs(LastTilt) > 0.0001 then
					Tilt = (LastTilt * 0.96)
				else
					Tilt = 0
				end
			else
				Tilt = ((LastTilt * 0.9) + (Tilt * 0.1))
			end
			LastTilt = Tilt
			if Tilt > 0.01 then
				local Animation = Animations.RightTurn
				if Humanoid.RigType == Enum.HumanoidRigType.R15 then
					Animation = Animations.R15RightTurn
				end
				if LastAnimUsed ~= Animation then
					SetAnimation("StopAnimation", LastAnimUsed)
					SetAnimation("PlayAnimation", Animation)
					LastAnimUsed = Animation
				end
			elseif Tilt < -0.01 then
				local Animation = Animations.LeftTurn
				if Humanoid.RigType == Enum.HumanoidRigType.R15 then
					Animation = Animations.R15LeftTurn
				end				
				if LastAnimUsed ~= Animation then
					SetAnimation("StopAnimation", LastAnimUsed)
					SetAnimation("PlayAnimation", Animation)
					LastAnimUsed = Animation
				end
			else
				local Animation = Animations.CoastingPose
				if Humanoid.RigType == Enum.HumanoidRigType.R15 then
					Animation = Animations.R15CoastingPose
				end							
				if LastAnimUsed ~= Animation then
					SetAnimation("StopAnimation", LastAnimUsed)
					SetAnimation("PlayAnimation", Animation)
					LastAnimUsed = Animation
				end
			end
			
-- This is where rotation happens vvvvvv
			if TotalMomentum < 0.5 then
				Momentum = Vector3.new(0, 0, 0)
				TotalMomentum = 0
				FlightGyro.cframe = (CFrame.new(Vector3.new(0,0,0), (Camera.CoordinateFrame.lookVector * Vector3.new(1, 0, 1))) * CFrame.Angles(0, -(math.pi / 2), 0)) 
			else
				FlightGyro.cframe = (CFrame.new(Vector3.new(0,0,0), Momentum) * CFrame.Angles(0, -(math.pi / 2), 0) * CFrame.Angles((Tilt * -20),0,0))
			end

-- This is where rotation happens ^^^^^^^

			FlightVelocity.velocity = Momentum -- <- This is where the flight takes place. 
                      -- You can see above that they use some kind of math formula to get momentum, in which I can't comprehend. I think my goal is to be able to wright stuff like this.
			local GravityDelta = ((((Momentum * Vector3.new(0, 1, 0)) - Vector3.new(0, -Speed.Max, 0)).magnitude / Speed.Max) * 0.5)
			if GravityDelta > 0.45 then
			end
			
			LastMomentum = Momentum
			wait(Rate)
		end
		if CheckIfAlive() then
			Humanoid.AutoRotate = true
			Humanoid.PlatformStand = false
			Humanoid:ChangeState(Enum.HumanoidStateType.Freefall)
		end
		local Cloud = InvokeServer("Fly", {Flying = false})
		RemoveFlyStuff()
		Flying = false
	end
end

I used insert service to put it into my game for free.

3 Likes

Gravity delta looks like a linear curve ratio divided by speed max.

This probably generates an anti gravity force in a range of 0-1, 0 at no speed and 1 at max speed.

The formula for momentum just looks like explicit euler integration or before that just acceleration formulas SUVAT.

Velocity += acceleration*deltaTime

Not sure what inertia is.

There is some physics and maths concepts but you can use those concepts for your flying.

Or you can make assumptions like there is always an anti gravity force which simplifies it.

I’ve played around with the code, and basically inertia slows down the momentum when the player stops moving. I’ll follow your advice and just use the script modified.

That is what I basically did.
I imported it for free, then I just played with the code (because I didn’t understand it) and after adjusting different values, I sort of got the idea of what it was doing and was able to modify it for my own flying. It probably took me a week of playing with it to get it how I wanted. Eventually I was able to move it to its own module script, and even made a version that worked for custom swimming.
Good luck.