---
order: 1
title: Touch
type: Interact
label: Interact
---

Galacean's touch is based on [Pointer](https://www.w3.org/TR/pointerevents3/), which smooths out the differences between [Mouse](https://developer.mozilla.org/zh-CN/docs/Web/API/MouseEvent) and [Touch](https://developer.mozilla.org/zh-CN/docs/Web/API/TouchEvent), making touch unified in both concept and interface.

## Pointer

In Galacean, whether it's a mouse on a PC, a stylus or a finger on a mobile device, when it performs the corresponding behavior within the touch range (**Down**, **Move**, etc.), it will be instantiated as a [Pointer](/apis/core/#Pointer). You can get all the currently active touch points in the [InputManager](/apis/core/#InputManager).

<img src="https://mdn.alipayobjects.com/huamei_yo47yq/afts/img/A*k6_aRKNVxGkAAAAAAAAAAAAADhuCAQ/original" alt="image.png"  />

> It should be noted that each touch point is independent of each other, they respond to the corresponding events and callback the corresponding hook functions.

### Lifecycle

Each touch point will start its life in **PointerDown** or **PointerMove**, and leave the stage in **PointerLeave** or **PointerCancel**. In Galacean, you can get the real-time status of this touch point through `Pointer.phase`.

```mermaid
timeline
    title Phase of pointer
    ……
    Frame 100 : 「PointerDown」
              : pointer.phase = PointerPhase.Down
    Frame 101 : 「PointerMove」
              : pointer.phase = PointerPhase.Move
    Frame 102 : 「Nothing」
              : pointer.phase = PointerPhase.Stationary
    Frame 103 : 「PointerUp」
              : pointer.phase = PointerPhase.Up
    Frame 104 : 「PointerLeave」
              : pointer.phase = PointerPhase.Leave
    ……
```

### Touch Buttons

Referring to the [W3C standard](https://www.w3.org/TR/uievents/#dom-mouseevent-button) and [Microsoft related documentation](https://learn.microsoft.com/en-us/dotnet/api/system.windows.input.mousebutton?view=windowsdesktop-6.0), Galacean defines touch buttons as follows:

| Enumeration                                      | Explanation                                                      |
| :---------------------------------------------- | :--------------------------------------------------------------- |
| [None](/apis/core/#PointerButton-None)        | No touch button pressed                                          |
| [Primary](/apis/core/#PointerButton-Primary)  | The primary button of the device, usually the left button (mouse) or the only button on a single-button device (finger) |
| [Secondary](/apis/core/#PointerButton-Secondary) | The secondary button of the device, usually the right button (mouse) |
| [Auxiliary](/apis/core/#PointerButton-Auxiliary) | The auxiliary button of the device, usually the wheel (mouse)    |
| [XButton1](/apis/core/#PointerButton-XButton1) | The extended button of the device, usually the undo button (mouse) |
| [XButton2](/apis/core/#PointerButton-XButton2) | The extended button of the device, usually the redo button (mouse) |
| [XButton3](/apis/core/#PointerButton-XButton3) | Extended button                                                  |
| [XButton4](/apis/core/#PointerButton-XButton4) | Extended button                                                  |
| ……                                              | ……                                                               |


### Touch Callbacks

You only need to add touch callbacks to an Entity with a Collider component to enable interaction with rendered objects. Touch callbacks are integrated into the engine's [script lifecycle](/en/docs/script/class/#脚本生命周期), allowing users to easily add the following events. The hook functions will carry the Pointer instance that triggered the callback.

| Interface                                           | Trigger Timing and Frequency                                               |
| :-------------------------------------------------- | :------------------------------------------------------------------------- |
| [onPointerEnter](/apis/core/#Script-onPointerEnter) | Triggered once when the touch point enters the Entity's collider range     |
| [onPointerExit](/apis/core/#Script-onPointerExit)   | Triggered once when the touch point leaves the Entity's collider range     |
| [onPointerDown](/apis/core/#Script-onPointerDown)   | Triggered once when the touch point is pressed within the Entity's collider range |
| [onPointerUp](/apis/core/#Script-onPointerUp)       | Triggered once when the touch point is released within the Entity's collider range |
| [onPointerClick](/apis/core/#Script-onPointerClick) | Triggered once when the touch point is pressed and released within the Entity's collider range |
| [onPointerDrag](/apis/core/#Script-onPointerDrag)   | Continuously triggered when the touch point is pressed within the Entity's collider range until the touch point is no longer pressed |

<Callout type="info">
Touch callbacks **depend on the physics engine**. Please ensure the physics engine is initialized before using this feature.
</Callout>


### Raycasting

Touch callbacks are implemented based on raycasting. Customizing raycasting is also very simple, just follow these steps.

```mermaid
flowchart LR
   A[Add Collider Component] --> B[Get Touch Point] --> C[Get Ray from Canvas Coordinates] --> Raycasting
```

Refer to [Collider Component](/en/docs/physics/collider/) for adding a collider component. The code logic for implementing the detection part is as follows:

```typescript
// 假设当前有一个活动的触控点
const pointer = inputManager.pointers[0];
// 通过触控点得到由相机发射的射线
const ray = camera.screenPointToRay(pointer.position, new Ray());
// 射线与场景的碰撞体进行碰撞检测
const hitResult = new HitResult();
if (scene.physics.raycast(ray, 100, hitResult)) {
  console.log("Hit entity", hitResult.entity);
}
```

## Compatibility

As of February 2024, the compatibility of PointerEvent across different platforms has reached [96.35%](https://caniuse.com/?search=PointerEvent).

<Callout type="info">
️ If you encounter compatibility issues on a platform, you can raise an issue at https://github.com/galacean/polyfill-pointer-event.
</Callout>

## QA

### Touch works fine on PC but behaves abnormally on mobile devices

On mobile devices, touch interactions trigger the default behavior of HTML elements. Once the default behavior is triggered, the touch interaction is removed from the element (PointerCancel). This can be resolved by setting the `touchAction` of the listening source. If the listening source is the default canvas:

```typescript
(engine.canvas._webCanvas as HTMLCanvasElement).style.touchAction = "none";
```

### Right-click operation fails, context menu pops up

This is caused by the default behavior triggered by the right-click. You can add the following code to prevent it:

```typescript
document.oncontextmenu = (e) => {
  e.preventDefault();
};
```
