> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-ko/sdk7/interactivity/button-events/system-based-events.md).

# 시스템 기반 이벤트

씬에서 사용자 클릭을 처리하는 방법을 알아봅니다.

씬에 동일한 로직으로 모두 활성화되는 유사한 엔티티가 여러 개 있다면, 모든 엔티티를 순회하는 단일 시스템을 작성하여 그 동작을 한 번만 설명할 수 있습니다. 이것은 가장 성능이 좋고 더 [데이터 지향적인](/creator/content-creator-ko/sdk7/architecture/data-oriented-programming.md) 접근 방식입니다.

시스템을 사용하여 다음도 감지할 수 있습니다 [전역 입력 이벤트](#global-input-events), 따라서 플레이어의 커서가 어디를 향하는지와 관계없이 키가 눌릴 때마다 씬이 반응합니다.

단일 엔티티에서 버튼을 클릭하거나 눌러 활성화하기만 하려는 경우, 가장 쉬운 방법은 다음을 사용하는 것입니다 [콜백 등록](/creator/content-creator-ko/sdk7/interactivity/button-events/register-callback.md) 접근 방식입니다.

더 구체적인 사용자 지정 로직을 설정하려면 원시 데이터를 다루고 다음을 사용해야 할 수 있습니다 [고급](/creator/content-creator-ko/sdk7/interactivity/button-events/advanced-button-events.md) 접근 방식입니다.

엔티티가 상호작용 가능하려면 다음이 있어야 합니다 [collider](/creator/content-creator-ko/sdk7/3d/colliders.md). 참고: [장애물](/creator/content-creator-ko/sdk7/interactivity/button-events/click-events.md#obstacles) 에서 자세한 내용을 확인하세요. 이는 근접 클릭 이벤트에도 적용됩니다.

## 시스템 사용하기

입력에서 헬퍼 함수 중 하나를 실행하여 버튼 이벤트를 확인합니다 `inputSystem` 네임스페이스를 매 틱마다 다음 내부에서 실행합니다 [시스템](/creator/content-creator-ko/sdk7/architecture/systems.md).

예를 들어, 다음 시스템은 `inputSystem.isTriggered()` 함수를 사용하여 포인터가 클릭되었는지 확인합니다. 매 틱마다 버튼이 눌렸는지 확인합니다. 만약 `inputSystem.isTriggered()` 반환합니다 *true*, 시스템은 이에 반응하여 일부 사용자 지정 로직을 실행합니다.

```ts
engine.addSystem(() => {
	if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_DOWN)) {
		// 버튼 누름에 반응하는 로직
	}
})
```

다음 헬퍼 함수는 `inputSystem` 네임스페이스에서 사용할 수 있으며, 매 틱마다 비슷한 방식으로 호출할 수 있습니다:

* `inputSystem.isTriggered`: 마지막 틱 이후 입력 작업이 발생했으면 true를 반환합니다.
* `inputSystem.isPressed`: 입력이 현재 눌린 상태이면 true를 반환합니다. 버튼이 다시 올라갈 때까지 매 틱마다 true를 반환합니다.
* `inputSystem.getInputCommand`: 입력 작업에 관한 데이터가 포함된 객체를 반환합니다.

각 항목에 관한 자세한 내용은 아래 섹션을 참조하세요.

엔티티의 버튼 이벤트를 처리할 때는 항상 플레이어에게 피드백을 제공하여, 엔티티와 상호작용할 수 있음을 알리세요. 다음을 추가하면 `PointerEvents` 컴포넌트를 엔티티에 추가하면 플레이어는 해당 엔티티 위에 커서를 올릴 때 힌트를 보게 됩니다. 다음을 참조하세요 [피드백 표시](#show-feedback) 에서 상호작용 가능한 엔티티에 호버 힌트를 추가하는 방법을 알아보세요.

### 전역 입력 이벤트

다음을 사용하세요 `inputSystem.isTriggered` SDK가 추적하는 모든 입력에서 버튼 누름 및 버튼 뗌 이벤트를 감지합니다.

```ts
engine.addSystem(() => {
	if (
		inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_DOWN)
	) {
		// 버튼 누름에 반응하는 로직
	}
})
```

위 예제는 포인터가 어디에 있거나 경로에 어떤 엔티티가 있는지와 관계없이 버튼이 눌렸는지 확인합니다.

`inputSystem.isTriggered()` 반환합니다 *true* 표시된 버튼이 게임 루프의 현재 틱에서 눌린 경우에만 해당합니다. 버튼이 눌리지 않았거나 이전 틱부터 이미 눌린 상태였다면 다음을 반환합니다 *false*.

{% hint style="warning" %}
**📔 참고**: 포인터 이벤트가 감지되려면 플레이어가 씬의 경계 안에 서 있어야 합니다. 플레이어의 커서도 잠겨 있어야 하며, 자유 커서 상태에서 누른 버튼은 감지되지 않습니다.

상호작용하려는 모든 엔티티에는 둘 다 다음이 있어야 합니다 [`PointerEvents` 컴포넌트](#show-feedback) 와 하나의 [collider](/creator/content-creator-ko/sdk7/3d/colliders.md).
{% endhint %}

이 `inputSystem.isTriggered` 함수는 다음 필수 인수를 받습니다:

* `InputAction`: 수신할 입력으로, 다음의 값입니다 `InputAction` 열거형의 값을 사용합니다. 다음을 참조하세요 [포인터 버튼](/creator/content-creator-ko/sdk7/interactivity/button-events/click-events.md#pointer-buttons) 에서 지원되는 옵션을 확인하세요.
* `PointerEventType`: 수신할 이벤트 유형으로, 다음의 값입니다 `PointerEventType` 열거형의 값을 사용합니다. 다음을 참조하세요 [포인터 이벤트의 종류](/creator/content-creator-ko/sdk7/interactivity/button-events/click-events.md#types-of-pointer-events) 에서 지원되는 옵션을 확인하세요.

### 엔티티 활성화

특정 엔티티를 가리키는 동안 버튼 이벤트를 감지하려면 세 번째 선택적 인수를 다음에 전달하세요 `inputSystem.isTriggered` 에서 확인할 엔티티를 지정합니다.

```ts
// 엔티티에 PointerEvents 컴포넌트 부여
PointerEvents.create(myEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_PRIMARY,
				showFeedback: false,
			},
		},
	],
})

// 시스템 생성
engine.addSystem(() => {
	if (
		inputSystem.isTriggered(
			InputAction.IA_POINTER,
			PointerEventType.PET_DOWN,
			myEntity
		)
	) {
		// myEntity에서의 버튼 누름에 반응하는 로직
	}
})
```

위 예제는 단일 하드코딩된 엔티티가 포인터 버튼(마우스 왼쪽 버튼)으로 눌렸는지 매 틱마다 확인합니다.

이 `inputSystem.isTriggered` 함수는 다음 인수를 사용합니다:

* `InputAction`: 수신할 입력으로, 다음의 값입니다 `InputAction` 열거형의 값을 사용합니다. 다음을 참조하세요 [포인터 버튼](/creator/content-creator-ko/sdk7/interactivity/button-events/click-events.md#pointer-buttons) 에서 지원되는 옵션을 확인하세요.
* `PointerEventType`: 수신할 이벤트 유형으로, 다음의 값입니다 `PointerEventType` 열거형의 값을 사용합니다. 다음을 참조하세요 [포인터 이벤트의 종류](/creator/content-creator-ko/sdk7/interactivity/button-events/click-events.md#types-of-pointer-events) 에서 지원되는 옵션을 확인하세요.
* `Entity` *(선택 사항)*: 이 이벤트를 확인할 엔티티입니다. 값을 제공하지 않으면 플레이어의 커서가 어디를 가리켰는지와 관계없이 전역 버튼 누름을 확인합니다.

이 예제에서는 다음도 추가한다는 점에 유의하세요 `PointerEvents` 상호작용하려는 엔티티에 컴포넌트를 추가합니다. 이 단계는 필수이며, 이 컴포넌트가 없으면 엔티티는 다음의 어떤 함수로도 감지되지 않습니다 `inputSystem`. 다음을 참조하세요 [피드백 표시](#show-feedback) 에서 다음에 관한 자세한 내용을 확인하세요 `PointerEvents` 컴포넌트를 추가해야 합니다.

{% hint style="warning" %}
**📔 참고**: 및 [collider](/creator/content-creator-ko/sdk7/3d/colliders.md). 참고: [장애물](/creator/content-creator-ko/sdk7/interactivity/button-events/click-events.md#obstacles) 자세한 내용은.
{% endhint %}

플레이어가 같은 방식으로 상호작용할 수 있는 엔티티가 여러 개라면 다음 사용을 고려하세요 `inputSystem.getInputCommand`. 이 명령은 엔티티 ID를 포함한 전역 클릭 명령 정보를 반환하며, 이를 사용해 모두를 처리하는 단일 함수를 실행할 수 있습니다.

```ts
engine.addSystem(() => {
	const result = inputSystem.getInputCommand(
		InputAction.IA_POINTER,
		PointerEventType.PET_DOWN
	)
	if (result) {
		if (result.hit?.entityId === myEntity) {
			// 클릭 처리
		}
	}
})
```

{% hint style="warning" %}
**📔 참고**: 상호작용하려는 모든 엔티티에는 둘 다 다음이 있어야 합니다 [`PointerEvents` 컴포넌트](#show-feedback) 와 하나의 [collider](/creator/content-creator-ko/sdk7/3d/colliders.md).
{% endhint %}

다음 [입력 액션의 데이터](#data-from-input-action) 에서 자세한 정보를 확인하세요. 이 메서드는 포인터 이벤트의 히트에 관한 더 상세한 데이터도 제공합니다.

### 입력 버튼 뗌

다음을 사용하여 매우 유사한 방식으로 포인터 뗌 이벤트도 확인할 수 있습니다 `PointerEventType.PET_UP`.

```ts
engine.addSystem(() => {
	if (
		inputSystem.isTriggered(
			InputAction.IA_POINTER,
			PointerEventType.PET_UP,
			myEntity
		)
	) {
		// myEntity를 가리키는 동안 버튼을 뗀 것에 반응하는 로직
	}
})
```

{% hint style="warning" %}
**📔 참고**: 특정 엔티티에 대해 포인터 뗌 이벤트를 확인할 때는 버튼을 눌렀을 당시 커서가 어디를 가리켰는지는 고려하지 않습니다. 버튼을 뗄 때 커서가 가리키는 위치만 고려합니다.

또한 엔티티에는 둘 다 다음이 있어야 한다는 점을 유념하세요 [`PointerEvents` 컴포넌트](#show-feedback) 와 하나의 [collider](/creator/content-creator-ko/sdk7/3d/colliders.md).
{% endhint %}

### 눌린 버튼 확인

다음을 사용하여 버튼이 현재 눌린 상태인지 확인합니다 `inputSystem.isPressed()` 를 시스템 내에서 사용합니다.

```ts
engine.addSystem(() => {
	if (inputSystem.isPressed(InputAction.IA_POINTER)) {
		// 버튼을 계속 누르고 있는 것에 반응하는 로직
	}
})
```

`inputSystem.isPressed()` 반환합니다 *true* 버튼을 언제 눌렀는지, 플레이어의 커서가 어디를 가리키는지와 관계없이 버튼이 현재 계속 눌린 상태이면 해당합니다. 그렇지 않으면 다음을 반환합니다 *false*.

이 `inputSystem.isPressed` 함수는 단일 인수를 받습니다:

* `InputAction`: 수신할 입력으로, 다음의 값입니다 `InputAction` 열거형의 값을 사용합니다. 다음을 참조하세요 [포인터 버튼](/creator/content-creator-ko/sdk7/interactivity/button-events/click-events.md#pointer-buttons) 에서 지원되는 옵션을 확인하세요.

### 여러 엔티티 처리

씬에 포인터 이벤트의 영향을 같은 방식으로 받는 엔티티가 여러 개 있다면, 이들 모두를 순회하는 시스템을 작성하는 것이 합리적입니다.

```ts
engine.addSystem(() => {
	const activatedEntites = engine.getEntitiesWith(PointerEvents)
	for (const [entity] of activatedEntites) {
		if (
			inputSystem.isTriggered(
				InputAction.IA_POINTER,
				PointerEventType.PET_DOWN,
				엔티티
			)
		) {
			// 엔티티와 상호작용하는 것에 반응하는 로직
		}
	}
})
```

이 예제는 다음을 사용합니다 [컴포넌트 쿼리](/creator/content-creator-ko/sdk7/architecture/querying-components.md) 를 사용하여 다음을 가진 모든 엔티티를 순회합니다 `PointerEvents` 컴포넌트. 그런 다음 이들 각각의 엔티티를 다음으로 확인합니다 `inputSystem.isTriggered`, 하나씩 순회합니다. 이 엔티티 중 하나에서 입력 작업이 감지되면 사용자 지정 로직을 수행합니다.

다음을 순회하는 대신 *모든* 다음을 가진 엔티티들 `PointerEvents` 컴포넌트를 하나의 시스템에서 처리하는 대신, 서로 다르게 동작해야 하는 엔티티를 처리하기 위해 서로 다른 시스템을 작성할 수 있습니다. 권장하는 방식은 서로 다른 유형의 엔티티를 특정 [커스텀 컴포넌트](/creator/content-creator-ko/sdk7/architecture/custom-components.md)로 표시하고, 별도의 시스템에서 각각을 순회하는 것입니다.

```ts
engine.addSystem(() => {
	const activatedDoors = engine.getEntitiesWith(IsDoor, PointerEvents)
	for (const [entity] of activatedDoors) {
		if (
			inputSystem.isTriggered(
				InputAction.IA_POINTER,
				PointerEventType.PET_DOWN,
				엔티티
			)
		) {
			openDoor(entity)
		}
	}
})

engine.addSystem(() => {
	const pickedUpGems = engine.getEntitiesWith(IsGem, PointerEvents)
	for (const [entity] of pickedUpGems) {
		if (
			inputSystem.isTriggered(
				InputAction.IA_POINTER,
				PointerEventType.PET_DOWN,
				엔티티
			)
		) {
			pickUp(entity)
		}
	}
})
```

이 예제에는 이름이 다음인 사용자 지정 컴포넌트를 가진 모든 엔티티를 순회하는 시스템 하나와 `IsDoor` 이름이 다음인 사용자 지정 컴포넌트를 가진 모든 엔티티를 순회하는 또 다른 시스템이 있습니다 `isGem`. 두 시스템 모두에서 일치하는 모든 엔티티가 포인터 버튼으로 활성화되었는지 확인합니다.

이러한 씬 코드 구성 방식은 매우 [데이터 지향적인](/creator/content-creator-ko/sdk7/architecture/data-oriented-programming.md) 하며 메모리 리소스를 매우 효율적으로 사용하게 됩니다.

\## 엔티티의 여러 버튼

다음과 같은 헬퍼를 사용하면 `pointerEventsSystem.onPointerDown`, 각 엔티티는 단일 이벤트 유형만 가질 수 있습니다. 서로 다른 두 버튼 이벤트를 등록할 수 없습니다. 시스템 기반 이벤트를 사용할 때는 이 제한이 없습니다. 예를 들어, 다음은 플레이어가 E와 F를 모두 눌러 상호작용할 수 있으며 각각 다른 기능을 트리거하는 엔티티입니다.

```ts
    engine.addSystem(() => {
        if (inputSystem.isTriggered(InputAction.IA_PRIMARY, PointerEventType.PET_DOWN, myEntity)) {
            // E에 반응
        }
        if (inputSystem.isTriggered(InputAction.IA_SECONDARY, PointerEventType.PET_DOWN, myEntity)) {
            // F에 반응
        }
    })
```

## 피드백 표시

엔티티를 가리키는 동안 UI 힌트를 표시하려면 엔티티의 다음 속성을 사용하세요 `PointerEvents` 컴포넌트를 추가해야 합니다.

```ts
// 엔티티 생성
const myEntity = engine.addEntity()

// 엔티티에 PointerEvents 컴포넌트 부여
PointerEvents.create(myEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
			},
		},
	],
})
```

플레이어의 커서가 이 엔티티의 콜라이더를 가리킬 때마다 UI는 엔티티와 상호작용할 수 있음을 나타내는 호버 힌트를 표시합니다. 구성할 수 있는 항목에 대한 자세한 내용은 아래 섹션을 참조하세요.

{% hint style="warning" %}
**📔 참고**: `PointerEvents` 컴포넌트는 호버 피드백 표시만 처리합니다. 사용자 지정 로직으로 버튼 이벤트 자체를 처리하려면 다음을 참조하세요 [시스템 사용하기](#check-for-events).
{% endhint %}

이 `PointerEvents` 컴포넌트에는 포인터 이벤트 정의가 하나 이상 필요합니다. 각 포인터 이벤트 정의는 다음과 같이 구성할 수 있습니다:

* `eventType`: 수신할 이벤트 유형으로, 다음의 값입니다 `PointerEventType` 열거형의 값을 사용합니다. 다음을 참조하세요 [포인터 이벤트의 종류](/creator/content-creator-ko/sdk7/interactivity/button-events/click-events.md#types-of-pointer-events) 에서 지원되는 옵션을 확인하세요.
* `eventInfo`: 다음 필드를 포함할 수 있는 객체입니다:
  * `button` (*필수*): 수신할 입력으로, 다음의 값입니다 `InputAction` 열거형의 값을 사용합니다. 다음을 참조하세요 [포인터 버튼](/creator/content-creator-ko/sdk7/interactivity/button-events/click-events.md#pointer-buttons) 에서 지원되는 옵션을 확인하세요.
  * `hoverText` *(선택 사항)*: 호버 피드백 힌트에 표시할 문자열입니다. 기본값은 "Interact"입니다.
  * `showFeedback` *(선택 사항)*: false이면 이 엔티티의 호버 힌트와 가장자리 하이라이트를 모두 숨깁니다. *true* 내보냅니다.
  * `showHighlight` *(선택 사항)*: true이면 플레이어가 커서를 엔티티 위에 올렸을 때 가장자리 하이라이트를 보게 됩니다. *true* 기본값입니다. 이 값은 다음 경우에만 고려됩니다: `showFeedback` 가 *true*.
  * `maxDistance` *(선택 사항)*: 플레이어의 **아바타** 가 엔티티에서 얼마나 멀리 떨어져 있어도 상호작용할 수 있는지(미터)입니다. 기본값은 *10미터*. 참고: [최대 거리](#max-distance).
  * `maxCameraDistance` *(선택 사항)*: 다음이 엔티티에서 얼마나 멀리 떨어져 있어도 상호작용할 수 있는지(미터)입니다. 기본적으로 설정되지 않습니다. 다음을 참조하세요 **활성 카메라** 가 [최대 거리](#max-distance).
  * `priority` *(선택 사항)*: 여러 엔티티가 겹칠 때 어떤 엔티티가 우선하는지입니다. 값이 높을수록 우선합니다. *0* 내보냅니다.

단일 `PointerEvents` 컴포넌트는 서로 다른 버튼에 대해 서로 다른 이벤트를 감지할 수 있는 여러 포인터 이벤트 정의를 보유할 수 있습니다. 각 엔티티는 하나의 *하나만* `PointerEvents` 컴포넌트만 가질 수 있지만, 이 컴포넌트는 다음에 여러 객체를 포함할 수 있습니다 `pointerEvents` 배열에 반응할 각 이벤트마다 하나씩 포함됩니다.

```ts
PointerEvents.create(NPCEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: '인사하기',
			},
		},
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_PRIMARY,
				hoverText: '목 조르기',
			},
		},
		{
			eventType: PointerEventType.PET_UP,
			eventInfo: {
				button: InputAction.IA_PRIMARY,
				hoverText: '목 조르기 중지',
			},
		},
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_SECONDARY,
				hoverText: '보석 주기',
			},
		},
	],
})
```

플레이어는 각 포인터 이벤트마다 하나씩, 커서 주변에 방사형으로 표시되는 여러 레이블을 보게 됩니다.

아래 예제는 다음을 사용하는 것을 결합합니다 `PointerEvents` 를 사용해 호버 힌트를 표시하고, 플레이어의 작업을 실제로 사용자 지정 로직으로 처리하는 시스템과 함께 사용합니다.

```ts
// 엔티티 생성
const myEntity = engine.addEntity()

// 엔티티에 호버 피드백 제공
PointerEvents.create(myEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: '열기',
			},
		},
	],
})

// 엔티티의 클릭 이벤트 처리
engine.addSystem(() => {
	if (
		inputSystem.isTriggered(
			InputAction.IA_POINTER,
			PointerEventType.PET_DOWN,
			myEntity
		)
	) {
		// 입력 작업에 반응하는 사용자 지정 로직
	}
})
```

### 호버 피드백

플레이어가 다음이 있는 아이템 위에 커서를 올리면 `PointerEvents` 컴포넌트가 있으면 다음을 보게 됩니다:

* 엔티티의 가장자리 하이라이트
* 커서 근처에, 눌러야 하는 버튼 아이콘과 "상호작용"이라는 문자열이 있는 호버 힌트

이 요소들은 켜고 끄거나 사용자 지정할 수 있습니다.

UI의 호버 피드백은 다음에서 선택한 입력에 따라 다른 아이콘을 표시합니다. `button` 필드입니다. PC에서는 다음 아이콘이 표시됩니다: `E` 에 대해 `InputAction.IA_PRIMARY`, 그리고 `F` 에 대해 `InputAction.IA_SECONDARY`, 그리고 마우스 아이콘은 `InputAction.IA_POINTER`.

문자열은 다음 값을 변경하여 바꾸세요 `hoverText` . 이 문자열은 짧게 유지하세요. 읽기 쉽고 화면에서 너무 거슬리지 않게 하기 위해서입니다.

```ts
// 엔티티 생성
const chest = engine.addEntity()

// 엔티티에 PointerEvents 컴포넌트 부여
PointerEvents.create(chest, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: '열기',
			},
		},
	],
})
```

위 예제에서 포인터 이벤트에는 다음의 값이 포함되어 있습니다 `hoverText`. 이 필드는 플레이어가 엔티티를 가리키는 동안 UI에 표시할 문자열을 정의합니다. 기본적으로 이 문자열은 다음과 같이 표시됩니다 *상호작용*.

{% hint style="info" %}
**💡 팁**: `hoverText` 문자열은 상호작용 시 발생하는 작업을 설명해야 합니다. 예를 들면 `열기`, `활성화`, `잡기`, `선택하세요`. 플레이어의 주의를 너무 많이 빼앗지 않도록 이 문자열은 가능한 한 짧아야 합니다.
{% endhint %}

엔티티에 여러 포인터 이벤트가 있으면 각각의 호버 힌트가 커서 주변에 방사형으로 표시됩니다.

이 `hoverText` 다음의 `.UP` 포인터 이벤트는 플레이어가 이미 해당 키를 누른 채 엔티티를 가리키는 동안에만 표시됩니다.

엔티티에 `DOWN` 포인터 이벤트 및 `UP` 포인터 이벤트가 있는 경우, 다음에 대한 힌트는 `DOWN` 작업은 버튼을 누르지 않은 동안 표시됩니다. 버튼을 누르고 계속 누른 상태일 때만 힌트가 다음의 힌트로 전환됩니다 `UP` 이벤트입니다.

```ts
// 엔티티 생성
const entity = engine.addEntity()

// 엔티티에 PointerEvents 컴포넌트 부여
PointerEvents.create(entity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: '드래그',
			},
		},
		{
			eventType: PointerEventType.PET_UP,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: '놓기',
			},
		},
	],
})
```

호버 힌트를 숨기되 가장자리 하이라이트는 남기려면, 다음의 값을 `hoverText` ""로 설정하세요.

```ts
// 엔티티 생성
const chest = engine.addEntity()

// 엔티티에 PointerEvents 컴포넌트 부여
PointerEvents.create(chest, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: '',
			},
		},
	],
})
```

가장자리 하이라이트를 숨기되 호버 힌트는 남기려면, 다음을 설정하세요. `showHighlight` 를 *false*.

```ts
// 엔티티 생성
const chest = engine.addEntity()

// 엔티티에 PointerEvents 컴포넌트 부여
PointerEvents.create(chest, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				hoverText: '문 열기',
				showHighlight: false,
			},
		},
	],
})
```

호버 힌트와 가장자리 하이라이트를 모두 숨기려면, 다음을 설정하세요. `showFeedback` 를 *false*. 이렇게 하면 커서에 아이콘, 텍스트 또는 가장자리 강조 표시가 나타나지 않습니다. 엔티티에서 다음을 제거할 수도 있습니다 `PointerEvents` 컴포넌트.

```ts
// 엔티티 생성
const chest = engine.addEntity()

// 엔티티에 PointerEvents 컴포넌트 부여
PointerEvents.create(chest, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				showFeedback: false,
			},
		},
	],
})
```

### 최대 거리

일부 엔티티는 의도적으로 가까운 거리에서만 상호작용 가능할 수 있습니다. 플레이어가 엔티티에서 너무 멀리 떨어져 있으면 커서 옆에 호버 힌트가 표시되지 않습니다.

기본적으로 엔티티는 플레이어의 **아바타** 가 다음 범위 내에 있을 때만 클릭할 수 있습니다 *10미터* 엔티티의. 다음을 설정하여 해당 범위를 변경할 수 있습니다 `maxDistance` 포인터 이벤트의 속성.

```ts
// 엔티티 생성
const myEntity = engine.addEntity()

// 엔티티에 PointerEvents 컴포넌트 부여
PointerEvents.create(myEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_POINTER,
				maxDistance: 6,
			},
		},
	],
})

// 포인터 이벤트를 처리할 시스템 구현
engine.addSystem(() => {
	// 포인터 이벤트에 관한 데이터 가져오기
	const cmd = inputSystem.getInputCommand(
		InputAction.IA_POINTER,
		PointerEventType.PET_DOWN,
		myEntity
	)

	// 클릭이 충분히 가까운지 확인
	if (cmd && cmd.hit && cmd.hit.length < 6) {
		// 무언가를 수행
	}
})
```

위 예제는 호버 힌트의 최대 거리를 *6미터*. 입력 작업을 처리하는 로직도 동일한 규칙을 따르도록 하세요. 다음을 참조하세요 [입력 액션의 데이터](#data-from-input-action) 에서 입력 작업의 거리를 얻는 방법을 확인하세요.

`maxDistance` 는 플레이어의 다음으로부터 측정됩니다 **아바타**, 따라서 1인칭과 3인칭에서 동일하게 동작합니다.

다음이 얼마나 멀리 떨어져 있는지로 상호작용을 제한하려면 **활성 카메라** 대신 다음을 사용하세요 `maxCameraDistance`. 둘 다 설정하면 둘 중 하나의 검사를 통과하는 것으로 충분합니다. 다음을 참조하세요 [거리 제한](/creator/content-creator-ko/sdk7/interactivity/button-events/register-callback.md#distance-limits) 에서 전체 규칙 세트를 확인하세요.

{% hint style="warning" %}
**📔 참고**: `maxPlayerDistance` 의 더 이상 사용되지 않는 별칭입니다 `maxDistance`. 둘 다 아바타로부터의 거리를 측정하므로 다음을 사용하세요 `maxDistance` 를 사용하세요.
{% endhint %}

## 고급 사용자 지정 힌트

이 `PointerEvents` 컴포넌트는 플레이어의 커서가 엔티티 위로 호버하기 시작할 때 UI 힌트를 쉽게 추가합니다. 일반적으로 힌트가 다른 Decentraland 씬에서 플레이어가 익숙하게 보아 온 방식과 일관되게 동작하는 것이 좋습니다. 하지만 어떤 경우에는 무언가가 상호작용 가능하다는 것을 사용자 지정 방식으로 알리고 싶을 수 있습니다. 예를 들어, 플레이어가 엔티티 위로 호버하기 시작할 때 미묘한 소리를 재생할 수 있습니다. 호버하는 동안 엔티티 주변에 빛나는 강조 표시를 보여 주고, 더 이상 호버하지 않으면 숨길 수도 있습니다. 특정 게임플레이 메커니즘에 사용할 수도 있습니다.

다음을 사용하세요 `inputSystem.isTriggered()` 함수를 다음과 함께 사용합니다 `PointerEventType.PET_HOVER_ENTER` 과 `PointerEventType.PET_HOVER_LEAVE` 이벤트를 사용하여 플레이어의 커서가 엔티티의 콜라이더를 가리키기 시작할 때와 커서가 더 이상 이를 가리키지 않을 때마다 사용자 지정 동작을 수행합니다.

아래 예제는 엔티티의 크기를 다음으로 확대합니다 *1.5* 커서가 해당 콜라이더를 가리키기 시작할 때, 그리고 크기를 다음으로 되돌립니다 *1* 커서가 엔티티를 벗어날 때.

```ts
engine.addSystem(() => {
	const meshEntities = engine.getEntitiesWith(MeshRenderer)
	for (const [entity] of meshEntities) {
		if (
			inputSystem.isTriggered(
				InputAction.IA_POINTER,
				PointerEventType.PET_HOVER_ENTER,
				엔티티
			)
		) {
			Transform.getMutable(entity).scale = Vector3.create(1.5, 1.5, 1.5)
		}

		if (
			inputSystem.isTriggered(
				InputAction.IA_POINTER,
				PointerEventType.PET_HOVER_LEAVE,
				엔티티
			)
		) {
			Transform.getMutable(entity).scale = Vector3.create(1, 1, 1)
		}
	}
})
```

{% hint style="warning" %}
**📔 참고**: 상호작용하려는 모든 엔티티에는 둘 다 다음이 있어야 합니다 [`PointerEvents` 컴포넌트](#show-feedback) 와 하나의 [collider](/creator/content-creator-ko/sdk7/3d/colliders.md).
{% endhint %}

## 근접 이벤트

다음을 사용하여 커서가 어디를 가리키는지와 관계없이 근접 버튼 누름을 확인합니다 `PET_DOWN` 다음을 사용하는 엔티티에서 `InteractionType.PROXIMITY`. 다음을 설정합니다 `interactionType` 필드를 포인터 이벤트 정의에서 다음 옆에 설정합니다 `eventInfo`, 이벤트를 근접 기반으로 표시합니다.

다음 [**근접 이벤트**](/creator/content-creator-ko/sdk7/interactivity/button-events/proximity-events.md) 에서 사용 가능한 헬퍼 함수를 포함한 자세한 내용을 확인하세요.

```ts
PointerEvents.create(myEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_DOWN,
			eventInfo: {
				button: InputAction.IA_PRIMARY,
				hoverText: 'E 누르기',
				maxDistance: 5
			},
			interactionType: InteractionType.PROXIMITY,
		},
	],
})

engine.addSystem(() => {
	if (inputSystem.isTriggered(InputAction.IA_PRIMARY, PointerEventType.PET_DOWN, myEntity)) {
		console.log('플레이어가 엔티티 근처에서 버튼을 눌렀습니다')
	}
})
```

다음과 같은 헬퍼를 사용하면 `pointerEventsSystem.onProximityDown`, 엔티티는 커서 핸들러 하나와 근접 핸들러 하나를 동시에 보유할 수 있고 두 콜백이 모두 실행됩니다. 하지만 동일한 핸들러에 서로 다른 두 버튼을 등록할 수는 없습니다. 시스템 기반 이벤트에는 이 두 제한 모두 없습니다. 동작마다 하나의 항목을 정의합니다. 예를 들어, 다음은 커서로 가리키며 E를 눌러 상호작용하거나, 커서로 가리키지 않고 그 근처로 걸어가 E를 눌러 상호작용할 수 있는 엔티티입니다.

```ts
	PointerEvents.create(myEntity, {
        pointerEvents: [
            {
                eventType: PointerEventType.PET_DOWN,
                eventInfo: {
                    button: InputAction.IA_POINTER,
                    hoverText: 'Click',
                    maxDistance: 15,
                },
                interactionType: InteractionType.CURSOR,
            },
            {
                eventType: PointerEventType.PET_DOWN,
                eventInfo: {
                    button: InputAction.IA_PRIMARY,
                    hoverText: 'E 누르기',
                    maxDistance: 15,
                },
                interactionType: InteractionType.PROXIMITY,
            },
        ],
    })
    
    engine.addSystem(() => {
        if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_DOWN, myEntity)) {
            console.log('플레이어가 엔티티를 클릭했습니다')
        }
        if (inputSystem.isTriggered(InputAction.IA_PRIMARY, PointerEventType.PET_DOWN, myEntity)) {
            console.log('플레이어가 엔티티 근처에서 버튼을 눌렀습니다')
        }
    })
```

다음을 사용해서도 `inputSystem.isTriggered()` 의 `PET_PROXIMITY_ENTER` 과 `PET_PROXIMITY_LEAVE` 이벤트 유형을 사용하여 플레이어가 엔티티의 근접 범위에 들어오거나 나갈 때 반응합니다. 이는 근접 활성화 엔티티에 추가 피드백을 표시하는 데 유용합니다. 예를 들어 소리나 애니메이션을 재생할 수 있습니다.

이 기능이 작동하려면 엔티티에 다음이 있어야 합니다 `PointerEvents` 컴포넌트에 해당 근접 이벤트 유형이 정의되어 있어야 합니다.

```ts
PointerEvents.create(myEntity, {
	pointerEvents: [
		{
			eventType: PointerEventType.PET_PROXIMITY_ENTER,
			eventInfo: {
				button: InputAction.IA_POINTER,
				maxDistance: 5,
			},
		},
		{
			eventType: PointerEventType.PET_PROXIMITY_LEAVE,
			eventInfo: {
				button: InputAction.IA_POINTER,
				maxDistance: 5,
				showFeedback: false,
			},
		},
	],
})

engine.addSystem(() => {
	if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_PROXIMITY_ENTER, myEntity)) {
		console.log('플레이어가 근접 범위에 들어왔습니다')
	}
	if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_PROXIMITY_LEAVE, myEntity)) {
		console.log('플레이어가 근접 범위를 벗어났습니다')
	}
})
```

## 입력 액션의 데이터

눌린 버튼, 맞은 엔티티, 레이의 방향과 길이 등 입력 액션에서 데이터를 가져옵니다. 다음을 참조하세요 ([문서 보기](https://github.com/decentraland/docs/tree/main/README.md))에서 사용 가능한 모든 데이터에 대한 설명을 확인하세요.

이 데이터를 가져오려면 다음을 사용하세요 `inputSystem.getInputCommand`. 이 함수는 입력 이벤트에 관한 데이터가 포함된 전체 데이터 구조를 반환합니다.

```ts
engine.addSystem(() => {
	const cmd = inputSystem.getInputCommand(
		InputAction.IA_POINTER,
		PointerEventType.PET_DOWN,
		myEntity
	)
	if (cmd) {
		console.log(cmd.hit?.entityId)
	}
})
```

쿼리와 일치하는 입력 작업이 없었다면 다음은 `inputSystem.getInputCommand` 반환합니다 *null*. 로직에서 이 시나리오를 처리해야 합니다.

### 최대 클릭 거리

최대 거리를 적용하여 엔티티를 가까운 거리에서만 클릭할 수 있게 하려면 다음을 가져오세요 `hit.length` 이벤트 데이터의 속성.

```ts
// 포인터 이벤트를 처리할 시스템 구현
engine.addSystem(() => {
	// 포인터 이벤트에 관한 데이터 가져오기
	const cmd = inputSystem.getInputCommand(
		InputAction.IA_POINTER,
		PointerEventType.PET_DOWN,
		myEntity
	)

	// 클릭이 충분히 가까운지 확인
	if (cmd && cmd.hit && cmd.hit.length < 6) {
		// 무언가를 수행
	}
})
```

{% hint style="warning" %}
**📔 참고**: 멀리 떨어진 이벤트를 무시한다면 다음을 반드시 설정하세요 `maxDistance` 매개변수를 다음에서 `PointerEvents` 컴포넌트가 일관되게 동작하도록 합니다.
{% endhint %}

### 모델 내부의 서로 다른 메시

흔히, *.glTF* 3D 모델은 각각 개별 내부 이름을 가진 여러 메시로 구성됩니다. 모든 버튼 이벤트에는 클릭된 특정 메시 정보가 포함되므로, 이 정보를 사용해 경우마다 다른 클릭 동작을 트리거할 수 있습니다.

모델 내부 메시의 이름을 확인하려면 다음과 같은 편집 도구로 3D 모델을 열어야 합니다 [Blender](https://www.blender.org/) 를 예로 들 수 있습니다.

![](https://3980763956-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-c0c8238fe31b8eb541ccb25d29459670a994f03e%2Fmesh-names%20\(1\).png?alt=media)

{% hint style="info" %}
**💡 팁**: 클릭된 메시의 이름을 로그에 기록하고 콘솔에서 확인할 수도 있습니다.
{% endhint %}

다음에 접근합니다 `meshName` 속성을 다음의 일부로 `히트` 객체이며, 클릭 이벤트가 반환합니다.

아래 예제에는 이름이 다음인 메시를 포함하는 집 모델이 있습니다 `firePlace`. 해당 메시가 클릭되었을 때만 벽난로를 켜려고 합니다.

```ts
engine.addSystem(() => {
	const cmd = inputSystem.getInputCommand(
		InputAction.IA_POINTER,
		PointerEventType.PET_DOWN,
		myEntity
	)
	if (cmd && cmd.hit?.meshName === 'firePlace') {
		// 불 켜기
	}
})
```

{% hint style="warning" %}
**📔 참고**: 이는 포인터 기반 이벤트에만 적용되며 근접 기반 이벤트에는 적용되지 않습니다. 근접 기반 이벤트의 경우 모델의 모든 메시가 동시에 플레이어 가까이에 있을 수 있기 때문입니다.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.decentraland.org/creator/content-creator-ko/sdk7/interactivity/button-events/system-based-events.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
