So it looks like you want to create an on screen button using ContextActionService, and more specifically, the BindAction function. This function can be used to process keyboard input, gamepad input, and to create an on screen mobile button.
I suggest you re-work your code to ensure you’ve written it all and understand it thoroughly; it will help you become a better programmer. I will be referencing some of the code code you’ve provided in my explanation, as well as the DevHub.
The following explanation will assume your knowledge of functions and parameters. If you don’t understand them, reference the DevHub for more information.
Firstly, you’ll want to define a specific function for attacking, so it can be referenced more easily.
Assuming the code inside of your UserInputService
InputBegan
function is what you want to happen when you attack, this is what it should look like. Again, this is assuming your code for attacking is already functional.
local function Attack()
if canattack == true then
canattack = false
event:FireServer()
script.RemoteEvent:FireServer(AttackArm)
human:LoadAnimation(AttachArm and script.R or script.L):Play()
wait(0.6)
AttackArm = not AttackArm
canattack = true
end
end
Now that we have the Attack
function defined, we’ll take a look at BindAction
.
There are 4 required parameters for the function BindAction
, which are the following:
The second parameter for BindAction
must be a Function, and this function will be automatically called when the specified inputTypes
are pressed. For instance, when you press the key F. This is not the Attack
function though; this is a function that will process the input, then call the Attack
function afterward.
functionToBind
, when called, will be passed 3 parameters, which are the following:
With this in mind, we can define another function to uniformly handle processing inputs, and from there, call the Attack
function. The function that will be responsible for all this will be called ProcessAction
, and it will receive the three aforementioned parameters.
local function ProcessAction(ActionName,InputState,InputObject)
-- This function ProcessAction will be called both when the key is pressed, and
-- when it is released.
-- We want to make sure this only proceeds if the key is pressed, and not released.
if InputState == Enum.UserInputState.Begin then
-- If the ActionName is correct, proceed and call the Attack function.
if ActionName == "Attack" then
Attack()
end
end
end
And all that is left to do now, is to call BindAction
.
However, make sure ContextActionService is defined somewhere in your code above this, as so:
local ContextActionService = game:GetService("ContextActionService")
-- The third parameter specifies whether there will be an on screen button for Mobile.
-- And all the parameters after that are the additional sources of input (gamepad, keyboard, etc.).
ContextActionService:BindAction("Attack", ProcessAction, true, Enum.KeyCode.F, Enum.KeyCode.ButtonY)
This will internally bind an action by the name of “Attack”, to a mobile button, the keyboard key F, and the gamepad button Y. When any of those inputs are triggered, the function ProcessAction
will be called to process the action.
Here’s what it’ll look like so far:
This is a default button though, with no text or image, and it isn’t in the best position. This can be corrected using the functions SetPosition and SetTitle.
ContextActionService:SetPosition("Attack",UDim2.new(0,0,0,0))
ContextActionService:SetTitle("Attack","Attack")
When these changes are made, the button looks more presentable, and even says “Attack” on it. This is not all though, as further customizations can be made (see SetDescription, SetImage, GetButton).
And all together your final code product may look something like this:
local ContextActionService = game:GetService("ContextActionService")
local function Attack()
-- Attack code
end
local function ProcessAction(ActionName,InputState,InputObject)
-- This function ProcessAction will be called both when the key is pressed, and
-- when it is released.
-- We want to make sure this only proceeds if the key is pressed, and not released.
if InputState == Enum.UserInputState.Begin then
-- If the ActionName is correct, proceed and call the Attack function.
if ActionName == "Attack" then
Attack()
end
end
end
-- The third parameter specifies whether there will be an on screen button for Mobile.
-- And all the parameters after that are the additional sources of input.
ContextActionService:BindAction("Attack", ProcessAction, true, Enum.KeyCode.F, Enum.KeyCode.ButtonY)
ContextActionService:SetPosition("Attack",UDim2.new(0,0,0,0))
ContextActionService:SetTitle("Attack","Attack")