Connecting user input to actions gives users much better and more intuitive control over your experience's features. In this tutorial, you will bind a reloading action to a specific key.
Getting Started
This tutorial uses the Blaster tool created in Creating Player Tools. You can follow those instructions to create the tool or you can download the Blaster model and insert it into StarterPack.
Models can be added into your Inventory to be used between any experience. To add a model to your experience:
- In a browser, open the model page, click the Get button. This adds the model into your inventory.
- In Studio, go to the View tab and click on the Toolbox.
- In the Toolbox window, click on the Inventory button. Then, make sure the dropdown is on My Models.
- Select the Blaster model to add it into the experience.
Creating an Action Handler
First, you'll need a function to handle when user input is detected.
Open the ToolController LocalScript inside of the Blaster.
Make a variable to store a name for the action.
local tool = script.Parentlocal RELOAD_ACTION = "reloadWeapon"local function toolEquipped()tool.Handle.Equip:Play()endlocal function toolActivated()tool.Handle.Activate:Play()endtool.Equipped:Connect(toolEquipped)tool.Activated:Connect(toolActivated)Create a function named onAction that receives three arguments: actionName, inputState, and inputObject. This will be the function that runs when user input is detected.
local tool = script.Parentlocal RELOAD_ACTION = "reloadWeapon"local function onAction(actionName, inputState, inputObject)endlocal function toolEquipped()tool.Handle.Equip:Play()endInside the function, check that the given actionName matches the reload action name and make sure inputState is UserInputState.Begin (the beginning state). This is important because the function will run every time the inputState changes, but the reload only needs to happen once.
local function onAction(actionName, inputState, inputObject)if actionName == RELOAD_ACTION and inputState == Enum.UserInputState.Begin thenendendTo make it obvious when the user reloads, change the TextureId of the tool to "rbxassetid://6593020923" for a moment, and then change it back to its original value of "rbxassetid://92628145".
local function onAction(actionName, inputState, inputObject)if actionName == RELOAD_ACTION and inputState == Enum.UserInputState.Begin thentool.TextureId = "rbxassetid://6593020923"task.wait(2)tool.TextureId = "rbxassetid://92628145"endend
Binding the Action
ContextActionService can be used to bind a function to a specific input by using the BindAction function, which accepts several arguments:
- The name of the action
- The function to handle the action (also called a "callback")
- Whether or not a touchscreen button should be displayed
- Any amount of Enum.KeyCodes to detect and associate with the action.
KeyCodes are values that represent different input buttons, such as keyboard keys or controller buttons. A full list of codes is available here.
Get ContextActionService at the top of the script.
local ContextActionService = game:GetService("ContextActionService")local tool = script.Parentlocal RELOAD_ACTION = "reloadWeapon"Inside of the toolEquipped function, call BindAction and pass through the following arguments:
- The name of the action (RELOAD_ACTION)
- The action handler (onAction)
- A value to create a touch button (true)
- A key press to detect (Enum.KeyCode.R)
local RELOAD_ACTION = "reloadWeapon"local function onAction(actionName, inputState, inputObject)if actionName == RELOAD_ACTION and inputState == Enum.UserInputState.Begin thentool.TextureId = "rbxassetid://6593020923"task.wait(2)tool.TextureId = "rbxassetid://92628145"endendlocal function toolEquipped()ContextActionService:BindAction(RELOAD_ACTION, onAction, true, Enum.KeyCode.R)tool.Handle.Equip:Play()endPlaytest by equipping the tool and pressing the R key on your keyboard. The backpack icon should momentarily change to a waiting symbol to signal that the weapon is reloading:
Unbinding the Action
When the user unequips the tool, the action needs to be unbound so they can't reload without the tool being equipped.
Create a new function called toolUnequipped and call UnbindAction, passing through the action name.
local function toolEquipped()ContextActionService:BindAction(RELOAD_ACTION, onAction, true, Enum.KeyCode.R)tool.Handle.Equip:Play()endlocal function toolUnequipped()ContextActionService:UnbindAction(RELOAD_ACTION)endlocal function toolActivated()tool.Handle.Activate:Play()endtool.Equipped:Connect(toolEquipped)tool.Activated:Connect(toolActivated)Connect the toolUnequipped function to the Unequipped event so the function will run when the event fires.
local ContextActionService = game:GetService("ContextActionService")local tool = script.Parentlocal RELOAD_ACTION = "reloadWeapon"local function onAction(actionName, inputState, inputObject)if actionName == RELOAD_ACTION and inputState == Enum.UserInputState.Begin thentool.TextureId = "rbxassetid://6593020923"task.wait(2)tool.TextureId = "rbxassetid://92628145"endendlocal function toolEquipped()ContextActionService:BindAction(RELOAD_ACTION, onAction, true, Enum.KeyCode.R)tool.Handle.Equip:Play()endlocal function toolUnequipped()ContextActionService:UnbindAction(RELOAD_ACTION)endlocal function toolActivated()tool.Handle.Activate:Play()endtool.Equipped:Connect(toolEquipped)tool.Unequipped:Connect(toolUnequipped)tool.Activated:Connect(toolActivated)Playtest to confirm that everything works correctly. You should be able to reload when the tool is equipped, but not when it is unequipped.
Your reloading animation is now complete - for an extra challenge, try counting down an ammo counter each time the blaster is fired. You can then deactivate the toolActivated function when the gun has no ammo, then reactivate it once the reload animation is finished.