Loading...
Loading...
System-level input polling and player movement control in Decentraland. Covers inputSystem, InputModifier, PointerLock, and PrimaryPointerInfo. Use when the user wants continuous key polling, WASD-controlled entities, to freeze the player during a cutscene, FPS-style cursor lock, or multi-key combo patterns. For event-driven clicks and hover on entities see add-interactivity.
npx skill4agent add decentraland/sdk-skills advanced-inputadd-interactivitypointerEventsSystem.onPointerDown()inputSystemimport { engine, PointerLock } from '@dcl/sdk/ecs'
function checkPointerLock() {
const isLocked = PointerLock.get(engine.CameraEntity).isPointerLocked
if (isLocked) {
// Cursor is captured — player is in first-person control
} else {
// Cursor is free — player can click UI elements
}
}
engine.addSystem(checkPointerLock)PointerLock.isPointerLocked31,20-pointer-lock-controlPointerLock.createOrReplace(engine.CameraEntity, { isPointerLocked: false })
// request lock (e.g. from a button)
PointerLock.getMutable(engine.CameraEntity).isPointerLocked = true
// release lock
PointerLock.getMutable(engine.CameraEntity).isPointerLocked = falsegetMutable(engine.CameraEntity)PointerLockPointerLock.createOrReplace(engine.CameraEntity, { isPointerLocked: false })main()truePointerLock.onChange(engine.CameraEntity, (pointerLock) => {
if (pointerLock?.isPointerLocked) {
console.log('Cursor locked')
} else {
console.log('Cursor unlocked')
}
})import { engine, PrimaryPointerInfo } from '@dcl/sdk/ecs'
function readPointer() {
const pointerInfo = PrimaryPointerInfo.getOrCreateMutable(engine.RootEntity)
console.log('Cursor position:', pointerInfo.screenCoordinates)
console.log('Cursor delta:', pointerInfo.screenDelta)
console.log('World ray direction:', pointerInfo.worldRayDirection)
}
engine.addSystem(readPointer)screenCoordinatesscreenDeltaxyscreenCoordinatesworldRayDirectionscreenDeltaworldRayDirectionpointerType010,5-primary-cursor-infopointerInfo.screenCoordinates?.x ?? -666pointerInfo.worldRayDirection?.x.toFixed(2)getOrCreateMutable(engine.RootEntity)worldRayDirectionimport { engine, inputSystem, InputAction, PointerEventType } from '@dcl/sdk/ecs'
function myInputSystem() {
// Check for click on a specific entity
const clickData = inputSystem.getInputCommand(
InputAction.IA_POINTER,
PointerEventType.PET_DOWN,
myEntity
)
if (clickData) {
console.log('Entity clicked via system:', clickData.hit.entityId)
}
}
engine.addSystem(myInputSystem)hitgetInputCommand()InputAction.IA_ANYgetInputCommand(InputAction.IA_ANY, PointerEventType.PET_DOWN)cmd.button0,1-input-modifierengine.getEntitiesByTaggetInputCommand{baseDir}/references/input-patterns.mdisTriggered()isPressed()function globalInputSystem() {
// Was the key just pressed this frame?
if (inputSystem.isTriggered(InputAction.IA_PRIMARY, PointerEventType.PET_DOWN)) {
console.log('E key pressed!')
}
// Is the key currently held down?
if (inputSystem.isPressed(InputAction.IA_SECONDARY)) {
console.log('F key is held!')
}
}
engine.addSystem(globalInputSystem)| InputAction | Key/Button |
|---|---|
| Left mouse button |
| E key |
| F key |
| 1 key |
| 2 key |
| 3 key |
| 4 key |
| Space key |
| W key |
| S key |
| A key |
| D key |
| Control key |
| Shift key (run) |
| Matches any input action (wildcard — use with |
PointerEventType.PET_DOWN // Button/key pressed
PointerEventType.PET_UP // Button/key released
PointerEventType.PET_HOVER_ENTER // Cursor enters entity
PointerEventType.PET_HOVER_LEAVE // Cursor leaves entityimport { engine, InputModifier } from '@dcl/sdk/ecs'
// Freeze player completely
InputModifier.create(engine.PlayerEntity, {
mode: InputModifier.Mode.Standard({ disableAll: true })
})
// Restrict specific movement (all flags optional; a false/omitted flag is ignored)
InputModifier.createOrReplace(engine.PlayerEntity, {
mode: InputModifier.Mode.Standard({
disableWalk: true,
disableJog: true,
disableRun: true,
disableJump: true,
disableEmote: true,
disableDoubleJump: true,
disableGliding: true
})
})
// Restore normal movement
InputModifier.deleteFrom(engine.PlayerEntity)input_modifier.gen.d.tsdisableAlldisableWalkdisableJogdisableRundisableJumpdisableEmotedisableDoubleJumpdisableGlidingfalseInputModifier.Mode.Standard({...}){ $case: 'standard', standard: {...} }disableAllInputModifier.deleteFrom{baseDir}/references/input-patterns.mdIA_FORWARDIA_BACKWARDIA_LEFTIA_RIGHTisPressedTransformInputModifier{baseDir}/references/input-patterns.mdIA_ACTION_3IA_ACTION_6isTriggered{baseDir}/references/input-patterns.mdimport { getPlatform, isMobile } from '@dcl/sdk/platform'
// getPlatform() returns 'mobile' | 'desktop' | 'web' | null
// Returns null until the explorer reports its platform (async, shortly after scene start)
// Defer platform-dependent setup until getPlatform() is non-null:
function platformCheckSystem() {
if (getPlatform() === null) return
engine.removeSystem(platformCheckSystem)
if (isMobile()) {
// mobile-specific setup here (e.g. larger UI, touch-friendly interactions)
}
}
engine.addSystem(platformCheckSystem)@dcl/sdk/platform17ca7be17ca7beborderRadiusScreenInsetArea@dcl/sdk/react-ecsdisableWalkdisableJoggetInputCommand(IA_ANY, PET_DOWN)PointerLock.isPointerLockedPointerLock.onChangePrimaryPointerInfoworldRayDirectionisPressed(IA_FORWARD/...)getEntitiesWith(Cube, PointerEvents)inputSystem.isTriggered(IA_POINTER, PET_DOWN, entity)PrimaryPointerInfo.screenDeltascreenDeltascreenCoordinates{baseDir}/references/input-patterns.mdadd-interactivity