How To Make A Character Fly

I would like to give characters the ability to fly in the air. How would I go about doing this?

  1. I would like the character to be able to fly by hitting the jump button for example.

  2. I will need to override the default “falling” animation.

  3. When the character lands on the ground, they should be able to resume walking.

Thanks for any suggestions.

73 Likes

I don’t know quite how new you are to scripting, so I’ll assume you understand code but don’t know the specifics.

First things first, you need to get the UserInputService. Easy!

local uis = game:GetService("UserInputService")

This gets all the things the UIS can do for us.

You then need to make it so that it detects when the user has pressed the key desired. Again, this isn’t really all too difficult.

uis.InputBegan:connect(function(input)
	if input.KeyCode == Enum.KeyCode.Space then
		-- Do something
	end
end)

Next up, you’ll need a function for flying that is called whenever your user presses the space bar.

We’ll call this function “Fly”

function fly()
end

This is going to be the bulk of your code, and I’ll write a fairly quick example of how you could write the flying “physics”.

First things first, you need a few variables set up. I’ll lay them all out here:

local myPlayer = game.Players.LocalPlayer
local myChar = myPlayer.Character
local myHRP = myChar:WaitForChild("HumanoidRootPart")

local bp = Instance.new("BodyPosition", myHRP) -- Body Position that determines your location
bp.MaxForce = Vector3.new()
bp.D = 10
bp.P = 10000

local bg = Instance.new("BodyGyro", myHRP) -- Body Gyro that determines your rotation
bg.MaxTorque = Vector3.new()
bg.D = 10

local flying = false -- Determines if you're in flight or not
local rs = game:GetService("RunService") -- Look me up
local camera = game.Workspace.CurrentCamera
local speed = 0.5 -- Speed of flight is kind of determined by this

And now the function can be written:

function fly()
	flying = true
	bp.MaxForce = Vector3.new(400000,400000,400000)
	bg.MaxTorque = Vector3.new(400000,400000,400000)
	while flying do
		rs.RenderStepped:wait()
		bp.Position = myHRP.Position +((myHRP.Position - camera.CFrame.p).unit * speed)
		bg.CFrame = CFrame.new(camera.CFrame.p, myHRP.Position)
	end
end

But this will force you to fly forever. You’ll need another function that lets you stop the person from flying. I’ll wrap up everything together now!

The end code looks a lil’ like this:

local uis = game:GetService("UserInputService")
local rs = game:GetService("RunService")

local myPlayer = game.Players.LocalPlayer
local myChar = myPlayer.Character
local myHRP = myChar:WaitForChild("HumanoidRootPart")
local camera = game.Workspace.CurrentCamera

local flying = false
local speed = 0.5


local bp = Instance.new("BodyPosition", myHRP)
bp.MaxForce = Vector3.new()
bp.D = 10
bp.P = 10000

local bg = Instance.new("BodyGyro", myHRP)
bg.MaxTorque = Vector3.new()
bg.D = 10

function fly()
	flying = true
	bp.MaxForce = Vector3.new(400000,400000,400000)
	bg.MaxTorque = Vector3.new(400000,400000,400000)
	while flying do
		rs.RenderStepped:wait()
		bp.Position = myHRP.Position +((myHRP.Position - camera.CFrame.p).unit * speed)
		bg.CFrame = CFrame.new(camera.CFrame.p, myHRP.Position)
	end
end

function endFlying()
	bp.MaxForce = Vector3.new()
	bg.MaxTorque = Vector3.new()
	flying = false
end

uis.InputBegan:connect(function(input)
	if input.KeyCode == Enum.KeyCode.Space then
		if not flying then
			fly()
		else
			endFlying()
		end
	end
end)

You wanted to also add in animations, and apparently make it so that if you touch the ground, you stop flying. The former is simple. Look up loading animations into a humanoid and then playing them.

Looks a bit like this:

local hum = char:WaitForChild("Humanoid") --the npc's humanoid
local animation = hum:LoadAnimation(script.Animation) -- Should be an animation object inside the script
animation:Play() --plays the animation

The touching the ground can be done in two ways. You could either set a .Touched event for the HRP which triggers stop flying, or alternatively you could do a continuous raycast check whilst flying. I wouldn’t recommend the latter if you’re worried about performance, though.

I hope this helps :slight_smile:

163 Likes

Better way is https://wiki.roblox.com/index.php?title=API:Enum/HumanoidStateType

9 Likes

Amazing post. Thank you so much for taking the time to write all of this out!

5 Likes

I was going to post a big response like @Zarkonan_Zenheart, but he beat me to it. Regardless I made up a placefile that I was going to post so you can use that as a reference as well.

fly.rbxl (14.5 KB)

65 Likes

This is great. Thank you very much for posting this file.

6 Likes

No problem aha. This specific problem and I go wayyyy back, because I’ve always been fascinated by flight and yet I’ve never known how to script it. Hopefully it’ll be of some help to you, and if not, at least I can tip my hat to @EgoMoose for teaching me the maths required to make the script I posted. Thanks Ego :stuck_out_tongue:

14 Likes

As always, hats off to @EgoMoose for his dedication to teaching us stuff!
Too bad all his old forum posts are gone…

5 Likes

Interestingly, I noticed that if I remove all the BodyGyro code, then everything still seems to work just fine. So is there any reason to even need a BodyGyro?

2 Likes

Well the BodyGyro allows for pitch rotation of the character with the camera. If you want the player to be able to rotate only their camera when not moving it’s a simple adjustment.

  1. Adjust the body gyro values (optional)
bodyGyro.D = 500;
bodyGyro.P = 10^4;
  1. Make isMoving accessible to other functions
local isFlying = false;
local isJumping = false;
local isMoving = false;

local function movementBind(actionName, inputState, inputObject)
	-- ...
	isMoving = movement.right + movement.left + movement.forward + movement.backward > 0;
end
  1. Only set BodyGyro.CFrame to a new value when moving
local function onUpdate(dt)
	if (isFlying) then
		local cf = camera.CFrame;
		-- ...
		bodyGyro.CFrame = isMoving and cf or bodyGyro.CFrame;
	end
end

16 Likes

This is ALL server right? Or is it local, and any effects are done through server?

3 Likes

Based On LocalPlayer, I would have to say this is on local.

3 Likes

He’s correct in saying it’s all local. Almost everything involving character movement should be handled on the client.

3 Likes

I have remixed your fly script, so you change your fly status easier. Here’s my project if somebody is interested: flyRemixedJm.rbxl (28.6 KB)

Edit: The [fly] key is now set to R by default since F doesn’t always work. You can change the [fly] key to your desired key by modifying the variable located at the beginning of the script.

5 Likes

but that might result in big exploits.
but whatever we do there are going to be exploits lol.

1 Like

you don’t want to have that lag effect when flying, response time etc.
anyways normal exploits can already make you fly, physics of their character are on their client. that’s in every game, but you can check sudden movements in position on server with a whitelist of users who can fly. the same counts for teleport scripts.

Edit:
Anything that replicates from client to server can be exploited, roblox automatically replicates the position of your character
Exploiters can also abuse other things that replicate like they can move their accessories to workspace and they will be stuck there forever
They can also touch moving objects to gain network ownership and teleport those objects, that means their client hosts the physics of those objects

It’s the best to try and detect anything suspicious, and then undo their exploit or kick them, or even ban them. I would not recommend banning a user if the exploit detection is sensitive.

Yet another edit:
I would only make anti-exploits if the exploit can harm other’s gameplay. But make sure to add anti exploits if you have games where you have to move alot to collect “coins” for example, exploiters can just teleport themselves to those “coins” and cheat their way through. Especially if your game contains a trading system.

2 Likes

So there is a bug where 2 animation overlap when you begin to fly if anyone needs this fix here is the code
Put this in Line 62
for i, v in pairs(humanoid:GetPlayingAnimationTracks()) do
v:Stop()
end

sorry i forgot how to put it into code

How do i make it so i can add more animations

I’m not on my PC now, but as I said, I made a remix of what have @EgoMoose done. The only change in my Script is that you can fly with F key and not 2x Jump (it was buggy for me so that’s why I changed it).

Edit: there is much more changes in the current version.

ok ill ask egomoose when he comes online