Disabling player controls doesn't work

Hello!

I have a very simple local script in starterplayerscripts that disables and then enables the player’s controls. It seems that it doesn’t work anymore, as it throws an error directing to a completely different script. See below.

My code:

wait(2)
local LocalPlayer = game:GetService("Players").LocalPlayer
local Controls = require(LocalPlayer.PlayerScripts.PlayerModule):GetControls()

Controls:Disable()
wait(2)
Controls:Enable()

After it gets to Controls:Disable(), it throws this error:

Players.xasc.PlayerScripts.PlayerModule.ControlModule:274: attempt to index nil with 'Enable'

Stack begin
Script 'Players.xasc.PlayerScripts.PlayerModule.ControlModule', Line 274
Script 'Players.xasc.PlayerScripts.PlayerModule.ControlModule', Line 326 - function UpdateActiveControlModuleEnabled
Script 'Players.xasc.PlayerScripts.PlayerModule.ControlModule', Line 360 - function Disable
Script 'Players.xasc.PlayerScripts.LocalScript', Line 5
Stack end

I have never experienced this before. What should I do?

5 Likes

Roblox updated their player module code and broke it lol, we just have to wait for it to get fixed

1 Like

same thing happening with me. Roblox is working on something im seeing this strange property.

image

Ah, alright. It seemed kinda strange that it’d just stop working out of the blue.

Same issue, Critical Strike is broken right now.

This is the reason why I do not revolve my code around something that is subject to change at any moment. If you would like to use my private Controls module, feel free to grab it below.

It’s new so the API is pretty small, but I’ll expand on it later on.

API & Examples
-- Disables the controls by sinking the inputs via ContextActionService for Keyboard/Controller
-- and moves the TouchGui out of the screen to prevent touch inputs (simply changing the
-- Visible property wont work).
Controls:Disable()

-- Enables the controls.
Controls:Enable()

-- Checks if the controls are enabled.
local isEnabled: boolean = Controls:IsEnabled()

-- You can also grab the TouchGui if it exists.
local touchGui: ScreenGui? = Controls:GetTouchGui()

-- You can also listen for these events anytime
Controls.Toggled:Connect(function(enabled: boolean): ()
	-- code
end)

Controls.TouchGuiAdded:Connect(function(touchGui: ScreenGui): ()
	-- code
end)

Controls.TouchGuiRemoved:Connect(function(touchGui: ScreenGui): ()
	-- code
end)

-- You can also check if the input is a gamepad. It returns the connected gamepad # as well.
-- It will return false, 0 if it is not a gamepad.
local isGamepad: boolean, connectedGamepad: number = Controls:IsInputObjectGamepad(inputObject: InputObject)
local isGamepad: boolean, connectedGamepad: number = Controls:IsUserInputTypeGamepad(inputType: Enum.UserInputType)

-- This also fixes the multiple firing issue with UserInputService.JumpRequest.
-- It works for keyboard, gamepad, and touch screen.
Controls.JumpRequest:Connect(function(): ()
	-- code
end)
Controls.lua
--!strict

-- Controls.lua
-- UIScript
-- 21 April 2024

local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local ContextActionService = game:GetService("ContextActionService")
local GuiService = game:GetService("GuiService")

local LocalPlayer = Players.LocalPlayer
local PlayerGui = LocalPlayer.PlayerGui

local Signal = require(script.Parent.Signal)

local Toggled: Signal.Signal<boolean> = Signal.new()
local TouchGuiAdded: Signal.Signal<ScreenGui> = Signal.new()
local TouchGuiRemoved: Signal.Signal<ScreenGui> = Signal.new()
local JumpRequest: Signal.Signal<> = Signal.new()

local Controls = {
	Toggled = Toggled,
	TouchGuiAdded = TouchGuiAdded,
	TouchGuiRemoved = TouchGuiRemoved,
	JumpRequest = JumpRequest
}

local touchGuiConnections = {
	Toggled = nil :: Signal.Connection?,
}

function Controls:IsUserInputTypeGamepad(inputType: Enum.UserInputType): (boolean, number)
	for connectedGamepad: number = 1, 8 do
		if inputType == Enum.UserInputType[`Gamepad{connectedGamepad}`] then
			return true, connectedGamepad
		end
	end

	return false, 0
end

function Controls:IsInputObjectGamepad(inputObject: InputObject): (boolean, number)
	return Controls:IsUserInputTypeGamepad(inputObject.UserInputType)
end

function Controls:GetTouchGui(): ScreenGui?
	local touchGui: ScreenGui? = PlayerGui:FindFirstChild("TouchGui") :: ScreenGui
	local touchControlFrame: Frame? = if touchGui ~= nil then touchGui:FindFirstChild("TouchControlFrame") :: Frame else nil
	
	if touchControlFrame ~= nil and touchControlFrame.ClassName == "Frame" then
		return touchGui
	end
	
	return nil
end

function Controls:IsEnabled(): boolean
	return ContextActionService:GetAllBoundActionInfo()["Controls_Disable"] == nil
end

function Controls:Enable(): ()
	if Controls:IsEnabled() == false then
		ContextActionService:UnbindAction("Controls_Disable")
		Toggled:Fire(true)
	end
end

function Controls:Disable(): ()
	if Controls:IsEnabled() == true then
		local function handleControlsAction(_: string, inputState: Enum.UserInputState, inputObject: InputObject): Enum.ContextActionResult
			if inputObject.UserInputType == Enum.UserInputType.Keyboard then
				return Enum.ContextActionResult.Sink
			elseif Controls:IsInputObjectGamepad(inputObject) == true and ((inputObject.KeyCode == Enum.KeyCode.Thumbstick1 and inputState == Enum.UserInputState.Change) or inputObject.KeyCode == Enum.KeyCode.ButtonA) then
				return Enum.ContextActionResult.Sink
			end

			return Enum.ContextActionResult.Pass
		end

		ContextActionService:BindActionAtPriority(
			"Controls_Disable",
			handleControlsAction,
			false,
			Enum.ContextActionPriority.High.Value + 1,
			Enum.PlayerActions.CharacterForward,
			Enum.PlayerActions.CharacterBackward,
			Enum.PlayerActions.CharacterLeft,
			Enum.PlayerActions.CharacterRight,
			Enum.PlayerActions.CharacterJump,
			Enum.UserInputType.Gamepad1
			--Enum.UserInputType.Gamepad2,
			--Enum.UserInputType.Gamepad3,
			--Enum.UserInputType.Gamepad4,
			--Enum.UserInputType.Gamepad5,
			--Enum.UserInputType.Gamepad6,
			--Enum.UserInputType.Gamepad7,
			--Enum.UserInputType.Gamepad8
		)
		
		Toggled:Fire(false)
	end
end

do
	local function onControlsToggled(enabled: boolean): ()
		local touchGui: ScreenGui? = Controls:GetTouchGui()
		local touchControlFrame: Frame? = if touchGui ~= nil then touchGui:FindFirstChild("TouchControlFrame") :: Frame else nil
		
		if touchGui ~= nil and touchControlFrame ~= nil then
			touchControlFrame.Visible = enabled
			touchControlFrame.Position = UDim2.fromScale(0, if enabled == true then 0 else 1)
		end
	end
	
	onControlsToggled(Controls:IsEnabled())
	
	local function onPlayerGuiChildAdded(child: Instance): ()
		if child.ClassName == "ScreenGui" and child.Name == "TouchGui" then
			if touchGuiConnections.Toggled == nil then
				touchGuiConnections.Toggled = Toggled:Connect(onControlsToggled)
			end
			
			Controls.TouchGuiAdded:Fire(child :: ScreenGui)
			
			local touchControlFrame: Frame? = child:FindFirstChild("TouchControlFrame") :: Frame
			local jumpButton: GuiButton? = if touchControlFrame ~= nil then touchControlFrame:FindFirstChild("JumpButton") :: GuiButton else nil
			
			if jumpButton ~= nil and jumpButton:IsA("GuiButton") == true then
				local function onJumpButtonInputBegan(): ()
					JumpRequest:Fire()
				end
				
				jumpButton.InputBegan:Connect(onJumpButtonInputBegan)
			end
		end
	end
	
	local function onPlayerGuiChildRemoved(child: Instance): ()
		if child.ClassName == "ScreenGui" and child.Name == "TouchGui" then
			local touchControlFrame: Frame? = child:FindFirstChild("TouchControlFrame") :: Frame
			
			if touchControlFrame ~= nil and touchControlFrame.ClassName == "Frame" then
				if touchGuiConnections.Toggled ~= nil then
					touchGuiConnections.Toggled:Disconnect()
					touchGuiConnections.Toggled = nil
				end
				
				TouchGuiRemoved:Fire(child :: ScreenGui)
			end
		end
	end
	
	PlayerGui.ChildAdded:Connect(onPlayerGuiChildAdded)
	PlayerGui.ChildRemoved:Connect(onPlayerGuiChildRemoved)
	
	for _: number, child: Instance in PlayerGui:GetChildren() do
		task.spawn(onPlayerGuiChildAdded, child)
	end
	
	local function handleJumpAction(_: string, inputState: Enum.UserInputState): Enum.ContextActionResult
		if inputState == Enum.UserInputState.Begin then
			JumpRequest:Fire()
		end

		return Enum.ContextActionResult.Pass
	end

	ContextActionService:BindActionAtPriority(
		"Controls_JumpAction",
		handleJumpAction,
		false,
		Enum.ContextActionPriority.Medium.Value + 1,
		Enum.PlayerActions.CharacterJump,
		Enum.KeyCode.ButtonA
	)
end

return Controls

You will also need @sleitnick’s Signal you can grab here:

1 Like

Yeah i noticed the same thing, my game is totally broken now.
I belive all we can do is wait for roblox to fix it

I was wondering why this was as well, but yeah all makes sense now

Issue was solved here