mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 14:01:37 +00:00
update rules
This commit is contained in:
parent
4c390fdd37
commit
d5522b2fef
8549 changed files with 11783 additions and 1888 deletions
95
.cursor/rules/roblox/en-us/input/gamepad.md
Normal file
95
.cursor/rules/roblox/en-us/input/gamepad.md
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
---
|
||||
title: Gamepad input
|
||||
description: Explains how to accept input from USB gamepads, such as Xbox and PlayStation controllers.
|
||||
---
|
||||
|
||||
import ControllerEmulator from '../includes/studio/controller-emulator.md'
|
||||
|
||||
Roblox accepts input from gamepads such as Xbox and PlayStation controllers. To simplify [cross‑platform](../projects/cross-platform.md) inputs, including gamepads, Roblox provides the [Input Action System](../input/input-action-system.md) to define **actions** such as "jump," "sprint," or "shoot" and set up **bindings** for multiple hardware inputs to drive those actions.
|
||||
|
||||
When binding gamepad inputs, see [common control schemas](#common-control-schemas) to create a consistent gamepad experience for players. After inputs are set, you can enhance the player's experience by including [haptic feedback](#haptic-feedback) on supported controllers.
|
||||
|
||||
As you build out support for gamepads, remember to test frequently using a connected gamepad or the [Controller Emulator](#controller-emulation) in Studio.
|
||||
|
||||
## Input type detection
|
||||
|
||||
In cross‑platform development, it's important that you determine and respond to the `Class.UserInputService.PreferredInput|PreferredInput` type a player is using, normally to ensure that [UI elements](../ui/index.md#ui-objects) like on-screen buttons and menus work elegantly and support interaction across devices.
|
||||
|
||||
For example, a console assumes that gamepads are the default input, but a player on PC or laptop may also choose to connect a bluetooth gamepad. In this case, mouse/keyboard remains a valid input for that player, but you can assume they want to switch to the connected gamepad as the **primary** input type.
|
||||
|
||||
See [input type detection](./index.md#input-type-detection) for more information.
|
||||
|
||||
<Alert severity="info">
|
||||
For alternative gamepad detection methods, see the `Class.UserInputService.GamepadEnabled` property and the `Class.UserInputService.GamepadConnected|GamepadConnected`/`Class.UserInputService.GamepadDisconnected|GamepadDisconnected` events.
|
||||
</Alert>
|
||||
|
||||
## Common control schemas
|
||||
|
||||
When considering specific control bindings for the [Input Action System](../input/input-action-system.md), it's best to establish consistency across different experiences. The following input bindings will help players immediately feel familiar and comfortable with gamepad controls.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Input</th>
|
||||
<th>Common use cases</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>`Enum.KeyCode|ButtonA`</td>
|
||||
<td>Accepts player prompts or GUI selections. Alternatively used for primary actions such as jumping.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`Enum.KeyCode|ButtonB`</td>
|
||||
<td>Cancels player prompts or GUI selections. Alternatively used for secondary actions such as a dodge, roll, or sprint.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`Enum.KeyCode|Thumbstick1`</td>
|
||||
<td>Generally associated with character movement.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`Enum.KeyCode|Thumbstick2`</td>
|
||||
<td>Generally associated with camera movement.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`Enum.KeyCode|ButtonL2`, `Enum.KeyCode|ButtonR2`</td>
|
||||
<td>Generally used for primary actions, such as shooting. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`Enum.KeyCode|ButtonL1`, `Enum.KeyCode|ButtonR1`, `Enum.KeyCode|ButtonX`, `Enum.KeyCode|ButtonY`</td>
|
||||
<td>Secondary actions such as reloading, targeting, or accessing an inventory or minimap.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="Xbox">
|
||||
<img src="../assets/scripting/input/Gamepad-Inputs-Xbox.png" width="860" height="510" />
|
||||
</TabItem>
|
||||
<TabItem label="PlayStation">
|
||||
<img src="../assets/scripting/input/Gamepad-Inputs-PS.png" width="860" height="510" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Haptic feedback
|
||||
|
||||
Many gamepad controllers have motors built in to provide haptic feedback. Adding rumbles and vibrations can greatly enhance a player's experience and provide subtle feedback beyond visuals or audio.
|
||||
|
||||
Roblox supports haptics for PlayStation gamepads, Xbox gamepads, and the Quest Touch controller. Haptic feedback is managed through `Class.HapticEffect` instances which can be set to a specific `Class.HapticEffect.Type|Type` such as `Enum.HapticEffectType|GameplayCollision` or `Enum.HapticEffectType|UIClick`.
|
||||
|
||||
Once a `Class.HapticEffect` is in place, you can initiate it through the `Class.HapticEffect:Play()|Play()` method, for instance:
|
||||
|
||||
```lua
|
||||
local Workspace = game:GetService("Workspace")
|
||||
|
||||
local effect = Instance.new("HapticEffect")
|
||||
effect.Type = Enum.HapticEffectType.GameplayExplosion
|
||||
effect.Parent = Workspace
|
||||
|
||||
-- Play the haptic effect
|
||||
effect:Play()
|
||||
```
|
||||
|
||||
## Controller emulation
|
||||
|
||||
<ControllerEmulator components={props.components} />
|
||||
103
.cursor/rules/roblox/en-us/input/index.md
Normal file
103
.cursor/rules/roblox/en-us/input/index.md
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
---
|
||||
title: Input
|
||||
description: Summary of cross-platform input on Roblox and implementation guidelines.
|
||||
---
|
||||
|
||||
import DefaultBindings from '../includes/default-bindings.md'
|
||||
|
||||
Every experience needs to receive user input for players to interact and view their environment. Roblox supports nearly all forms of input, including [mouse/keyboard](../input/mouse-and-keyboard.md), [touch](../input/mobile.md), [gamepads](../input/gamepad.md), and VR.
|
||||
|
||||
## Cross-platform input
|
||||
|
||||
Roblox is inherently [cross‑platform](../projects/cross-platform.md), as players can discover and join experiences on their phone or tablet, then later continue where they left off on their PC or console. Input is especially important as part of your cross‑platform development plan.
|
||||
|
||||
To simplify this process, Roblox provides the [Input Action System](../input/input-action-system.md) to define **actions** such as "jump," "sprint," or "shoot" and set up **bindings** for multiple hardware inputs to drive those actions. This frees you from thinking of all the technical aspects of hardware inputs and allows you to simply define which inputs perform which actions.
|
||||
|
||||
<img src="../assets/publishing/cross-platform/Input-Actions-Jump.png" />
|
||||
|
||||
## Input type detection
|
||||
|
||||
In cross‑platform development, it's important that you determine and respond to the **primary** input type a player is using, normally to ensure that [UI elements](../ui/index.md#ui-objects) like on‑screen buttons and menus work elegantly across devices.
|
||||
|
||||
For example, a touch‑enabled device assumes touch is the default input and that touch buttons may appear for actions, but if a player connects an additional bluetooth keyboard/mouse or gamepad, you can assume they want to switch to that as the **primary** input type and possibly use touch as a backup input for on‑screen UI. The read‑only `Class.UserInputService.PreferredInput` property is a convenient way to test for and adapt to multiple input types across multiple device types, based on anticipated player behavior.
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="Behavior">
|
||||
The value of `Class.UserInputService.PreferredInput|PreferredInput` changes based on built‑in device inputs and the player's most recent interaction with a connected gamepad or keyboard/mouse. Examples include:
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Real-World Scenario</th>
|
||||
<th>`PreferredInput`</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Player is using a phone with no other connected input devices; no possibility of an input type change.</td>
|
||||
<td>`Enum.PreferredInput|Touch`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Player is using a mobile device with a bluetooth keyboard & mouse connected, but no gamepad is connected.</td>
|
||||
<td>`Enum.PreferredInput|KeyboardAndMouse`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Player is using a tablet with a bluetooth gamepad connected, but no keyboard or mouse is connected.</td>
|
||||
<td>`Enum.PreferredInput|Gamepad`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Player is using an Xbox or PlayStation with a bluetooth keyboard & mouse connected and has most recently interacted with the keyboard or mouse.</td>
|
||||
<td>`Enum.PreferredInput|KeyboardAndMouse`</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Player is on a Windows or Mac PC with a gamepad connected and has most recently interacted with the gamepad.</td>
|
||||
<td>`Enum.PreferredInput|Gamepad`</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</TabItem>
|
||||
<TabItem label="Benefits">
|
||||
Importantly, the `Class.UserInputService.PreferredInput|PreferredInput` property overcomes the following issues related to `Class.UserInputService.TouchEnabled` and `Class.UserInputService:GetLastInputType()`, both traditionally used to detect input types.
|
||||
|
||||
- `Class.UserInputService.TouchEnabled|TouchEnabled` is `true` on laptops with touch screens, so it is **not** a proper "is mobile" check.
|
||||
- UI layouts for gamepad or keyboard/mouse may be more appropriate even if a device has touch capability, for example a mobile device with a bluetooth gamepad connected.
|
||||
- Multiple `Class.UserInputService:GetLastInputType()|GetLastInputType()` values may represent the same input device, requiring compound `or` logic in scripts. For example, `Enum.UserInputType|MouseWheel`, `Enum.UserInputType|MouseMovement`, and `Enum.UserInputType|MouseButton1` all represent a mouse.
|
||||
- `Class.UserInputService:GetLastInputType()|GetLastInputType()` frequently thrashes between `Enum.UserInputType|MouseMovement` and `Enum.UserInputType|Keyboard` which may cause code to run more often than expected. Similarly, thrashes between `Enum.UserInputType|Touch` and `Enum.UserInputType|Gamepad[]` may cause on‑screen UI to flicker between layouts.
|
||||
- `Class.UserInputService:GetLastInputType()|GetLastInputType()` may return confusing values such as `Enum.UserInputType|TextInput`, `Enum.UserInputType|Focus`, and `Enum.UserInputType|InputMethod`.
|
||||
|
||||
<Alert severity="info">
|
||||
For advanced workflows or control schemes that rely on detecting and responding to the player's **specific** most recent UserInputType, you can continue using UserInputService:GetLastInputType() and UserInputService.LastInputTypeChanged.
|
||||
</Alert>
|
||||
</TabItem>
|
||||
</Tabs><br />
|
||||
|
||||
The following `Class.LocalScript` is a template for initially detecting the preferred input and responding to changes during gameplay.
|
||||
|
||||
```lua title="PreferredInput detection"
|
||||
local UserInputService = game:GetService("UserInputService")
|
||||
|
||||
local function preferredInputChanged()
|
||||
local preferredInput = UserInputService.PreferredInput
|
||||
|
||||
if preferredInput == Enum.PreferredInput.Touch then
|
||||
-- Player is on touch-enabled device with no other input types available/connected
|
||||
print("Touch")
|
||||
elseif preferredInput == Enum.PreferredInput.Gamepad then
|
||||
-- Player has connected or most recently interacted with a gamepad
|
||||
print("Gamepad")
|
||||
elseif preferredInput == Enum.PreferredInput.KeyboardAndMouse then
|
||||
-- Player has connected or most recently interacted with a keyboard or mouse
|
||||
print("KeyboardAndMouse")
|
||||
end
|
||||
end
|
||||
|
||||
preferredInputChanged()
|
||||
|
||||
UserInputService:GetPropertyChangedSignal("PreferredInput"):Connect(function()
|
||||
preferredInputChanged()
|
||||
end)
|
||||
```
|
||||
|
||||
## Default bindings
|
||||
|
||||
<DefaultBindings components={props.components} />
|
||||
356
.cursor/rules/roblox/en-us/input/input-action-system.md
Normal file
356
.cursor/rules/roblox/en-us/input/input-action-system.md
Normal file
|
|
@ -0,0 +1,356 @@
|
|||
---
|
||||
title: Input Action System
|
||||
description: The cross-platform Input Action System lets you connect actions and arrange bindings across various hardware inputs at edit time.
|
||||
---
|
||||
|
||||
import DefaultBindings from '../includes/default-bindings.md'
|
||||
|
||||
The cross-platform **Input Action System** lets you connect [actions](#input-actions) and arrange [bindings](#input-bindings) across various hardware inputs at edit time. Combined with [contexts](#input-contexts), you can easily configure and edit a modular input system that works on any device in any phase of play. Use cases include:
|
||||
|
||||
- A first-person shooter system with actions dynamically swapping in and out depending on if the player is in battle mode or spectator mode.
|
||||
- A comprehensive driving system equipped with acceleration/deceleration, car boosters, and refuel stations.
|
||||
- Hotkeys for an abilities system in a fighting game to swap out moves seamlessly without players missing a punch.
|
||||
|
||||
## Input contexts
|
||||
|
||||
An `Class.InputContext` is a collection of actions which holds related [input actions](#input-actions), for example `PlayContext` for in‑experience character controls and `NavContext` for controls to navigate around UI menus. You can enable or disable contexts (and their corresponding actions) through their `Class.InputContext.Enabled|Enabled` property, such as to enable the `NavContext` when an inventory menu is open and then change to the `PlayContext` when the player closes the menu and returns to primary gameplay.
|
||||
|
||||
Even if an experience may not use multiple input contexts initially, best practice is to create a primary context at the top level of any input system, for example the `PlayContext` instance for input that occurs during gameplay.
|
||||
|
||||
1. Insert a new `Class.InputContext` into `Class.StarterGui`.
|
||||
2. Rename it to `PlayContext`.
|
||||
|
||||
<img src="../assets/studio/explorer/StarterGui-InputContext.png" width="320" alt="New InputContext instance inside StarterGui, renamed to PlayContext" />
|
||||
|
||||
## Input actions
|
||||
|
||||
An `Class.InputAction` defines a gameplay action mechanic such as "Jump," "Sprint," or "Shoot." These actions are then mapped to hardware inputs using [input bindings](#input-bindings).
|
||||
|
||||
An `Class.InputAction` can be of several variations depending on its `Class.InputAction.Type|Type` property (`Enum.InputActionType`). The default is `Enum.InputActionType|Bool`, designed to receive `true`/`false` values from press/release of inputs such as `Enum.KeyCode.ButtonA|ButtonA`, `Enum.KeyCode.E|E`, or `Enum.KeyCode.MouseLeftButton|MouseLeftButton`. The `Enum.InputActionType|Bool` type also exposes the `Class.InputBinding.UIButton|UIButton` property on child bindings, allowing you to easily hook up press/release of a specific `Class.GuiButton` for the action.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Input Action Type</th>
|
||||
<th>Example Usage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>`Enum.InputActionType|Bool`</td>
|
||||
<td>Triggered actions such as jump, shoot, sprint, etc. with support for pressed/released thresholds on analog inputs.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`Enum.InputActionType|Direction1D`</td>
|
||||
<td>Variable zero-to-full actions such as a car's accelerator pedal or a view scope's zoom level.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`Enum.InputActionType|Direction2D`</td>
|
||||
<td>2D directional movement such as camera rotation, or the standard Roblox character movement.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`Enum.InputActionType|Direction3D`</td>
|
||||
<td>3D directional movement like an airborne vehicle that can levitate up/down, accelerate/decelerate, and drift left/right.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`Enum.InputActionType|ViewportPosition`</td>
|
||||
<td>2D viewport coordinates like mouse input, such as for custom cursors or raycasting to select world objects.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
To test an `Class.InputAction` for simple character sprinting:
|
||||
|
||||
1. Create a new `Class.InputAction` inside the `PlayContext` context within `Class.StarterGui`. Rename it to `CharacterSprint` to indicate its dedicated action.
|
||||
|
||||
<img src="../assets/studio/explorer/StarterGui-InputContext-InputAction.png" width="320" alt="New InputAction instance inside an InputContext, renamed to CharacterSprint" />
|
||||
|
||||
2. In the [Properties](../studio/properties.md) window, notice that the action's `Class.InputAction.Type|Type` is `Enum.InputActionType|Bool` (default). This is a logical type for simple character sprinting as a boolean `true`/`false` action (character is either sprinting or not sprinting).
|
||||
|
||||
<img src="../assets/studio/properties/InputAction-Type-Bool.png" width="320" alt="Type property of an InputAction set to Bool" />
|
||||
|
||||
## Input bindings
|
||||
|
||||
An `Class.InputBinding` defines which hardware binding should trigger the parent `Class.InputAction`, for example a key press, gamepad button, or tap on a touch‑enabled device. For [cross‑platform](../projects/cross-platform.md) compatibility, each `Class.InputAction` should have an `Class.InputBinding` for **gamepad**, **keyboard/mouse**, and **touch** as illustrated here.
|
||||
|
||||
<img src="../assets/studio/explorer/StarterGui-InputContext-InputAction-InputBinding-All.png" width="320" />
|
||||
|
||||
The `Class.InputAction.Type|Type` assigned to the parent `Class.InputAction` directly affects which general input types (key/button/tap, analog trigger, thumbstick, etc.) are valid for child `Class.InputBinding` instances. In turn, values sent to the parent action's connected events depend on a binding's chosen input type. See [input events](#input-events) for details on the correlation between action types, bindings, and return values.
|
||||
|
||||
To hook up bindings for simple character sprinting:
|
||||
|
||||
1. Insert a new `Class.InputBinding` into the `CharacterSprint` action and rename it to `KeyboardBinding`. Then set the binding's `Class.InputBinding.KeyCode|KeyCode` property to `Enum.KeyCode.LeftShift|LeftShift`.
|
||||
|
||||
<Grid container spacing={2} alignItems="top">
|
||||
<Grid item>
|
||||
<img src="../assets/studio/explorer/StarterGui-InputContext-InputAction-InputBinding-KeyboardBinding.png" width="320" />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<img src="../assets/studio/properties/InputBinding-KeyCode-LeftShift.png" width="320" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
2. To ensure mouse <kbd>Shift</kbd>-lock does not interfere with the key binding, select `Class.StarterPlayer` in the [Explorer](../studio/explorer.md) and disable its `Class.StarterPlayer.EnableMouseLockOption|EnableMouseLockOption` in the [Properties](../studio/properties.md) window.
|
||||
|
||||
<Grid container spacing={2} alignItems="top">
|
||||
<Grid item>
|
||||
<img src="../assets/studio/explorer/StarterPlayer.png" width="320" />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<img src="../assets/studio/properties/StarterPlayer-EnableMouseLockOption-Off.png" width="320" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
3. Insert another `Class.InputBinding` into the `CharacterSprint` action and rename it to `GamepadBinding`. Then set the binding's `Class.InputBinding.KeyCode|KeyCode` property to `Enum.KeyCode.ButtonY|ButtonY`.
|
||||
|
||||
<Grid container spacing={2} alignItems="top">
|
||||
<Grid item>
|
||||
<img src="../assets/studio/explorer/StarterGui-InputContext-InputAction-InputBinding-GamepadBinding.png" width="320" />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<img src="../assets/studio/properties/InputBinding-KeyCode-ButtonY.png" width="320" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
4. Inside a `Class.ScreenGui` container inside `Class.StarterGui`, create an [on-screen button](../ui/buttons.md), rename it to `SprintButton`, and [position/resize](../ui/position-and-size.md) it as desired.
|
||||
|
||||
<img src="../assets/studio/explorer/StarterGui-ScreenGui-SprintButton.png" width="320" />
|
||||
|
||||
<img src="../assets/ui/button-text-input/Sprint-Button.png" width="840" />
|
||||
|
||||
5. Insert another `Class.InputBinding` into the `CharacterSprint` action and rename it to `TouchBinding`. Then, in the [Properties](../studio/properties.md) window, link the binding's `Class.InputBinding.UIButton|UIButton` property to the `SprintButton` button you created previously inside `Class.StarterGui`.
|
||||
|
||||
<Grid container spacing={2} alignItems="top">
|
||||
<Grid item>
|
||||
<img src="../assets/studio/explorer/StarterGui-InputContext-InputAction-InputBinding-TouchBinding.png" width="320" />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<img src="../assets/studio/properties/InputBinding-UIButton-SprintButton.png" width="320" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
## Input events
|
||||
|
||||
The `Class.InputAction` instance has three built-in **events** to handle player input coming from `Class.InputBinding|InputBindings`.
|
||||
|
||||
- `Class.InputAction.Pressed|Pressed` — This event fires only when the input action's `Class.InputAction.Type|Type` is set to `Enum.InputActionType|Bool`, and only when the state transitions from `false` to `true`.
|
||||
- `Class.InputAction.Released|Released` — This event fires only when the input action's `Class.InputAction.Type|Type` is set to `Enum.InputActionType|Bool`, and only when the state transitions from `true` to `false`.
|
||||
- `Class.InputAction.StateChanged|StateChanged` — This event fires for all input action types whenever the state changes, except if the state attempts to transition to the same state.
|
||||
|
||||
Depending on the input action's `Class.InputAction.Type|Type` (`Enum.InputActionType|Bool`, `Enum.InputActionType|Direction1D`, `Enum.InputActionType|Direction2D`, `Enum.InputActionType|Direction3D`, or `Enum.InputActionType|ViewportPosition`) and the general input type coming from a child `Class.InputBinding` (key/button/tap, analog trigger, thumbstick, etc.), different values are returned to the `Class.InputAction.Pressed|Pressed`, `Class.InputAction.Released|Released`, and `Class.InputAction.StateChanged|StateChanged` event handlers. Examine the following tables to better understand the correlation.
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="Bool">
|
||||
The `Enum.InputActionType|Bool` type is best for triggered actions such as jump, shoot, sprint, etc. with support for pressed/released thresholds on analog inputs.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Valid Input Types on `Class.InputBinding|InputBindings`</th>
|
||||
<th>Returned to the `Class.InputAction` Event(s)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="40%">Boolean inputs from keyboard keys or basic mouse/gamepad buttons through the binding's `Class.InputBinding.KeyCode|KeyCode` property, or a `Class.GuiButton` press/release through the binding's `Class.InputBinding.UIButton|UIButton` property.</td>
|
||||
<td><ul style={{marginBottom: -16}}><li>`Class.InputAction.Pressed|Pressed` event:<ul><li>`true` when pressed</li></ul></li><li>`Class.InputAction.Released|Released` event:<ul><li>`true` when released</li></ul></li><li>`Class.InputAction.StateChanged|StateChanged` event:<ul><li>`true` (pressed) or `false` (released)</li></ul></li></ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Variable input amounts from analog inputs like gamepad triggers (`Enum.KeyCode.ButtonL2|ButtonL2`/`Enum.KeyCode.ButtonR2|ButtonR2`) through the binding's `Class.InputBinding.KeyCode|KeyCode` property.</td>
|
||||
<td><ul style={{marginBottom: -16}}><li>`Class.InputAction.Pressed|Pressed` event:<ul><li>`true` when trigger press is `>=` `Class.InputBinding.PressedThreshold|PressedThreshold`</li></ul></li><li>`Class.InputAction.Released|Released` event:<ul><li>`true` when trigger press is `<=` `Class.InputBinding.ReleasedThreshold|ReleasedThreshold`</li></ul></li><li>`Class.InputAction.StateChanged|StateChanged` event:<ul><li style={{marginBottom: -16}}>`true` when trigger press is `>=` `Class.InputBinding.PressedThreshold|PressedThreshold`</li><li>`false` when trigger press is `<=` `Class.InputBinding.ReleasedThreshold|ReleasedThreshold`</li></ul></li></ul></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="Direction1D">
|
||||
The `Enum.InputActionType|Direction1D` type is best for variable zero‑to‑full actions such as a car's accelerator pedal or a view scope's zoom level.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Valid Input Types on `Class.InputBinding|InputBindings`</th>
|
||||
<th>Returned to the `Class.InputAction` Event(s)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="40%">Variable input amounts from analog inputs like gamepad triggers (`Enum.KeyCode.ButtonL2|ButtonL2`/`Enum.KeyCode.ButtonR2|ButtonR2`) through the binding's `Class.InputBinding.KeyCode|KeyCode`, `Class.InputBinding.Up|Up`, and `Class.InputBinding.Down|Down` properties.</td>
|
||||
<td><ul style={{marginBottom: -16}}><li>`Class.InputAction.StateChanged|StateChanged` event:<ul><li style={{marginBottom: -16}}>`0` to `1` (fully released to fully pressed) through the `Class.InputBinding.KeyCode|KeyCode` or `Class.InputBinding.Up|Up` properties</li><li>`0` to `-1` (fully released to fully pressed) through the `Class.InputBinding.Down|Down` property</li></ul></li></ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Boolean inputs from keyboard keys or basic mouse/gamepad buttons through the binding's `Class.InputBinding.KeyCode|KeyCode`, `Class.InputBinding.Up|Up`, and `Class.InputBinding.Down|Down` properties.</td>
|
||||
<td><ul style={{marginBottom: -16}}><li>`Class.InputAction.StateChanged|StateChanged` event:<ul><li style={{marginBottom: -16}}>`1` (pressed) or `0` (released) through the `Class.InputBinding.KeyCode|KeyCode` or `Class.InputBinding.Up|Up` properties</li><li>`-1` (pressed) or `0` (released) through the `Class.InputBinding.Down|Down` property</li></ul></li></ul></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="Direction2D">
|
||||
The `Enum.InputActionType|Direction2D` type is best for 2D directional movement such as camera rotation, or the standard Roblox character movement.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Valid Input Types on `Class.InputBinding|InputBindings`</th>
|
||||
<th>Returned to the `Class.InputAction` Event(s)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="40%">Variable input amounts from 2D analog inputs like gamepad thumbsticks (`Enum.KeyCode.Thumbstick1|Thumbstick1`/`Enum.KeyCode.Thumbstick2|Thumbstick2`) through the binding's `Class.InputBinding.KeyCode|KeyCode` property.</td>
|
||||
<td><ul style={{marginBottom: -16}}><li>`Class.InputAction.StateChanged|StateChanged` event:<ul><li>`Datatype.Vector2` between <Typography noWrap>`(-1, -1)`</Typography> and <Typography noWrap>`(1, 1)`</Typography></li></ul></li></ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Variable input amounts from analog inputs like gamepad triggers (`Enum.KeyCode.ButtonL2|ButtonL2`/`Enum.KeyCode.ButtonR2|ButtonR2`) through the binding's `Class.InputBinding.Up|Up`, `Class.InputBinding.Down|Down`, `Class.InputBinding.Left|Left`, and `Class.InputBinding.Right|Right` properties.</td>
|
||||
<td><ul style={{marginBottom: -16}}><li>`Class.InputAction.StateChanged|StateChanged` event:<ul><li style={{marginBottom: -16}}>`Datatype.Vector2` with `Datatype.Vector2.Y|Y` component between `0` and `1` (fully released to fully pressed) through the `Class.InputBinding.Up|Up` property</li><li style={{marginBottom: -16}}>`Datatype.Vector2` with `Datatype.Vector2.Y|Y` component between `0` and `-1` (fully released to fully pressed) through the `Class.InputBinding.Down|Down` property</li><li style={{marginBottom: -16}}>`Datatype.Vector2` with `Datatype.Vector2.X|X` component between `0` and `-1` (fully released to fully pressed) through the `Class.InputBinding.Left|Left` property</li><li>`Datatype.Vector2` with `Datatype.Vector2.X|X` component between `0` and `1` (fully released to fully pressed) through the `Class.InputBinding.Right|Right` property</li></ul></li></ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Boolean inputs from keyboard keys or basic mouse/gamepad buttons through the binding's `Class.InputBinding.Up|Up`, `Class.InputBinding.Down|Down`, `Class.InputBinding.Left|Left`, and `Class.InputBinding.Right|Right` properties.</td>
|
||||
<td><ul style={{marginBottom: -16}}><li>`Class.InputAction.StateChanged|StateChanged` event:<ul><li style={{marginBottom: -16}}>`Datatype.Vector2` of <Typography noWrap>`(0, 1)`</Typography> (pressed) or
|
||||
<Typography noWrap>`(0, 0)`</Typography> (released) through the `Class.InputBinding.Up|Up` property</li><li style={{marginBottom: -16}}>`Datatype.Vector2` of <Typography noWrap>`(0, -1)`</Typography> (pressed) or
|
||||
<Typography noWrap>`(0, 0)`</Typography> (released) through the `Class.InputBinding.Down|Down` property</li><li style={{marginBottom: -16}}>`Datatype.Vector2` of <Typography noWrap>`(-1, 0)`</Typography> (pressed) or
|
||||
<Typography noWrap>`(0, 0)`</Typography> (released) through the `Class.InputBinding.Left|Left` property</li><li>`Datatype.Vector2` of <Typography noWrap>`(1, 0)`</Typography> (pressed) or
|
||||
<Typography noWrap>`(0, 0)`</Typography> (released) through the `Class.InputBinding.Right|Right` property</li></ul></li></ul></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="Direction3D">
|
||||
The `Enum.InputActionType|Direction3D` type is best for 3D directional movement like an airborne vehicle that can levitate up/down, accelerate/decelerate, and drift left/right.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Valid Input Types on `Class.InputBinding|InputBindings`</th>
|
||||
<th>Returned to the `Class.InputAction` Event(s)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="40%">Variable input amounts from analog inputs like gamepad triggers (`Enum.KeyCode.ButtonL2|ButtonL2`/`Enum.KeyCode.ButtonR2|ButtonR2`) through the binding's `Class.InputBinding.Up|Up`, `Class.InputBinding.Down|Down`, `Class.InputBinding.Left|Left`, `Class.InputBinding.Right|Right`, `Class.InputBinding.Forward|Forward`, and `Class.InputBinding.Backward|Backward` properties.</td>
|
||||
<td><ul style={{marginBottom: -16}}><li>`Class.InputAction.StateChanged|StateChanged` event:<ul><li style={{marginBottom: -16}}>`Datatype.Vector3` with `Datatype.Vector3.Y|Y` component between `0` and `1` (fully released to fully pressed) through the `Class.InputBinding.Up|Up` property</li><li style={{marginBottom: -16}}>`Datatype.Vector3` with `Datatype.Vector3.Y|Y` component between `0` and `-1` (fully released to fully pressed) through the `Class.InputBinding.Down|Down` property</li><li style={{marginBottom: -16}}>`Datatype.Vector3` with `Datatype.Vector3.X|X` component between `0` and `-1` (fully released to fully pressed) through the `Class.InputBinding.Left|Left` property</li><li style={{marginBottom: -16}}>`Datatype.Vector3` with `Datatype.Vector3.X|X` component between `0` and `1` (fully released to fully pressed) through the `Class.InputBinding.Right|Right` property</li><li style={{marginBottom: -16}}>`Datatype.Vector3` with `Datatype.Vector3.Z|Z` component between `0` and `-1` (fully released to fully pressed) through the `Class.InputBinding.Forward|Forward` property</li><li>`Datatype.Vector3` with `Datatype.Vector3.Z|Z` component between `0` and `1` (fully released to fully pressed) through the `Class.InputBinding.Backward|Backward` property</li></ul></li></ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Boolean inputs from keyboard keys or basic mouse/gamepad buttons through the binding's `Class.InputBinding.Up|Up`, `Class.InputBinding.Down|Down`, `Class.InputBinding.Left|Left`, `Class.InputBinding.Right|Right`, `Class.InputBinding.Forward|Forward`, and `Class.InputBinding.Backward|Backward` properties.</td>
|
||||
<td><ul style={{marginBottom: -16}}><li>`Class.InputAction.StateChanged|StateChanged` event:<ul><li style={{marginBottom: -16}}>`Datatype.Vector3` of <Typography noWrap>`(0, 1, 0)`</Typography> (pressed) or <Typography noWrap>`(0, 0, 0)`</Typography> (released) through the `Class.InputBinding.Up|Up` property</li><li style={{marginBottom: -16}}>`Datatype.Vector3` of <Typography noWrap>`(0, -1, 0)`</Typography> (pressed) or <Typography noWrap>`(0, 0, 0)`</Typography> (released) through the `Class.InputBinding.Down|Down` property</li><li style={{marginBottom: -16}}>`Datatype.Vector3` of <Typography noWrap>`(-1, 0, 0)`</Typography> (pressed) or <Typography noWrap>`(0, 0, 0)`</Typography> (released) through the `Class.InputBinding.Left|Left` property</li><li style={{marginBottom: -16}}>`Datatype.Vector3` of <Typography noWrap>`(1, 0, 0)`</Typography> (pressed) or <Typography noWrap>`(0, 0, 0)`</Typography> (released) through the `Class.InputBinding.Right|Right` property</li><li style={{marginBottom: -16}}>`Datatype.Vector3` of <Typography noWrap>`(0, 0, -1)`</Typography> (pressed) or <Typography noWrap>`(0, 0, 0)`</Typography> (released) through the `Class.InputBinding.Forward|Forward` property</li><li>`Datatype.Vector3` of <Typography noWrap>`(0, 0, 1)`</Typography> (pressed) or <Typography noWrap>`(0, 0, 0)`</Typography> (released) through the `Class.InputBinding.Backward|Backward` property</li></ul></li></ul></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="ViewportPosition">
|
||||
The `Enum.InputActionType|ViewportPosition` type is best for absolute 2D viewport coordinates of an input such as a mouse pointer or touch, which can be used for features like custom cursors or selecting objects.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Valid Input Types on `Class.InputBinding|InputBindings`</th>
|
||||
<th>Returned to the `Class.InputAction` Event(s)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="40%">Variable input amounts from positional inputs such as a mouse pointer (`Enum.KeyCode.MousePosition|MousePosition`) or touch (`Enum.KeyCode.Touch|Touch`).</td>
|
||||
<td><ul style={{marginBottom: -16}}><li>`Class.InputAction.StateChanged|StateChanged` event:<ul><li>`Datatype.Vector2` between <Typography noWrap>`(0, 0)`</Typography> and the maximum absolute <Typography noWrap>`(X, Y)`</Typography> pixel size in the viewport.</li></ul></li></ul></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
<Alert severity="info">
|
||||
Note that returned `Datatype.Vector2`/`Datatype.Vector3` values for 2D/3D inputs will be normalized such that the magnitude is never greater than `1` (unless scaling is applied). For example, a 45° up+right press on a gamepad thumbstick will return a normalized `Datatype.Vector2` of <Typography noWrap>`(0.7071, 0.7071)`</Typography> instead of <Typography noWrap>`(1, 1)`</Typography>. In practical terms of character movement, this ensures that diagonal presses do not allow players to move faster diagonally than they would in a cardinal direction.
|
||||
</Alert><br />
|
||||
|
||||
To connect events for simple character sprinting:
|
||||
|
||||
1. Insert a new `Class.LocalScript` into the `CharacterSprint` tree, alongside the various input bindings.
|
||||
|
||||
<img src="../assets/studio/explorer/StarterGui-InputContext-InputAction-LocalScript.png" width="320" />
|
||||
|
||||
2. Paste the following code into the script. Note the `Class.InputAction.Pressed|Pressed` event connection on lines `13`‑`15` which doubles the character's walk speed when a sprint input binding is pressed, and the corresponding `Class.InputAction.Released|Released` event connection on lines `16`‑`18` which resets the walk speed to default when a sprint input binding is released.
|
||||
|
||||
```lua
|
||||
local Players = game:GetService("Players")
|
||||
|
||||
local player = Players.LocalPlayer
|
||||
local character = player.Character
|
||||
if not character or character.Parent == nil then
|
||||
character = player.CharacterAdded:Wait()
|
||||
end
|
||||
local humanoid = character:WaitForChild("Humanoid")
|
||||
local defaultWalkSpeed = humanoid.WalkSpeed
|
||||
|
||||
local inputAction = script.Parent
|
||||
|
||||
inputAction.Pressed:Connect(function()
|
||||
humanoid.WalkSpeed = defaultWalkSpeed * 2
|
||||
end)
|
||||
inputAction.Released:Connect(function()
|
||||
humanoid.WalkSpeed = defaultWalkSpeed
|
||||
end)
|
||||
```
|
||||
|
||||
3. Playtest your experience and test the character sprint action with the [bindings](#input-bindings) you chose previously: `Enum.KeyCode.LeftShift|LeftShift` for keyboard, `Enum.KeyCode.ButtonY|ButtonY` for gamepad, and the on‑screen `SprintButton` for touch‑enabled devices. Remember that you can use the [Controller Emulator](../studio/testing-modes.md#controller-emulation) to test gamepad inputs directly in Roblox Studio.
|
||||
|
||||
<video controls src="../assets/ui/button-text-input/Sprint-Demo.mp4" width="720"></video>
|
||||
|
||||
## Context changes
|
||||
|
||||
Once you have an [input context](#input-contexts) such as `PlayContext`, you can enable/disable it during gameplay through scripting, change its `Class.InputContext.Priority|Priority` to determine which actions take precedence over others, and `Class.InputContext.Sink|Sink` inputs from being processed within contexts of lower priority.
|
||||
|
||||
1. To make it easier to switch contexts from other scripts, insert a new `Class.BindableEvent` into `Class.StarterGui` and rename it to `ContextEvent`.
|
||||
|
||||
<img src="../assets/studio/explorer/StarterGui-BindableEvent-ContextEvent.png" width="320" />
|
||||
|
||||
2. Create a new `Class.LocalScript` inside `Class.StarterGui` and rename it to `UpdateContext`.
|
||||
|
||||
<img src="../assets/studio/explorer/StarterGui-LocalScript-UpdateContext.png" width="320" />
|
||||
|
||||
3. Inside the `UpdateContext` script, paste the following code:
|
||||
|
||||
```lua
|
||||
local Players = game:GetService("Players")
|
||||
|
||||
local player = Players.LocalPlayer
|
||||
local playerGui = player.PlayerGui
|
||||
|
||||
local contextEvent = playerGui:FindFirstChild("ContextEvent")
|
||||
|
||||
-- Connect bindable event
|
||||
contextEvent.Event:Connect(function(targetContext, enabled)
|
||||
local context = playerGui:FindFirstChild(targetContext)
|
||||
if context then
|
||||
context.Enabled = enabled
|
||||
print(context.Name .. ": " .. tostring(context.Enabled))
|
||||
else
|
||||
warn("InputContext not found!")
|
||||
end
|
||||
end)
|
||||
```
|
||||
|
||||
4. With the `UpdateContext` script in place, you can now update a named `Class.InputContext` by firing the bindable event, for example from another `Class.LocalScript` that powers a `Class.GuiButton` inside the `Class.ScreenGui` container.
|
||||
|
||||
<img src="../assets/studio/explorer/StarterGui-ScreenGui-TextButton.png" width="320" style={{marginBottom: 0}} />
|
||||
|
||||
```lua
|
||||
local Players = game:GetService("Players")
|
||||
|
||||
local player = Players.LocalPlayer
|
||||
local playerGui = player.PlayerGui
|
||||
|
||||
local contextEvent = playerGui:FindFirstChild("ContextEvent")
|
||||
|
||||
local button = script.Parent
|
||||
button.Activated:Connect(function()
|
||||
-- Fire bindable event with target input context and enabled state
|
||||
contextEvent:Fire("PlayContext", true)
|
||||
end)
|
||||
```
|
||||
|
||||
## Default bindings
|
||||
|
||||
<DefaultBindings components={props.components} />
|
||||
112
.cursor/rules/roblox/en-us/input/mobile.md
Normal file
112
.cursor/rules/roblox/en-us/input/mobile.md
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
---
|
||||
title: Mobile input
|
||||
description: Explains Roblox support for mobile devices.
|
||||
---
|
||||
|
||||
The majority of Roblox sessions are played on mobile devices, so it's important to consider the mobile [device orientation](#device-orientation) and other [cross‑platform](../projects/cross-platform.md) factors when designing an experience for a wide audience.
|
||||
|
||||
To simplify cross‑platform inputs, including player interaction with virtual buttons, Roblox provides the [Input Action System](../input/input-action-system.md) to define **actions** such as "jump," "sprint," or "shoot" and set up **bindings** for multiple hardware inputs to drive those actions.
|
||||
|
||||
Roblox also supports native mobile features like [haptic feedback](#haptic-feedback), touch gestures such as `Class.UserInputService.TouchSwipe|TouchSwipe` and `Class.UserInputService.TouchPinch|TouchPinch`, or accelerometer and gyroscope functionality on `Class.UserInputService.AccelerometerEnabled|AccelerometerEnabled` and `Class.UserInputService.GyroscopeEnabled|GyroscopeEnabled` devices.
|
||||
|
||||
## Input type detection
|
||||
|
||||
In cross‑platform development, it's important that you determine and respond to the `Class.UserInputService.PreferredInput|PreferredInput` type a player is using, normally to ensure that [UI elements](../ui/index.md#ui-objects) like on-screen buttons and menus work elegantly and support interaction across devices.
|
||||
|
||||
For example, a touch-enabled device assumes touch is the default input and that touch-buttons may appear for actions, but a player may choose to connect a bluetooth gamepad. In this case, touch remains a valid input, but you can assume the player wants to switch to the connected gamepad as the **primary** input type and possibly use touch as a backup input for on-screen UI.
|
||||
|
||||
See [input type detection](./index.md#input-type-detection) for more information.
|
||||
|
||||
## Device orientation
|
||||
|
||||
By default, Roblox experiences run in **landscape** mode, allowing the experience to switch between landscape "left" and landscape "right" as the player's device rotates. However, experiences can be locked to a particular orientation if desired.
|
||||
|
||||
There are five different orientation modes, including two sensor-based modes and three locked modes.¹ Each of these can be set as the **default** orientation through `Class.StarterGui.ScreenOrientation`, accessible through Studio's [Properties](../studio/properties.md) window.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="2">Sensor Modes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>`Enum.ScreenOrientation|LandscapeSensor`</td>
|
||||
<td>The default Roblox setting in which the experience always appears in landscape mode (no portrait mode) and the device detects its physical orientation to ensure the experience view is always oriented upward.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`Enum.ScreenOrientation|Sensor`</td>
|
||||
<td>The device detects its physical orientation to ensure the experience view is always oriented upward, switching between landscape and portrait mode as needed.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="2">Locked Modes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>`Enum.ScreenOrientation|LandscapeLeft`</td>
|
||||
<td>On devices with a virtual home/nav bar, its touch region is at the bottom of the display. On devices with a physical home button, the home button is to the left of the display.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`Enum.ScreenOrientation|LandscapeRight`</td>
|
||||
<td>On devices with a virtual home/nav bar, its touch region is at the bottom of the display. On devices with a physical home button, the home button is to the right of the display.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>`Enum.ScreenOrientation|Portrait`</td>
|
||||
<td>On devices with a virtual home/nav bar, its touch region is at the bottom of the display. On devices with a physical home button, the home button is below the display.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<figcaption>¹ Roblox does not include a "portrait upside-down" mode since many devices do not natively support that orientation</figcaption><br /><br />
|
||||
|
||||
Beyond the default `Class.StarterGui.ScreenOrientation` property, you can change orientation during gameplay through `Class.PlayerGui.ScreenOrientation`. This can be useful when an experience needs to enforce an orientation, such as locking the view to `Enum.ScreenOrientation|Portrait` for a minigame.
|
||||
|
||||
The following code in a `Class.LocalScript` sets the screen orientation to portrait after a short delay:
|
||||
|
||||
```lua title="LocalScript - Change Screen Orientation to Portrait"
|
||||
local Players = game:GetService("Players")
|
||||
|
||||
local player = Players.LocalPlayer
|
||||
local playerGui = player.PlayerGui
|
||||
|
||||
task.wait(5)
|
||||
|
||||
playerGui.ScreenOrientation = Enum.ScreenOrientation.Portrait
|
||||
```
|
||||
|
||||
Finally, you can detect changes to screen orientation during gameplay by listening to value changes on the `Class.PlayerGui.CurrentScreenOrientation` property.
|
||||
|
||||
```lua title="LocalScript - Detect Screen Orientation Changes"
|
||||
local Players = game:GetService("Players")
|
||||
|
||||
local player = Players.LocalPlayer
|
||||
local playerGui = player.PlayerGui
|
||||
|
||||
local function onOrientationChange()
|
||||
print("Orientation changed to", playerGui.ScreenOrientation)
|
||||
end
|
||||
|
||||
playerGui:GetPropertyChangedSignal("ScreenOrientation"):Connect(onOrientationChange)
|
||||
```
|
||||
|
||||
## Haptic feedback
|
||||
|
||||
Most mobile devices have motors built in to provide haptic feedback. Adding rumbles and vibrations can greatly enhance a player's experience and provide subtle feedback beyond visuals or audio.
|
||||
|
||||
Roblox supports haptics for haptic-capable devices including most iPhone, Pixel, and Samsung Galaxy devices. Haptic feedback is managed through `Class.HapticEffect` instances which can be set to a specific `Class.HapticEffect.Type|Type` such as `Enum.HapticEffectType|GameplayCollision` or `Enum.HapticEffectType|UIClick`.
|
||||
|
||||
Once a `Class.HapticEffect` is in place, you can initiate it through the `Class.HapticEffect:Play()|Play()` method, for instance:
|
||||
|
||||
```lua
|
||||
local Workspace = game:GetService("Workspace")
|
||||
|
||||
local effect = Instance.new("HapticEffect")
|
||||
effect.Type = Enum.HapticEffectType.GameplayExplosion
|
||||
effect.Parent = Workspace
|
||||
|
||||
-- Play the haptic effect
|
||||
effect:Play()
|
||||
```
|
||||
95
.cursor/rules/roblox/en-us/input/mouse-and-keyboard.md
Normal file
95
.cursor/rules/roblox/en-us/input/mouse-and-keyboard.md
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
---
|
||||
title: Mouse and keyboard input
|
||||
description: Explains Roblox support for computer mice and keyboards.
|
||||
---
|
||||
|
||||
A large percentage of Roblox sessions are played on devices with a mouse and keyboard, so it's important to support these inputs when designing an experience for a wide audience.
|
||||
|
||||
To simplify [cross‑platform](../projects/cross-platform.md) inputs, including mouse/keyboard, Roblox provides the [Input Action System](../input/input-action-system.md) to define **actions** such as "jump," "sprint," or "shoot" and set up **bindings** for multiple hardware inputs to drive those actions.
|
||||
|
||||
Roblox also supports general mouse/keyboard input through `Class.UserInputService` events like `Class.UserInputService.InputBegan|InputBegan` and `Class.UserInputService.InputEnded|InputEnded` and methods like `Class.UserInputService:IsKeyDown()|IsKeyDown()` to check if a particular key is pressed on a keyboard.
|
||||
|
||||
## Input type detection
|
||||
|
||||
In cross‑platform development, it's important that you determine and respond to the `Class.UserInputService.PreferredInput|PreferredInput` type a player is using, normally to ensure that [UI elements](../ui/index.md#ui-objects) like on-screen buttons and menus work elegantly and support interaction across devices.
|
||||
|
||||
For example, a PC or laptop assumes mouse/keyboard is the default input, but a player may choose to connect a bluetooth gamepad. In this case, mouse/keyboard remains a valid input, but you can assume the player wants to switch to the connected gamepad as the **primary** input type.
|
||||
|
||||
See [input type detection](./index.md#input-type-detection) for more information.
|
||||
|
||||
## Generic mouse/key input
|
||||
|
||||
Beyond the [Input Action System](../input/input-action-system.md), you can capture mouse and keyboard inputs using `Class.UserInputService`. The following `Class.LocalScript`, when placed in `Class.StarterPlayerScripts`, captures the began and ended phases of key and mouse clicks and prints the result to the [Output](../studio/output.md) window.
|
||||
|
||||
```lua title="LocalScript - Output Key/Mouse Began and Ended"
|
||||
local UserInputService = game:GetService("UserInputService")
|
||||
|
||||
local function onInputBegan(inputObject, processedEvent)
|
||||
-- Return if another script has already processed the input
|
||||
if processedEvent then return end
|
||||
|
||||
print(inputObject.KeyCode.Name, "began!", inputObject.Position)
|
||||
end
|
||||
|
||||
local function onInputEnded(inputObject, processedEvent)
|
||||
-- Return if another script has already processed the input
|
||||
if processedEvent then return end
|
||||
|
||||
print(inputObject.KeyCode.Name, "ended!", inputObject.Position)
|
||||
end
|
||||
|
||||
UserInputService.InputBegan:Connect(onInputBegan)
|
||||
UserInputService.InputEnded:Connect(onInputEnded)
|
||||
```
|
||||
|
||||
## Mouse icon
|
||||
|
||||
You can customize the appearance and behavior of a player's mouse icon within your experience to create a cohesive style across all of your UI elements. This includes temporarily changing the player's mouse icon in specific circumstances, such as hovering over a button.
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="Change Icon">
|
||||
You can change the player's mouse icon in a `Class.LocalScript` by setting the `Class.UserInputService.MouseIcon|MouseIcon` property in `Class.UserInputService` to a custom Roblox asset ID. For example, the following `Class.LocalScript` changes the player's default mouse icon to a circle with a blue dot in the middle.
|
||||
|
||||
```lua highlight="3"
|
||||
local UserInputService = game:GetService("UserInputService")
|
||||
|
||||
UserInputService.MouseIcon = "rbxassetid://3400146391"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="Hide Icon">
|
||||
You can hide the player's mouse icon by setting the `Class.UserInputService.MouseIconEnabled` to `false` in a `Class.LocalScript`. For example, the following code switches the mouse icon from visible to invisible and back every two seconds.
|
||||
|
||||
```lua highlight="5,7"
|
||||
local UserInputService = game:GetService("UserInputService")
|
||||
|
||||
while true do
|
||||
task.wait(2)
|
||||
UserInputService.MouseIconEnabled = false
|
||||
task.wait(2)
|
||||
UserInputService.MouseIconEnabled = true
|
||||
end
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="Lock Icon">
|
||||
You can lock the mouse icon's position to the screen using `Class.UserInputService.MouseBehavior` with a `Enum.MouseBehavior` value of `Enum.MouseBehavior|LockCurrentPosition` or `Enum.MouseBehavior|LockCenter`, then unlock it again with a value of `Enum.MouseBehavior|Default`.
|
||||
|
||||
If a player's mouse icon is locked in a position, `Class.UserInputService.InputChanged` still fires when the player moves the mouse, passing in the distance the mouse has moved. For example, the following code sample locks the player's mouse icon after one second, then Studio prints the mouse delta whenever the player moves their mouse.
|
||||
|
||||
```lua highlight="5"
|
||||
local UserInputService = game:GetService("UserInputService")
|
||||
|
||||
task.wait(5)
|
||||
|
||||
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition
|
||||
|
||||
UserInputService.InputChanged:Connect(function(inputObject)
|
||||
if inputObject.UserInputType == Enum.UserInputType.MouseMovement then
|
||||
print("Mouse delta is (" .. tostring(inputObject.Delta.X) .. ", " .. tostring(inputObject.Delta.Y) .. ")")
|
||||
end
|
||||
end)
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
Loading…
Add table
Add a link
Reference in a new issue