Can't assign new buttons to a script that controls a VectorForce in a vehicle

I am working on a simple spaceship which relies on VectorForce for movement, although I am not going to make the ship fully rely on physics and I will make it’s rotation handled by a gyro system so it doesn’t spin out of control, I already have a script which partially works.

The problem is, that script relies on standard controls of a VehicleSeat (WASD) and I can’t figure out how to add new buttons to the script, so I can for instance move up and down using the Q and E buttons- I have been trying to program in new functionality but it did not seem to impact the VectorForce in any way, I did also look at possible fixes in the Developer Hub but I did not succeed in finding anything that could help me out.

local seat = script.Parent
local model = seat.Parent
local core = model:FindFirstChild("core")

if not core then
	error("No 'core' part has been found in the model")
end

local force = core:FindFirstChild("VectorForce")

if not force then
	error("No VectorForce found in 'core'")
end

-- Function that changes VectorForce based on the seat throttle
local function updateForce()
	local throttle = seat.Throttle
	local steer = seat.Steer

	-- Throttle and steer forces or something
	
	local forceDirection = Vector3.new(0, 0, -throttle * 1000) -- Forward/Backward force
	local forceSteer = Vector3.new(steer * 500, 0, 0) -- Left/Right force

	force.Force = forceDirection + forceSteer
end

-- this connects the function to the seat's Changed effect

seat.Changed:Connect(function(property)
	if property == "Throttle" or property == "Steer" then
		updateForce()
	end
end)

-- Initialize the force
updateForce()

I imagine I should probably define every button like WASD as well as Q and E using Enum.KeyCode rather than partially relying on the built-in system and then relying on the other?

UserInputService is how you handle other inputs.

You can use a simple AlignOrientation class link (alternate AlignOrientation) to control the way the spaceship is Oriented.

Instead of having a function calling a function you could have just a single function running checking for seat.Changed.
To initialize the force set the variables and parameters at the beginning of the script.

I will try to use the UserInputService to handle inputs from the keyboard and assign new buttons. Would I have to also assign buttons to the AlignOrientation or is it handled in a different way? For instance, mouse etc. I have not dealt with something like that before, either way I will handle the rotation of the ship using a separate script.

would it work more or less like this? so far only the WASD movement has been defined, but of course adding the Q and E for up and down would be easy- I still did not get this to function properly

local seat = script.Parent
local part = seat.Parent:FindFirstChild("core")

-- Check if core exists
if not part then
	error("Could not find core.")
	return
end


local userInputService = game:GetService("UserInputService")
local vectorForce = part:FindFirstChildOfClass("VectorForce")
local forceMagnitude = 1000

-- This function here handles them seat change thingy
local function onSeatChanged(property)
	if property == "Occupant" then
		local occupant = seat.Occupant
		if occupant then
			-- This connects the occupant's inputs
			userInputService.InputBegan:Connect(function(input)
				if input.UserInputType == Enum.UserInputType.Keyboard then
					local force = Vector3.new()

					if input.KeyCode == Enum.KeyCode.W then
						force = Vector3.new(0, 0, 1)  -- Move forward
					elseif input.KeyCode == Enum.KeyCode.A then
						force = Vector3.new(-1, 0, 0)  -- Move left
					elseif input.KeyCode == Enum.KeyCode.S then
						force = Vector3.new(0, 0, -1)  -- Move backward
					elseif input.KeyCode == Enum.KeyCode.D then
						force = Vector3.new(1, 0, 0)  -- Move right
					end

					-- This should apply the forces
					if vectorForce then
						vectorForce.Force = force * forceMagnitude
					else
						warn("VectorForce component not found.")
					end
				end
			end)
		end
	end
end

-- Connect the seat's Changed event to the onSeatChanged function
seat.Changed:Connect(onSeatChanged)

You can still use the WASD keys from the vehicleseat, that’s easy enough.
You’d only have to use the Steer and Throttle inputs. to change your AlignOrientation.Force values.

Your forces are very very small, unless you define forceMagnitude as a large number.
Another issue is why set the force to 0 with vector3.new() as soon as the player keyboard input is used?

You just need to use the input service to get the Q and E inputs (or other keys if you need to). You also need to get the InputEnded if you want the forces to stop when the player stops pressing the keys.

1 Like

Would it be something along these lines? Although this one is a LocalScript placed directly in the PlayerGUI instead, which could introduce some issues if my game will have multiple ships, but ah well-

This is the script, a basic one to allow me to figure out how this is supposed to function, rather than instantly trying to implement it.

local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer

local seat = workspace:WaitForChild("VehicleSeat")

-- this function checks if the player is sitting in the seat (duh)
local function isPlayerSittingInSeat()
    if seat.Occupant then
        local character = player.Character
        if character and seat.Occupant == character:FindFirstChildOfClass("Humanoid") then
            return true
        end
    end
    return false
end

-- This function handles the singular key press
local function onKeyPress(input, gameProcessed)
    if not gameProcessed and input.KeyCode == Enum.KeyCode.Q then
        if isPlayerSittingInSeat() then
            print("Q key pressed while sitting in the seat!")
            -- I can add some action here afterwards
        end
    end
end

UserInputService.InputBegan:Connect(onKeyPress)

Looks good, that’s the way I’ve used it as well.

What I did was include a script for each type of construction vehicle since they use different controls.
I named each VehicleSeat according to the type of vehicle it was in which allows you to have more than 1 model of the same kind of vehicle as well.
For this example lets say this is the Crane script I used. The seat would be named CraneSeat.
In the ‘isPlayerSittingInSeat’ function I checked to see if the seat.Name is “CraneSeat” and if so then allow the script to run. If not then the scirpt ends.

1 Like

Alright, I actually got some basics working- I can’t figure out how to make the script work when I put the VectorForce and BodyGyro in a different part outside of the VehicleSeat, or if I group it- for whatever reason it causes an infinite yield or something so I’d rather avoid it, but I might just end up putting the part inside of the seat hierarchy wise rather than beside it in the same group-- but for now both are in the seat itself, I’m just happy that it works.

I will definitely need a script that makes the camera stick to the avatar itself rather than being bound to the world, it would make controlling the ship a whole lot easier.

Script for controlling the Gyro:

-- Services
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")

-- Variables
local seat = workspace:WaitForChild("VehicleSeat")
local gyro = seat:FindFirstChildOfClass("BodyGyro")

-- Function to check if the player is sitting in the seat
local function isPlayerSittingInSeat(player)
	if seat.Occupant then
		local character = player.Character
		if character and seat.Occupant == character:FindFirstChildOfClass("Humanoid") then
			return true
		end
	end
	return false
end

-- These here functions handle ship rotation (using the arrow keys, I'll add console controller inputs in the future)


-- Z AXIS (rotating left and right )

local function onKeyPressRight(input, gameProcessed)
	-- Only proceed if the input is not processed by the game and is the desired key
	if not gameProcessed and input.KeyCode == Enum.KeyCode.KeypadSix then
		local player = Players.LocalPlayer
		if isPlayerSittingInSeat(player) then
			gyro.CFrame = gyro.CFrame * CFrame.Angles(0, 0, math.rad(-15)) -- Rotate the ship -15 degrees on the Z axis
		end
	end
end

local function onKeyPressLeft(input, gameProcessed)
	-- Only proceed if the input is not processed by the game and is the desired key
	if not gameProcessed and input.KeyCode == Enum.KeyCode.KeypadFour then
		local player = Players.LocalPlayer
		if isPlayerSittingInSeat(player) then
			gyro.CFrame = gyro.CFrame * CFrame.Angles(0, 0, math.rad(15)) -- Rotate the ship -15 degrees on the Z axis
		end
	end
end

-- Y AXIS (turning left and right)

local function onKeyPressTurnR(input, gameProcessed)
	-- Only proceed if the input is not processed by the game and is the desired key
	if not gameProcessed and input.KeyCode == Enum.KeyCode.KeypadNine then
		local player = Players.LocalPlayer
		if isPlayerSittingInSeat(player) then
			gyro.CFrame = gyro.CFrame * CFrame.Angles(0, math.rad(-15), 0) -- Rotate the ship -15 degrees on the Y axis
		end
	end
end

local function onKeyPressTurnL(input, gameProcessed)
	-- Only proceed if the input is not processed by the game and is the desired key
	if not gameProcessed and input.KeyCode == Enum.KeyCode.KeypadSeven then
		local player = Players.LocalPlayer
		if isPlayerSittingInSeat(player) then
			gyro.CFrame = gyro.CFrame * CFrame.Angles(0, math.rad(15), 0) -- Rotate the ship 15 degrees on the Y axis
		end
	end
end

-- X AXIS (Rotating forward and backward)

local function onKeyPressBack(input, gameProcessed)
	-- Only proceed if the input is not processed by the game and is the desired key
	if not gameProcessed and input.KeyCode == Enum.KeyCode.KeypadTwo then
		local player = Players.LocalPlayer
		if isPlayerSittingInSeat(player) then
			gyro.CFrame = gyro.CFrame * CFrame.Angles(math.rad(15), 0, 0) -- Rotate the ship 15 degrees on the X axis
		end
	end
end

local function onKeyPressForward(input, gameProcessed)
	-- Only proceed if the input is not processed by the game and is the desired key
	if not gameProcessed and input.KeyCode == Enum.KeyCode.KeypadEight then
		local player = Players.LocalPlayer
		if isPlayerSittingInSeat(player) then
			gyro.CFrame = gyro.CFrame * CFrame.Angles(math.rad(-15), 0, 0) -- Rotate the ship -15 degrees on the X axis
		end
	end
end



-- Connect the input events
UserInputService.InputBegan:Connect(onKeyPressRight)
UserInputService.InputBegan:Connect(onKeyPressLeft)

UserInputService.InputBegan:Connect(onKeyPressTurnL)
UserInputService.InputBegan:Connect(onKeyPressTurnR)

UserInputService.InputBegan:Connect(onKeyPressBack)
UserInputService.InputBegan:Connect(onKeyPressForward)

And the script for controlling the elevation-

-- Services
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")

-- Variables
local seat = workspace:WaitForChild("VehicleSeat")
local vectorForce = seat:FindFirstChildOfClass("VectorForce")

-- Function to check if the player is sitting in the seat
local function isPlayerSittingInSeat(player)
	if seat.Occupant then
		local character = player.Character
		if character and seat.Occupant == character:FindFirstChildOfClass("Humanoid") then
			return true
		end
	end
	return false
end


-- Q


local function onKeyPressQ(input, gameProcessed)
	-- Only proceed if the input is not processed by the game and is the desired key
	if not gameProcessed and input.KeyCode == Enum.KeyCode.Q then
		local player = Players.LocalPlayer
		if isPlayerSittingInSeat(player) then
			vectorForce.Force = Vector3.new(0, -5000, 0)
		end
	end
end
local function onKeyReleaseQ(input, gameProcessed)
	-- Only proceed if the input is not processed by the game and is the desired key
	if not gameProcessed and input.KeyCode == Enum.KeyCode.Q then
		local player = Players.LocalPlayer
		if isPlayerSittingInSeat(player) then
			vectorForce.Force = Vector3.new(0, 0, 0)
		end
	end
end


--E


local function onKeyPressE(input, gameProcessed)
	-- Only proceed if the input is not processed by the game and is the desired key
	if not gameProcessed and input.KeyCode == Enum.KeyCode.E then
		local player = Players.LocalPlayer
		if isPlayerSittingInSeat(player) then
			vectorForce.Force = Vector3.new(0, 5000, 0)
		end
	end
end
local function onKeyReleaseE(input, gameProcessed)
	-- Only proceed if the input is not processed by the game and is the desired key
	if not gameProcessed and input.KeyCode == Enum.KeyCode.E then
		local player = Players.LocalPlayer
		if isPlayerSittingInSeat(player) then
			vectorForce.Force = Vector3.new(0, 0, 0)
		end
	end
end

-- Connect the input events
UserInputService.InputBegan:Connect(onKeyPressQ)
UserInputService.InputEnded:Connect(onKeyReleaseQ)

UserInputService.InputBegan:Connect(onKeyPressE)
UserInputService.InputEnded:Connect(onKeyReleaseE)

If anything I can improve upon them further!

Nice!
A vehicleseat should normally make the camera move back to behind the player after they right mouse move the camera or if the seat rotates.
I can’t remember if there’s a setting in the seat for the camera property.

I’ve decided to make it so the camera is locked in first person when the character is sitting, so far it makes me unable to look around at all while sitting but definitely makes either piloting ships or using my jetpack tool a lot easier! It um, is necessary to get up properly as my custom gravity system is quite janky, I will likely make the game first person only though as it will hide most of what’s going on with one’s avatar. I won’t go into detail but it’s really quite a headache lol, either way I am very thankful for the help!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.