Humanoid:SetStateEnabled not working

Reproduction Steps

  1. Run this on a LocalScript:
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:wait()
local Humanoid = Character:WaitForChild("Humanoid")

UserInputService.InputBegan:Connect(function(Input,GPE)
	print(Input.KeyCode)
	if Input.KeyCode == Enum.KeyCode.P then
		print("Humanoid:GetState(): ", Humanoid:GetState())
		Humanoid:SetStateEnabled(Enum.HumanoidStateType.RunningNoPhysics, false)
		Player.Character.PrimaryPart.Anchored = true
	end
end)
  1. Start running with the character (key W)
  2. While running, press P (will anchor the character)

88b459d57d40e496126ad9bdc0ea91b8bf15e0d2

Expected Behavior
When the character is anchored, it should stop running

Actual Behavior
Humanoid:SetStateEnabled(Enum.HumanoidStateType.RunningNoPhysics, false) is not producing any effect.

Issue Area: Engine
Issue Type: Other
Impact: High
Frequency: Constantly

Can you print the state after the call to disable the state? It could be that disabling the state is only preventing further state transitions to that state and doesn’t actually boot the humanoid out of that state if it’s the current one.

If you want the character to stop its walking animation immediately maybe you should just set the walkspeed to 0 temporarily instead or disable player controls. In my experience most Roblox developers don’t use SetStateEnabled on the running state…

1 Like
print("before: ", Humanoid:GetState())
Humanoid:SetStateEnabled(Enum.HumanoidStateType.RunningNoPhysics, false)
print("after: ", Humanoid:GetState())

before: Enum.HumanoidStateType.RunningNoPhysics
after: Enum.HumanoidStateType.RunningNoPhysics

Humanoid.WalkSpeed = 0
Player.Character.PrimaryPart.Anchored = true

… no effect…

Edit

I managed to create an weird workaround:

UserInputService.InputBegan:Connect(function(Input,GPE)
	print(Input.KeyCode)
	if Input.KeyCode == Enum.KeyCode.P then
		Player.Character.PrimaryPart.Anchored = true -- will not stop the running animation
		wait(0.5)
		Player.Character.PrimaryPart.Anchored = false -- will stop it
		wait(0.5)
		Player.Character.PrimaryPart.Anchored = true -- back to true after stopping the animation
		
	end
end)

PS: The workaround above does not exempt the current bug.

So it’s like I mentioned in previous post: disabling a state only prevents incoming transitions to that state. It doesn’t kick the humanoid out of the state by itself, this wouldn’t make sense anyway since there are multiple state transitions (would it pick one at random? swimming? climbing?)

The second confusion you have is that “standing still” is a different state than running, there is actually no humanoid state for that. When you are standing or running, it’s all RunningNoPhysics.

You’ll want to disable player controls and the corresponding action animations by disabling the controls at a high level, not by hacking it with the humanoid physics/animation state.

So try something like this:

local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local LocalPlayer = game.Players.LocalPlayer
local PlayerModule = require(LocalPlayer:WaitForChild("PlayerScripts"):WaitForChild("PlayerModule"))

UserInputService.InputBegan:Connect(function(Input)
	if Input.KeyCode == Enum.KeyCode.P then
		PlayerModule:GetControls():Disable()
		LocalPlayer.Character.PrimaryPart.Anchored = true
	end
end)

IMO the PrimaryPart anchoring is not great because it means the player could be stuck mid-air when you disable their controls, you might want to do something with physics movers to lock their character from moving in the XZ plane instead.

Actually, I anchor the player to avoid this:

The best solution for the question above was this:

… but it creates the sequel mentioned here.

It doesn’t work. Have you tested before?

I tested it without the anchored line (because this is how I usually do this, with some physics mover additions to lock player in XZ plane like I mentioned). Looks like anchoring the player on the same frame as the Disable call prevents animation state updates. Doing just the :Disable() will work and halt animations. (try it)

You can probably achieve your result by putting a frame wait between the Disable and anchor calls. However I’d still argue anchoring the player isn’t the best way to solve this problem. Collision groups and locking in XZ plane is more robust/versatile.

Yeah, I’ve tried Collision Groups as I mentioned below, but it didn’t work.

Idle standing still uses the Running and RunningNoPhysics states. Idle isn’t a different state.

When you anchor the character the Humanoid Running state is correctly exiting the internal state step function early, and not doing anything to move the character.

If you look at the Animate script in the character you can see that the speed of the animation and switching between the run, walk, and idle animations is determined by the current speed from the Humanoid.Running signal. After the humanoid is anchored it no longer fires the Running signal.

We probably should change the running states to fire Running(0) when anchored. That might take a while to get to.

As a better workaround you could temporarily copy and modify the Animate script to watch for the Anchored property on the root part changing and call onRunning(0) when it is anchored.

2 Likes

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