As a developer, it’s not possible to use seats in games where jumping is disabled. Not all games are platformers – some, such as Brick Bronze, disable jumping entirely to craft their own experience. In these types of games, seats cannot be used because seats require players to jump to exit the seat.
A Solution:
I was thinking that when the Jumping state of Humanoids was disabled, we could just destroy the joint and let them walk away without triggering a jump. Upon further thinking, I was wondering why characters jump to leave seats in the first place. It doesn’t really make sense for characters to jump out of a seat – normal people just stand up.
Regardless of whether the jump state is disabled or not, exiting a seat should not initiate a jump. It should just disconnect the character from the seat, and humanoids can automatically shift the character up as they would do if they were clipping into something, or seats can manually move the character up to the standing position.
It would probably be a good idea to look into how this would affect existing games though, to ensure they wouldn’t break. We would also need a way to prevent characters from leaving seats since it would no longer be possible to prevent them by disabling the jumping state.
local player = game.Players.LocalPlayer
repeat wait() until player.Character
local hum = player.Character:WaitForChild("Humanoid")
game:GetService("UserInputService").JumpRequest:connect(function()
if hum.Sit then
hum.JumpPower = 50
wait()
hum.JumpPower = 0
end
end)
Kind of hacky but if anyone is having this problem, there’s a quick local-script workaround.
I agree that jumping out of a seat is weird behavior though.
If memory serves, the ControlScripts simply set Jump to true when you give it jump input. For those inclined, they could change this behavior so that if Sit is true, set it to false instead of setting jump to true.
EDIT: The principle is sound. Setting Sit to false will make players detach from the seat. However, this does not play well with the way ROBLOX handles jump input. Specifically, any frame the jump command is given and the humanoid is allowed to jump (not falling, not already jumping), it will. Basically, you detach from the seat in frame 1, and immediately begin jumping in frame 2, so there’s no net change in behavior.
There are 2 possibilities to fix this: disable the jump command when alighting so players have to let go and press the jump key again to begin jumping, or abstract the jump command and disable the abstracted command for a period of time after alighting.
local player = game.Players.LocalPlayer
repeat wait() until player.Character
local hum = player.Character:WaitForChild("Humanoid")
hum:SetStateEnabled(Enum.HumanoidStateType.Jumping, false)
game:GetService("UserInputService").JumpRequest:connect(function()
if hum.Sit then
hum.Sit = false
end
end)
Yup. I had to wait 0.2 seconds before allowing the player to jump again. This kind of works for desired behavior, right?
local player = game.Players.LocalPlayer
repeat wait() until player.Character
local hum = player.Character:WaitForChild("Humanoid")
game:GetService("UserInputService").JumpRequest:connect(function()
local oldJumpPower = hum.JumpPower
if hum.Sit then
hum.JumpPower = 0
hum.Sit = false
wait(0.2)
hum.JumpPower = oldJumpPower
end
end)
So, I went the abstracted boolean route and got this far. This is a replacement for the MasterControl module which should fully enable people to have seats and no jumping.
It works well except for one critical bug: if you sit in a seat when isJumping is true, the SeatPart will not update accordingly and you will be unable to sit or jump until you reset.
Further modifications include public API to enable the dismount behavior and having the dismount behavior disabled by default, with the idea that this could be a PR to the Actual Real Repo.
--[[
// FileName: MasterControl
// Version 1.0
// Written by: jeditkacheff
// Description: All character control scripts go thru this script, this script makes sure all actions are performed
--]]
-- [[ Constants ]]--
local ZERO_VECTOR3 = Vector3.new(0, 0, 0)
local STATE_JUMPING = Enum.HumanoidStateType.Jumping
local STATE_FREEFALL = Enum.HumanoidStateType.Freefall
local STATE_LANDED = Enum.HumanoidStateType.Landed
--[[ Local Variables ]]--
local MasterControl = {}
local Players = game:GetService('Players')
local RunService = game:GetService('RunService')
local VRService = game:GetService('VRService')
local VREnabled = VRService.VREnabled
while not Players.LocalPlayer do
Players.PlayerAdded:wait()
end
local LocalPlayer = Players.LocalPlayer
local LocalCharacter = LocalPlayer.Character
local CachedHumanoid = nil
local isJumping = false
local lastDismount = 0
local moveValue = Vector3.new(0, 0, 0)
local isJumpEnabled = true
local areControlsEnabled = true
local dismountDebounceTime = 0.333
--[[ Local Functions ]]--
function MasterControl:GetHumanoid()
if LocalCharacter then
if CachedHumanoid then
return CachedHumanoid
else
CachedHumanoid = LocalCharacter:FindFirstChildOfClass("Humanoid")
return CachedHumanoid
end
end
end
VRService.Changed:connect(function(prop)
if prop == "VREnabled" then
VREnabled = VRService.VREnabled
end
end)
local characterAncestryChangedConn = nil
local characterChildRemovedConn = nil
local function characterAdded(character)
if characterAncestryChangedConn then
characterAncestryChangedConn:disconnect()
end
if characterChildRemovedConn then
characterChildRemovedConn:disconnect()
end
LocalCharacter = character
CachedHumanoid = LocalCharacter:FindFirstChildOfClass("Humanoid")
characterAncestryChangedConn = character.AncestryChanged:connect(function()
if character.Parent == nil then
LocalCharacter = nil
else
LocalCharacter = character
end
end)
characterChildRemovedConn = character.ChildRemoved:connect(function(child)
if child == CachedHumanoid then
CachedHumanoid = nil
end
end)
end
if LocalCharacter then
characterAdded(LocalCharacter)
end
LocalPlayer.CharacterAdded:connect(characterAdded)
local getHumanoid = MasterControl.GetHumanoid
local moveFunc = LocalPlayer.Move
local getUserCFrame = VRService.GetUserCFrame
local updateMovement = function()
if not areControlsEnabled then return end
local recentlyDismounted = lastDismount+dismountDebounceTime >= tick()
local humanoid = getHumanoid()
if not humanoid then return end
--print("isJumpEnabled",isJumpEnabled,"isJumping",isJumping,"PlatformStand",humanoid.PlatformStand,"SeatPart",humanoid.SeatPart)
if isJumping and humanoid.SeatPart then
humanoid.Sit = false
lastDismount = tick()
elseif isJumpEnabled and isJumping and not humanoid.PlatformStand and not recentlyDismounted then
local state = humanoid:GetState()
if state ~= STATE_JUMPING and state ~= STATE_FREEFALL and state ~= STATE_LANDED then
humanoid.Jump = isJumping
end
end
local adjustedMoveValue = moveValue
if VREnabled and workspace.CurrentCamera.HeadLocked then
local vrFrame = getUserCFrame(VRService, Enum.UserCFrame.Head)
local lookVector = Vector3.new(vrFrame.lookVector.X, 0, vrFrame.lookVector.Z).unit
local rotation = CFrame.new(ZERO_VECTOR3, lookVector)
adjustedMoveValue = rotation:vectorToWorldSpace(adjustedMoveValue)
end
moveFunc(LocalPlayer, adjustedMoveValue, true)
end
local function manualDismount()
local humanoid = getHumanoid()
if not humanoid then return end
if humanoid.SeatPart then
humanoid.Sit = false
lastDismount = tick()
end
end
local function manualJump()
local humanoid = getHumanoid()
if not humanoid then return end
if lastDismount+dismountDebounceTime < tick() and not humanoid.PlatformStand then
humanoid.Jump = isJumping
end
end
--[[ Public API ]]--
function MasterControl:Init()
RunService:BindToRenderStep("MasterControlStep", Enum.RenderPriority.Input.Value, updateMovement)
end
function MasterControl:Enable()
areControlsEnabled = true
isJumpEnabled = true
if self.ControlState.Current then
self.ControlState.Current:Enable()
end
end
function MasterControl:Disable()
if self.ControlState.Current then
self.ControlState.Current:Disable()
end
--After current control state is disabled, moveValue has been set to zero,
--Call updateMovement one last time to make sure this propagates to the engine -
--Otherwise if disabled while humanoid is moving, humanoid won't stop moving.
updateMovement()
isJumping = false
areControlsEnabled = false
end
function MasterControl:EnableJump()
isJumpEnabled = true
if areControlsEnabled and self.ControlState:IsTouchJumpModuleUsed() then
self.TouchJumpModule:Enable()
end
end
function MasterControl:DisableJump(affectGui)
isJumpEnabled = false
if affectGui and self.ControlState:IsTouchJumpModuleUsed() then
self.TouchJumpModule:Disable()
end
end
function MasterControl:AddToPlayerMovement(playerMoveVector)
moveValue = Vector3.new(moveValue.X + playerMoveVector.X, moveValue.Y + playerMoveVector.Y, moveValue.Z + playerMoveVector.Z)
end
function MasterControl:GetMoveVector()
return moveValue
end
function MasterControl:SetIsJumping(jumping)
manualDismount()
if not isJumpEnabled then return end
isJumping = jumping
if jumping then
manualJump()
end
end
function MasterControl:DoJump()
manualDismount()
if not isJumpEnabled then return end
manualJump()
end
function MasterControl:SetDismountDebounce(amount)
dismountDebounceTime = amount
end
return MasterControl