How would I get a direction to be relative to the camera?

i’m making a flight controller. trying to explain my predicament is a bit challenging, but what i want is:

  • player presses W, A, S, or D
  • this moves them forward, backward, left, or right, but relative to the direction that the camera is facing, much like roblox’s default movement

i’m trying to figure out how to actually calculate the direction that i need, because right now, when i move left or right while looking forward, i cannot move at all. i have no idea what i could be doing wrong.

hopefully this diagram accurately describes my issue:

my script so far:

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local UserInputService = game:GetService("UserInputService")

local client = Players.LocalPlayer
local character = client.Character or client.CharacterAdded:Wait()
local root = character.PrimaryPart
local velocity = root:FindFirstChildWhichIsA("BodyVelocity")
local default_velocity = Vector3.new(0, 0.45, 0)

local camera = workspace.CurrentCamera
local mouse = client:GetMouse()
local multiplier = 100

-- disabling controls
local player_scripts = client.PlayerScripts
local player_module = require(player_scripts:WaitForChild("PlayerModule"))
local controls = player_module:GetControls()
controls:Disable()

-- general data, includes keybind mapping
local action_data = {
	forward = {
		updates = true,
		keybind = Enum.KeyCode.W,
		action = function(cam_dir)
			local total_dir = (cam_dir * Vector3.new(0, 0, 1))
			velocity.Velocity = total_dir * multiplier
		end,
	},

	backward = {
		updates = true,
		keybind = Enum.KeyCode.S,
		action = function(cam_dir)
			local total_dir = (cam_dir * Vector3.new(0, 0, -1))
			velocity.Velocity = total_dir * multiplier
		end,
	},

	left = {
		updates = true,
		keybind = Enum.KeyCode.A,
		action = function(cam_dir)
			local total_dir = (cam_dir * Vector3.new(1, 0, 0))
			velocity.Velocity = total_dir * multiplier
		end,
	},

	right = {
		updates = true,
		keybind = Enum.KeyCode.D,
		action = function(cam_dir)
			local total_dir = (cam_dir * Vector3.new(-1, 0, 0))
			velocity.Velocity = total_dir * multiplier
		end,
	},

	upward = {
		updates = true,
		keybind = Enum.KeyCode.Q,
		action = function(cam_dir)
			local total_dir = (cam_dir * Vector3.new(0, 1, 0))
			velocity.Velocity = total_dir * multiplier
		end,
	},

	downward = {
		updates = true,
		keybind = Enum.KeyCode.E,
		action = function(cam_dir)
			local total_dir = (cam_dir * Vector3.new(0, -1, 0))
			velocity.Velocity = total_dir * multiplier
		end,
	},

	detach_wings = {
		updates = false,
		keybind = Enum.KeyCode.F,
		action = function(cam_dir)
			print("detaching wings")
		end,
	}
}

-- helper function to find action by key
local function find_action(key_code)
	for _, action in pairs(action_data) do
		if action.keybind == key_code then
			return action
		end
	end
	return nil
end

-- keep track of active connections for each key
local active_connections = {}

local function handle_action(action, key_code)
	local cam_dir = camera.CFrame.LookVector
	action.action(cam_dir)

	if action.updates and not active_connections[key_code] then
		active_connections[key_code] = RunService.RenderStepped:Connect(function()
			local cam_dir = camera.CFrame.LookVector
			action.action(cam_dir)
		end)
	end
end

UserInputService.InputBegan:Connect(function(input, game_process)
	if game_process then return end

	local action = find_action(input.KeyCode)
	if action and action.action then
		handle_action(action, input.KeyCode)
	end
end)

UserInputService.InputEnded:Connect(function(input, game_process)
	if game_process then return end

	local action = find_action(input.KeyCode)
	if action and active_connections[input.KeyCode] then
		active_connections[input.KeyCode]:Disconnect()
		active_connections[input.KeyCode] = nil
		velocity.Velocity = default_velocity
		-- i don't know, i'm just a comment
	end
end)

how it turned out (less than ideal, the calculated directions are iffy and inaccurate):

please ignore the typo in the place name i know it’s dumb

1 Like

I guess you could use Humanoid.MoveDirection

Idk I’m kinda confused too about what you wanna accomplish

1 Like

i don’t think that will help, as i’ve disabled the player’s controls.

1 Like

Yikes idk well if you wanna get a direction relative to the camera then maybe you can use Vector3:Cross and get a dot product based on what action they perform…