Skip to content

t1k:cocos:playable:input-service

FieldValue
Moduleplayable
Version0.5.6
Efforthigh
Tools

Keywords: ads, cocos, gesture, input, InputService, playable, raycasting, touch

/t1k:cocos:playable:input-service

Cocos Component attached to a scene node. Listens to global input events and fires typed signals via SignalBus. See t1k-cocos-playable-signalbus for subscription patterns.

  • InputService — Cocos Component (attach to scene node), registers TOUCH_START/MOVE/END handlers in onLoad
  • InputSignals — Plain TS classes emitted via SignalBus; no constructor needed for FirstInteractionSignal
  • InputServiceConfig — Optional config overrides passed to configure()

Default thresholds: swipeThreshold=50px, swipeVelocityThreshold=300px/s, tapMaxDuration=300ms, tapMaxDistance=10px

SignalPayloadFires when
TouchStartSignalworldPosition, uiPositionfinger touches screen
TouchEndSignalworldPosition, uiPositionfinger lifts
TapSignalworldPosition, uiPositionduration < 300ms AND distance < 10px
SwipeSignal`direction (‘up''down'
DragSignalworldPosition, uiPosition, deltaevery TOUCH_MOVE
FirstInteractionSignalfirst ever touch (once per session)
RaycastHitSignalhitNode, hitPoint3D ray hits on TOUCH_START
RaycastMoveSignalhitNode, hitPoint3D ray hits on TOUCH_MOVE
RaycastEndSignalhitNode, hitPoint3D ray hits on TOUCH_END
// Runtime configuration (merge over defaults)
inputService.configure({ swipeThreshold: 80, tapMaxDuration: 200 });
// Provide explicit 2D camera for screen→world conversion
inputService.setMainCamera(camera2D);
// Enable 3D raycasting (auto-enables when set)
inputService.set3DCamera(camera3D);
// OR assign via @property in editor: inputService.camera3D = camera;
// Toggle all input processing
inputService.setEnabled(false);
// Raycast mask for filtering physics layers (default = all layers)
inputService.configure({ raycastMask: 1 << 3 }); // layer 3 only

Subscribe to tap anywhere:

SignalBus.instance.subscribe(TapSignal, (s) => {
console.log('tap at UI', s.uiPosition);
});

Detect first touch (BGM unlock):

// PlayableHelper already handles this — autoPlayMusicOnFirstTouch = true
// For custom logic:
SignalBus.instance.subscribe(FirstInteractionSignal, () => {
AudioService.instance.playMusic(Constant.AUDIO_NAME.BGM);
});

4-directional swipe:

SignalBus.instance.subscribe(SwipeSignal, (s) => {
if (s.direction === 'up') movePlayerUp();
});

3D object picking (drag):

// 1. Assign camera3D in editor @property or via set3DCamera()
// 2. Subscribe to raycast signals:
SignalBus.instance.subscribe(RaycastHitSignal, (s) => {
s.hitNode.getComponent(MyObject)?.onSelect();
});
SignalBus.instance.subscribe(RaycastMoveSignal, (s) => {
s.hitNode.setWorldPosition(s.hitPoint);
});

Screen-to-world conversion (internal): Uses camera.screenToWorld() auto-detected from Canvas if mainCamera not explicitly set.

PlayableHelper subscribes FirstInteractionSignal → plays BGM, and optionally subscribes TapSignal for redirect-after-N-clicks. Do not duplicate these subscriptions.

  • Attaching InputService to a node that gets destroyed early — use a persistent scene root node
  • Setting camera3D without enabling the PhysicsSystem in project settings (raycasts silently skip)
  • Forgetting to call setEnabled(false) during loading/cutscenes — tap/swipe signals still fire otherwise
  • Subscribing TapSignal when PlayableHelper.autoPlayMusicOnFirstTouch is true creates duplicate BGM play calls if you also subscribe FirstInteractionSignal
  • Touch events on Cocos Web target document, not Canvas — adding a div over the canvas blocks input silently.
  • Gamepad polling is per-frame, not per-event — debounce in user code if you need event semantics.
  • Multi-touch pinches deliver two unsynchronised TouchMove events per frame — buffer before reacting.