Humanoid seated bug

so im trying to make a script for a ball that when it touches the player it basically sends him flying in seated mode and it works well, only thing is the player is stuck in the seated mode and dosent want to get up even if i smash jump button multiple times

local parentPart = script.Parent -- The part you want to use as the trigger

-- Function to send the player flying in seated mode
local function sendPlayerFlying(player)
	local character = player.Character
	if character then
		local humanoid = character:FindFirstChildOfClass("Humanoid")
		if humanoid then
			-- Force the player into seated mode
			humanoid.Sit = true
			humanoid.PlatformStand = true -- Prevents the player from getting up
			humanoid.Jump = false -- Disable jumping
			humanoid:SetStateEnabled(Enum.HumanoidStateType.Seated, true) -- Enable sitting
			local launchDirection = (character.PrimaryPart.Position - parentPart.Position).unit * 100 -- Adjust the force as needed
			humanoid:Move(launchDirection) -- Apply the force
			wait(2) -- Wait for 2 seconds
			humanoid.PlatformStand = false -- Allows the player to be moved by physics
			wait(3) -- Wait for an additional 3 seconds before allowing the player to stand up

			-- Ensure that the player is not in a sitting state
			humanoid.Sit = false

			-- Wait for a short delay before allowing jumping
			wait(0.5)

			-- Re-enable jumping
			humanoid.Jump = true
		end
	end
end

-- Function to handle the touch event
local function onTouch(other)
	local player = game.Players:GetPlayerFromCharacter(other.Parent)
	if player then
		sendPlayerFlying(player)
	end
end

-- Connect the touch event
parentPart.Touched:Connect(onTouch)

Have you tried printing the properties in the output window after you change them?

I wasn’t able to replicate that issue when testing the code in either server-sided or client-sided scripts. In fact, I observed the opposite issue occurring, where the Character was able to stand up and jump before the function had concluded, which was most likely because of the following:

humanoid.Sit = true

humanoid.PlatformStand = true --[[ This overrides the humanoid.Sit property
because only one can be enabled at a time; if Sit is true, PlatformStand will
be false. If PlatformStand is true, Sit will be false.
You can test this by running a playtest, swapping the current simulation view
in the Test tab from "Current: Client" to "Current: Server", opening up the
Workspace, opening up the Character model, then selecting the Humanoid.
Enable one of the properties (either Sit or PlatformStand). Then, enable the
other property and observe how the first one you enabled is turned off.
--]]

humanoid.Jump = false --[[ This doesn't disable jumping; this property is 
false when the Character is not jumping,
and it's true when the Character begins to jump.
--]]

humanoid:SetStateEnabled(Enum.HumanoidStateType.Seated, true) --[[ This makes
it possible for the Humanoid to enter the "Seated" HumanoidStateType.
This doesn't force the Character to sit. As a result, it would make more 
sense to include this before setting the Humanoid's Sit property to true
(however, this HumanoidStateType* is never permanently set to false
in the first place, so this probably isn't necessary).
--]]

...

humanoid.PlatformStand = false --[[ Because PlatformStand is set to false,
the Character is now free to move around
--]]

wait(3)

humanoid.Sit = false --[[ This didn't change anything because the
Sit property was automatically set to false earlier when
PlatformStand was enabled
--]]

wait(0.5)

-- This doesn't re-enable jumping; this makes the Character jump once
humanoid.Jump = true

In addition to that, because there was no debounce created for the function, there’s a high likelihood that the function could have been run multiple times in a row due to the Touched event being repeatedly fired in quick succession (which could cause unintended behavior to occur).

I tested the code and included a print statement at the end, and after the first print statement appeared, it tended to print it out several more times (in addition to causing the Character to jump several times because of the humanoid.Jump = true that was included).


I also noticed moments where the server script would try to set Humanoid.PlatformStand to true while the Character was mid-jump but it didn’t actually take effect. However, when moving this to the client side, it consistently enabled PlatformStand, even if the Character was mid-jump.

It makes sense that it’s more consistent on the client based on what’s mentioned on the Roblox Creator Documentation page for each of the HumanoidStateTypes:

Some states only allow manual setting, and allow a developer to make the Humanoid relinquish control of its character.

When altering the Humanoid of a player, this should be done from a LocalScript ran by that player on their local client. Certain states only work when set by the owner process (client or server). (Dead for example)


Although I was not able to replicate the issue described in the original post, here’s what I would recommend trying to simultaneously solve that issue and to avoid other unintended behavior from happening:

  • Create a debounce for the sendPlayerFlying function (on a per-player basis) to ensure that the majority of its code won’t run again until it finishes running for the first time.

  • Update the PlatformStand property and the HumanoidStateType for Jumping via the client ( with the latter being done through Humanoid:SetStateEnabled() ) to ensure that the changes actually go into effect (the example revisions will also include a safeguard of sorts to try to force PlatformStand to true if the HumanoidStateType somehow happens to be set to something such as Jumping or Running before the Character is supposed to be able to be able to control itself again).

  • Don’t update the Humanoid.Jump property to true at the end of the function (since that will just make the Character jump on its own).

Example Revision #1

-- Server Script in the Part for Example Revision #1
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local RemoteEvent = ReplicatedStorage.RemoteEvent --[[ Make sure to create a new RemoteEvent in the ReplicatedStorage for this.
If you change its name, make sure to change it here as well as the reference to it in the LocalScript code
--]]
local parentPart = script.Parent

local playerDebounce = {}
local function sendPlayerFlying(player)
	if playerDebounce[player] ~= nil then print("debounce true for "..player.Name) return end
	
	playerDebounce[player] = true
	
	local Character = player.Character or player.CharacterAdded:Wait()
	if Character then
		local Humanoid = Character:FindFirstChildOfClass("Humanoid")
		if Humanoid then
			
			local connection
			connection = Humanoid.StateChanged:Connect(function(old, new)				
				if new ~= Enum.HumanoidStateType.PlatformStanding then -- Extra precaution to re-enable PlatformStand if it gets turned off before it's supposed to
					Humanoid.PlatformStand = true
					warn("Updated PlatformStand")
				end
			end)
			
			RemoteEvent:FireClient(player, Enum.HumanoidStateType.Jumping, false)
			RemoteEvent:FireClient(player, Enum.HumanoidStateType.Running, false)
			RemoteEvent:FireClient(player, Enum.HumanoidStateType.PlatformStanding, true)

--[[
If you want to really make sure the Character cannot stand back up until all of the "cooldowns"
have concluded, also set Enum.HumanoidStateType.Running to false and then set it back to true the same
time that Enum.HumanoidStateType.Jumping is re-enabled.

Otherwise, feel free to remove these two lines of code from the script:
(Line #30) RemoteEvent:FireClient(player, Enum.HumanoidStateType.Running, false)
(Line #56) RemoteEvent:FireClient(player, Enum.HumanoidStateType.Running, true)
--]]

			local launchDirection = (Character.PrimaryPart.Position - parentPart.Position).unit * 100
			Humanoid:Move(launchDirection)
			task.wait(2)
			
			connection:Disconnect()
			connection = nil
			
			RemoteEvent:FireClient(player, Enum.HumanoidStateType.PlatformStanding, false)
			warn("PlatformStand has been disabled")
			
			task.wait(3.5)
			
			RemoteEvent:FireClient(player, Enum.HumanoidStateType.Jumping, true)
			RemoteEvent:FireClient(player, Enum.HumanoidStateType.Running, true)
			warn("Jumping has been re-enabled")
		end
	end
	
	print("Setting debounce to false for "..player.Name)
	playerDebounce[player] = nil
end

local function onTouch(other)
	local player = Players:GetPlayerFromCharacter(other.Parent)
	if player then
		sendPlayerFlying(player)
	end
end

parentPart.Touched:Connect(onTouch)

And there would also be a new client-sided script for this example revision:

-- LocalScript in StarterPlayerScripts for Example Revision #1
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local player = Players.LocalPlayer
local RemoteEvent = ReplicatedStorage.RemoteEvent

RemoteEvent.OnClientEvent:Connect(function(humanoidStateType, newValue)
	local Character = player.Character or player.CharacterAdded:Wait()
	local Humanoid = Character:WaitForChild("Humanoid")
	
	if Character and Humanoid then
		if humanoidStateType == Enum.HumanoidStateType.PlatformStanding then
			Humanoid.PlatformStand = newValue
--[[ We're manually updating the property instead of using ChangeState here
because the Roblox Creator Documentation for Humanoid:ChangeState() says that:
"As it is unused, setting the state to Enum.HumanoidStateType.PlatformStanding
will cause the humanoid state to be automatically set to Enum.HumanoidStateType.Running."
--]]
		else
			Humanoid:SetStateEnabled(humanoidStateType, newValue)
		end
	end
end)

Example Revision #2

If you were to handle everything via a client-sided script, here’s what an example revision could look like for that:

-- Script (with RunContext property set to "Client") in the Part for Example Revision #2
local Players = game:GetService("Players")
local LocalPlayer = Players.LocalPlayer

local parentPart = script.Parent

local debounce = false

local function sendPlayerFlying()
	if debounce == true then print("debounce true for "..LocalPlayer.Name) return end
	
	debounce = true
		
	local Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
	if Character then
		local Humanoid = Character:FindFirstChildOfClass("Humanoid")
		if Humanoid then
				
			local connection
			connection = Humanoid.StateChanged:Connect(function(old, new)				
				if new ~= Enum.HumanoidStateType.PlatformStanding then -- Extra precaution to re-enable PlatformStand if it gets turned off before it's supposed to
					Humanoid.PlatformStand = true
					warn("Updated PlatformStand")
				end
			end)

			Humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, false)
			Humanoid:SetStateEnabled(Enum.HumanoidStateType.Running, false)
			Humanoid.PlatformStand = true

--[[
If you want to really make sure the Character cannot stand back up until all of the "cooldowns"
have concluded, also set Enum.HumanoidStateType.Running to false and then set it back to true the same
time that Enum.HumanoidStateType.Jumping is re-enabled.

Otherwise, feel free to remove these two lines of code from the script:
(Line #28) Humanoid:SetStateEnabled(Enum.HumanoidStateType.Running, false)
(Line #54) Humanoid:SetStateEnabled(Enum.HumanoidStateType.Running, true)
--]]

			local launchDirection = (Character.PrimaryPart.Position - parentPart.Position).unit * 100
			Humanoid:Move(launchDirection)
			task.wait(2)
				
			connection:Disconnect()
			connection = nil
				
			Humanoid.PlatformStand = false
			warn("PlatformStand has been disabled")
				
			task.wait(3.5)
				
			Humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, true)
			Humanoid:SetStateEnabled(Enum.HumanoidStateType.Running, true)
			warn("Jumping has been re-enabled")
		end
	end
		
	print("Setting debounce to false for "..LocalPlayer.Name)
	debounce = false
end

local function onTouch(other)
	local playerCheck = Players:GetPlayerFromCharacter(other.Parent)
	if playerCheck and playerCheck == LocalPlayer then
		sendPlayerFlying()
	end
end

parentPart.Touched:Connect(onTouch)

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