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