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)