How to stop player movement!

So im trying to add this thing to my tutorial where the game will walk you over to an area using path-finding but how can I stop the player from moving right/left etc?

31 Likes

You can use context action service to do this fairly cleanly.

The following works because ContextActionService works on a priority system. If a higher priority action is bound, it will sink input before filtering down to other actions. It also marks the input action as gameProcessed when checked against some UserInputService functions such as InputBegan.

At the current time, the default control scripts use UserInputService and check if the gameProcessed flag is false before moving your character.

local ContextActionService = game:GetService("ContextActionService")
local FROZEN_ACTION_KEY = "freezeMovement"

ContextActionService:BindActionAtPriority(
    FROZEN_ACTION_KEY,
    function() 
        return Enum.ContextActionResult.Sink
    end,
    false,
    Enum. ContextActionPriority.High.Value
    unpack(Enum.PlayerActions:GetEnumItems())
)

--to unfreeze

ContextActionService:UnbindAction(FROZEN_ACTION_KEY)
38 Likes

so that would “freeze” all the controls like space, right, left arrows and awsd? and how would i unfreeze it?

4 Likes

That would freeze all normal player actions yea. What its doing is replacing the player controls with an empty function. To get all the player actions, we call Enum.PlayerActions:GetEnumItems() which returns an array of all the player actions.

BindActionAtPriority is sorta weird in that it can take an unlimited amount of arguments. Anything at the end of the argument list is added as a new action to listen for.
Unfortunately we cannot pass an array as the final argument of BindActionAtPriority so we call unpack on the list which lists all the elements in the array in order as the final arguments.

You can unfreeze it by calling that last line of code.

6 Likes

OutlookG had a problem with this response as it does not seem to be working anymore,

Here is a different way of doing it

local Controller = require(game.Players.LocalPlayer:WaitForChild("PlayerScripts"):WaitForChild("PlayerModule")):GetControls()

Controller:Disable() --disables movement
Controller:Enable() --enables movement

I just wanted to update so if anyone stumbled upon this page they would have a working solution

:slight_smile:

59 Likes

I wouldnt recommend doing this because Control scripts are subject to change their function names at any time. Unless you are forking the ControlScripts while youre doing this, you are subject to code changing without your knowledge and is not future proof.

8 Likes

That is entirely true but I do not think it will be updated anytime soon as the methods are in the
“-- [ Public API ] --” part of the script ¯\_(ツ)_/¯

1 Like

I am sorry to have to ask but I believe ControlScript no longer appears under PlayerScripts so how is this done now?

OK found it
local ControlModule = require(game.Players.LocalPlayer:WaitForChild(“PlayerScripts”):WaitForChild(“PlayerModule”):WaitForChild(“ControlModule”))

ControlModule:Disable() --disables movement
ControlModule:Enable() --enables movement

:slight_smile:

11 Likes

My method above will work without having to touch or care about the control scripts. It will work in your own project code anywhere you call it.

I’ve already outline the reasons for avoiding using the control scripts in this same thread as well (since the very thing I warned about seemed to happen since this post)

4 Likes

So that I understand correctly if I am not using the ControlModule should I use the ContextActionService solution from the top of this chat?

1 Like

The ContextActionService one doesn’t even work when I tested it? @GollyGreg when was the last time you tested that one?

I have never tried it. I just tried the last one suggested from the topic and as it didn’t work changed to take into account the latest changes for PlayerScripts.
At the moment that is working so I am OK.
Was just wondering if there was a more favoured one that is not liable to change as was suggested earlier in this topic.

you have to return Enum.ContextActionResult.Sink (is a bug) will update.

3 Likes

I tried that as well and it didn’t seem to work, even though the function was being called :confused:

word for word code I have working on production rn:

ContextActionService:BindActionAtPriority(
	OVERWRITE_CONTROLS_TAG,
	function()
		return Enum.ContextActionResult.Sink
	end,
	false,
	Enum.ContextActionPriority.High.Value + 1,
	unpack(Enum.PlayerActions:GetEnumItems())
)
5 Likes

That’s strange, I have no idea then? The only difference is I used High.Value instead of High.Value + 1, and instead of it always sinking and being contextually added I had it always running like this:

ContextActionService:BindActionAtPriority(
	OVERWRITE_CONTROLS_TAG,
	function()
		return someBool and Enum.ContextActionResult.Sink or Enum.ContextActionResult.Pass
	end,
	false,
	Enum.ContextActionPriority.High.Value,
	unpack(Enum.PlayerActions:GetEnumItems())
)

I found an alternative solution, I’m just confused. Do you fork control scripts?

2 Likes

No, I can send you a studio file where this is working
stopMovement.rbxl (12.7 KB)

There is only a local script in StarterCharacterScripts

9 Likes

Extremely strange, I’ll look into seeing if I can reproduce my bug later.

2 Likes

I’m not sure why you necrobumped this post to make that comment and I’m not too sure you read the original post either before doing so. OP’s intention is to disable controls while still allowing movement. In your case, you’re only anchoring the root. Controls are still enabled and now the character can’t walk along the designated path.

7 Likes