Making character face in the direction of where they are looking when flying

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    I want my character to be able to face up and face down when their cameras are looking up and down when flying.

  2. What is the issue? Include screenshots / videos if possible!
    My character is just staying “flat”

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I thought about using body gyros because I know it has something to do with rotation, but sadly I don’t know enough of how to do that. And the dev forums don’t really help me much either. I tried finding stuff about body gyros on YouTube, but they were very vague and didn’t address my problem.

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!
This is essentially what I want. This is from Ignite Games’ “Age of Heroes” on Roblox
This is what I want to achieve:

local player = game.Players.LocalPlayer
local char = player.Character or player.CharacterAdded:wait()

local camera = workspace.CurrentCamera
local UIS = game:GetService('UserInputService')

local idleAnim = char:WaitForChild('Humanoid'):LoadAnimation(script:WaitForChild('FlyingIdle'))
local flyingAnim = char:WaitForChild('Humanoid'):LoadAnimation(script:WaitForChild('FlyingMove'))

local isFlying = false
---movement keys---
local wPressed = false
local aPressed = false
local dPressed = false
local sPressed = false

--[Mouse stuff]--
local mouse = player:GetMouse()

	if blah then return end
	---[Press F to fly]---
	if key.KeyCode == Enum.KeyCode.F then
		if isFlying then --[If character is flying]
			isFlying = false
			char.Animate.Disabled = false
		elseif not isFlying then --[if they are not flying]
			isFlying = true
			char.Animate.Disabled = true 
			local bv ='BodyVelocity')
			bv.MaxForce =,math.huge,math.huge)
			bv.Name = 'FlightForce'
			bv.Velocity =,0,0)
			bv.Parent = char.HumanoidRootPart
			repeat wait(.1) until isFlying == false --[wait until not isFlying to destroy bv]
	---[Setting movement keys to true]---
	if key.KeyCode == Enum.KeyCode.W then
		wPressed = true
	elseif key.KeyCode == Enum.KeyCode.S then
		sPressed = true
	elseif key.KeyCode == Enum.KeyCode.A then
		aPressed = true
	elseif key.KeyCode == Enum.KeyCode.D then
		dPressed = true

UIS.InputEnded:connect(function(key,blah) --[The character is still flying bc isFlying is still true]
	if blah then return end
	if key.KeyCode == Enum.KeyCode.W then
		wPressed = false
		--print('no longer pressing w')
	elseif key.KeyCode == Enum.KeyCode.S then
		sPressed = false
		--print('no longer pressing s')
	elseif key.KeyCode == Enum.KeyCode.A then
		aPressed = false
		--print('no longer pressing a')
	elseif key.KeyCode == Enum.KeyCode.D then
		dPressed = false
		--print('no longer pressing d')

game:GetService("RunService").RenderStepped:Connect(function() --[runs every frame for a smoother version rather than wait()]
	if isFlying then
		char.HumanoidRootPart:FindFirstChild('FlightForce').Velocity =,0,0) --[Since w,a,s,d is not true yet, we don't move]
		--[Direction the character is facing and stuff]--
        --[This is where I tried a few solutions, but it's not what I wanted]--
		local MousePos= mouse.Hit.p
		local lookVector =,MousePos.Y,MousePos.Z)

		--char.HumanoidRootPart.CFrame = CFrame.lookAt(char.HumanoidRootPart.CFrame.p,camera.CFrame.LookVector)

		--[[local bg ="BodyGyro") -- Body Gyro that determines your rotation
		bg.MaxTorque =,400000,400000)
		bg.D = 10
		bg.CFrame =,lookVector)
		bg.Parent = char.HumanoidRootPart]]

		---[The main movement stuff]---
		if wPressed then
			char.HumanoidRootPart:FindFirstChild('FlightForce').Velocity = camera.CFrame.LookVector * 50

		elseif aPressed then
			char.HumanoidRootPart:FindFirstChild('FlightForce').Velocity = camera.CFrame.RightVector * -50
		elseif sPressed then
			char.HumanoidRootPart:FindFirstChild('FlightForce').Velocity = camera.CFrame.LookVector * -50
		elseif dPressed then
			char.HumanoidRootPart:FindFirstChild('FlightForce').Velocity = camera.CFrame.RightVector * 50

Hmm, about this so why not just make it so the character faces the way they are currently moving Instead of where the camera is looking. So instead of this CFrame towards the camera direction

local characterPosition =char.HumanoidRootPart.CFrame.Position
local charNextPosition = characterPosition + char.HumanoidRootPart.Velocity.Unit
char.HumanoidRootPart.CFrame = CFrame.lookAt(characterPosition,charNextPosition)

This should make the character look where they are currently going based on velocity.


How come you added char.HumanoidRootPart.Velocity.Unit to characterPosition?

1 Like

Oh boy vector maths, here is the diagram I drew in MSPaint please forgive me.


In order to make CFrame.lookAt work properly, we need two variables for now, One is the point where the character is looking at (lookAt) and the other is where the character is at or it’s position.

As seen I drew the Humanoid position vector which can be found using, which is the at position relative to the world origin in the diagram represented by the black arrow.

local characterPosition =char.HumanoidRootPart.CFrame.Position

The next vector we get is the velocity vector represented by the blue arrow.

In order to get the lookAt point relative to the world represented by the pink dot, we have to add these two vectors the blue velocity vector and the black position vector to draw the pink path line towards the pink lookAt Position.

There we can make the character face in the direction it is currently moving at using the CFrame.lookAt method. Hope this helps and I explained it properly.


That was the best explanation ever. I understand why you added it now! The diagram definitely helped the most. TY!