[task] | code [pass] | ⏳ 미판정 [title] | 엔티티와 컴포넌트 참조 [question] | 내 플레이어 엔티티의 RigidbodyComponent를 참조하여 nil 여부를 확인하고 로그를 출력하는 스크립트를 작성해줘 [answer] | 내 플레이어 엔티티의 `RigidbodyComponent`를 참조하고 nil 여부를 확인하는 스크립트는 다음과 같습니다. ```lua [client only] void OnBeginPlay() { local myPlayerEntity = _UserService.LocalPlayer -- 내 플레이어 엔티티의 컴포넌트를 변수 rigidbody에 참조 local rigidbody = myPlayerEntity.RigidbodyComponent if rigidbody == nil then [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 컴포넌트는 엔티티를 작동시키는 구성품입니다. 그러므로 반드시 엔티티를 통해 컴포넌트로 접근해야 합니다. 일반적으로 **Entity.컴포넌트 명** 형태로 컴포넌트에 접근할 수 있습니다. 네이티브 컴포넌트는 스크립트 에디터에서 컴포넌트 명이 자동 완성됩니다. 다음은 내 플레이어 엔티티의 **RigidbodyComponent**에 접근하는 예시 코드입니다. ```lua [client only] void OnBeginPlay() { local myPlayerEntity = _UserService.LocalPlayer
[task] | code [pass] | ⏳ 미판정 [title] | 엔티티와 컴포넌트 참조 [question] | UserService와 Entity의 RigidbodyComponent를 사용해야 하며, OnBeginPlay에서 _UserService.LocalPlayer를 통해 엔티티를 가져와 컴포넌트 접근 예시를 구현해야 합니다. [answer] | `OnBeginPlay`에서 `_UserService.LocalPlayer`를 통해 내 플레이어 엔티티를 가져와 `RigidbodyComponent`에 접근하는 예시입니다. ```lua [client only] void OnBeginPlay() { local myPlayerEntity = _UserService.LocalPlayer -- 내 플레이어 엔티티의 RigidbodyComponent를 변수에 참조 local rigidbody = myPlayerEntity.RigidbodyComponent i [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 컴포넌트는 엔티티를 작동시키는 구성품입니다. 그러므로 반드시 엔티티를 통해 컴포넌트로 접근해야 합니다. 일반적으로 **Entity.컴포넌트 명** 형태로 컴포넌트에 접근할 수 있습니다. 네이티브 컴포넌트는 스크립트 에디터에서 컴포넌트 명이 자동 완성됩니다. 다음은 내 플레이어 엔티티의 **RigidbodyComponent**에 접근하는 예시 코드입니다. ```lua [client only] void OnBeginPlay() { local myPlayerEntity = _UserService.LocalPlayer
[task] | code [pass] | ⏳ 미판정 [title] | 엔티티의 충돌 [question] | TriggerComponent의 OnLeaveTriggerBody를 오버라이딩하여 엔티티가 트리거 영역에서 벗어날 때 로그를 출력하고 해당 상대 엔티티를 제거하는 스크립트를 작성해줘. [answer] | `TriggerComponent`의 `OnLeaveTriggerBody` 함수를 오버라이딩하여 요청하신 동작을 수행하는 스크립트는 다음과 같습니다. ```lua Method: [server only] void OnLeaveTriggerBody(TriggerBodyEvent event) { local TriggerBodyEntity = event.TriggerBodyEntity -- 로그 출력 log(TriggerBodyEntity.Name .. " is leaving the trigger area." [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 다른 스크립트 컴포넌트와는 달리, 확장된 **TriggerComponent**에는 몇 가지 함수를 오버라이딩할 수 있습니다. 이 함수들은 충돌 이벤트가 발생할 때 호출되는 것입니다. 이 함수를 추가하면 해당 함수의 정의부를 편집하여 오버라이딩할 수 있습니다. 오버라이딩할 수 있는 함수는 총 세 가지입니다. 다음은 함수별 호출 시점입니다. * **OnEnterTriggerBody** :엔티티 간 충돌이 처음 발생했을 때 1회 호출됩니다. * **OnStayTriggerBody**: 엔티티 간 충돌이 발생한 뒤, 두 엔티티가 겹쳐
[task] | code [pass] | ⏳ 미판정 [title] | 엔티티의 충돌 [question] | TriggerComponent의 OnEnterTriggerBody와 OnLeaveTriggerBody를 오버라이딩하여 충돌 시작과 종료 시점에 각각 다른 로그 메시지를 출력하는 스크립트를 작성해줘. [answer] | `TriggerComponent`의 `OnEnterTriggerBody`와 `OnLeaveTriggerBody` 함수는 확장된 컴포넌트에서 오버라이딩할 수 있는 네이티브 함수입니다. 이 함수들은 각각 충돌이 처음 발생했을 때와 충돌이 종료될 때 1회씩 호출됩니다. 참고 문서에 따르면, 충돌 이벤트 발생 시 매개 변수로 **상대 엔티티 정보**가 들어오며, 실제 예제 코드에서 볼 수 있듯이 이벤트 객체의 `TriggerBodyEntity` 프로퍼티를 통해 충돌한 상대 엔티티에 접근할 수 있습니다. 요청하신 대로 충돌 시작과 종료 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 다른 스크립트 컴포넌트와는 달리, 확장된 **TriggerComponent**에는 몇 가지 함수를 오버라이딩할 수 있습니다. 이 함수들은 충돌 이벤트가 발생할 때 호출되는 것입니다. 이 함수를 추가하면 해당 함수의 정의부를 편집하여 오버라이딩할 수 있습니다. 오버라이딩할 수 있는 함수는 총 세 가지입니다. 다음은 함수별 호출 시점입니다. * **OnEnterTriggerBody** :엔티티 간 충돌이 처음 발생했을 때 1회 호출됩니다. * **OnStayTriggerBody**: 엔티티 간 충돌이 발생한 뒤, 두 엔티티가 겹쳐
[task] | code [pass] | ⏳ 미판정 [title] | 엔티티와 컴포넌트 참조 [question] | 내 플레이어 엔티티에 부착된 CharacterStatus 스크립트 컴포넌트를 참조하여 nil 체크 후 로그를 출력하는 스크립트를 작성해줘 [answer] | 내 플레이어 엔티티에 부착된 `CharacterStatus` 스크립트 컴포넌트를 참조하고, 해당 컴포넌트가 존재하지 않는지(nil)를 확인한 후 로그를 출력하는 스크립트는 다음과 같습니다. ```lua [client only] void OnBeginPlay() { local myPlayerEntity = _UserService.LocalPlayer -- 내 플레이어 엔티티의 스크립트 컴포넌트를 변수 status에 참조 local status = myPlayerEntity.CharacterStatus [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 컴포넌트는 엔티티를 작동시키는 구성품입니다. 그러므로 반드시 엔티티를 통해 컴포넌트로 접근해야 합니다. 일반적으로 **Entity.컴포넌트 명** 형태로 컴포넌트에 접근할 수 있습니다. 네이티브 컴포넌트는 스크립트 에디터에서 컴포넌트 명이 자동 완성됩니다. 다음은 내 플레이어 엔티티의 **RigidbodyComponent**에 접근하는 예시 코드입니다. ```lua [client only] void OnBeginPlay() { local myPlayerEntity = _UserService.LocalPlayer
[task] | code [pass] | ⏳ 미판정 [title] | 엔티티와 컴포넌트 참조 [question] | Entity와 GetChildComponentsByTypeName 메서드를 사용해야 하며, OnBeginPlay에서 self.Entity.CurrentMap을 통해 맵 엔티티를 가져와 두 번째 매개변수를 생략(기본값 false)하여 호출해야 합니다. [answer] | 요구하신 조건에 따라 `OnBeginPlay`에서 `self.Entity.CurrentMap`을 통해 맵 엔티티를 가져오고, `GetChildComponentsByTypeName` 메서드를 두 번째 매개변수를 생략한 상태로 호출하는 스크립트입니다. ```lua void OnBeginPlay() { local map01Entity = self.Entity.CurrentMap local ComponentsArr = map01Entity:GetChildComponentsByTypeName("ComponentA") [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 컴포넌트는 엔티티를 작동시키는 구성품입니다. 그러므로 반드시 엔티티를 통해 컴포넌트로 접근해야 합니다. 일반적으로 **Entity.컴포넌트 명** 형태로 컴포넌트에 접근할 수 있습니다. 네이티브 컴포넌트는 스크립트 에디터에서 컴포넌트 명이 자동 완성됩니다. 다음은 내 플레이어 엔티티의 **RigidbodyComponent**에 접근하는 예시 코드입니다. ```lua [client only] void OnBeginPlay() { local myPlayerEntity = _UserService.LocalPlayer
[task] | two_turn [pass] | ⏳ 미판정 [title] | 엔티티의 충돌 [question] | 확장된 TriggerComponent에서 오버라이딩할 수 있는 충돌 이벤트 함수는 무엇이며 각각 언제 호출되나요? [answer] | 확장된 TriggerComponent에서 오버라이딩할 수 있는 충돌 이벤트 함수는 총 3가지입니다. 각 함수의 호출 시점은 다음과 같습니다. 1. **OnEnterTriggerBody**: 두 엔티티 간의 충돌이 **처음 발생했을 때 1회** 호출됩니다. 2. **OnStayTriggerBody**: 충돌이 발생한 뒤, 두 엔티티가 **겹쳐있는 동안 프레임마다** 호출됩니다. 3. **OnLeaveTriggerBody**: 두 엔티티 간의 충돌이 **종료될 때 1회** 호출됩니다. 이 함수들은 충돌 이벤트가 발생할 때 호출되며, [followup] | OnEnterTriggerBody, OnStayTriggerBody, OnLeaveTriggerBody 함수의 매개 변수로 들어오는 충돌 이벤트 객체에서 상대 엔티티 정보를 추출하는 mLua 코드 예시를 보여주세요. [followup_answer] | 참고 문서에 따르면, 충돌 이벤트 함수의 매개 변수로 들어오는 충돌 이벤트 객체에는 "엔티티와 충돌한 상대 엔티티 정보"가 포함되어 있다고 명시되어 있습니다. 그러나 참고 문서에는 해당 이벤트 객체에서 상대 엔티티를 추출하는 **구체적인 프로퍼티 이름(예: `event.OtherEntity`, `event.TriggerBodyEntity` 등)이 명시되어 있지 않습니다.** 문서에는 `HandleTriggerEnterEvent`와 같은 다른 이벤트 핸들러에서 `event.TriggerBodyEntity`를 사용하는 예제가 제시되 [scores] | [judge_reason] | [source_doc] | 다른 스크립트 컴포넌트와는 달리, 확장된 **TriggerComponent**에는 몇 가지 함수를 오버라이딩할 수 있습니다. 이 함수들은 충돌 이벤트가 발생할 때 호출되는 것입니다. 이 함수를 추가하면 해당 함수의 정의부를 편집하여 오버라이딩할 수 있습니다. 오버라이딩할 수 있는 함수는 총 세 가지입니다. 다음은 함수별 호출 시점입니다. * **OnEnterTriggerBody** :엔티티 간 충돌이 처음 발생했을 때 1회 호출됩니다. * **OnStayTriggerBody**: 엔티티 간 충돌이 발생한 뒤, 두 엔티티가 겹쳐
[task] | code [pass] | ⏳ 미판정 [title] | 엔티티와 컴포넌트 참조 [question] | 현재 맵 엔티티의 직접 하위 엔티티에만 존재하는 ComponentA 컴포넌트 배열을 반환받아 로그를 출력하는 스크립트를 작성해줘 [answer] | 현재 맵 엔티티의 **직접 하위 엔티티**에서만 `ComponentA`를 찾으려면 `Entity:GetChildComponentsByTypeName(string typename, bool recursive)` 메서드를 사용하며, `recursive` 매개 변수를 `false`로 설정해야 합니다. ```lua [client only] void OnBeginPlay() { local map01Entity = self.Entity.CurrentMap -- recursive를 false로 설정하여 직접 하위 엔티티 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 컴포넌트는 엔티티를 작동시키는 구성품입니다. 그러므로 반드시 엔티티를 통해 컴포넌트로 접근해야 합니다. 일반적으로 **Entity.컴포넌트 명** 형태로 컴포넌트에 접근할 수 있습니다. 네이티브 컴포넌트는 스크립트 에디터에서 컴포넌트 명이 자동 완성됩니다. 다음은 내 플레이어 엔티티의 **RigidbodyComponent**에 접근하는 예시 코드입니다. ```lua [client only] void OnBeginPlay() { local myPlayerEntity = _UserService.LocalPlayer
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 엔티티를 탐색하는 EntityService [question] | GetEntityByPath()와 GetEntitiesByPath()의 반환 타입 및 사용 시나리오를 비교하여 3문장 이내로 설명하세요. [answer] | `GetEntityByPath()`는 월드 경로가 일치하는 단일 엔티티를 반환하며, 경로가 유니크한 특정 객체를 탐색할 때 사용합니다. 반면 `GetEntitiesByPath()`는 해당 경로와 일치하는 모든 엔티티의 배열을 반환하여, 동일한 이름의 엔티티가 여러 개 생성된 경우를 한 번에 처리할 때 적합합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 월드를 제작하다 보면 특정 엔티티를 탐색하여 받아오거나, 혹은 관련 있는 여러 엔티티를 한 번에 받아야 하는 상황이 자주 발생합니다. 이럴 때 [**EntityService**](/apiReference/Services/EntityService)를 활용할 수 있습니다. **EntityService**는 엔티티 탐색, 삭제, 유효성 체크 등의 기능을 제공하고 있습니다. 이번 과정에서는 **EntityService**에서 제공하는 기능의 사용법을 하나씩 알아보도록 하겠습니다. **테스트 환경** **common
[task] | single_turn [pass] | ⏳ 미판정 [title] | 엔티티의 충돌 [question] | 스크립트 컴포넌트의 Event Handler에서 Trigger 검색으로 핸들러를 추가한 후, 특정 엔티티 A와 B의 충돌만 감지하려면 센더 설정을 어떻게 해야 하는지 궁금합니다. [answer] | 센더 설정은 **핸들러가 들어 있는 스크립트 컴포넌트가 부착된 엔티티**를 기준으로 합니다. 1. **자기 자신(self)의 충돌을 감지하는 경우:** * 스크립트 컴포넌트를 엔티티 A에 부착한 상태에서, 엔티티 A의 충돌 이벤트를 받고 싶다면 핸들러 상단의 센더를 **self**로 설정합니다. * 이 경우 엔티티 A의 `TriggerComponent`에 충돌이 발생하면 핸들러가 호출됩니다. 2. **다른 엔티티(entity)의 충돌을 감지하는 경우:** * 스크립트 컴포넌트를 엔티티 A에 부 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 충돌 이벤트 이후 액션은 **Entity Event System**을 활용하거나, **확장된 TriggerComponent** 활용합니다. 월드에 **TriggerComponent**를 포함하는 A와 B, 두 엔티티가 있다고 가정해 봅시다. A와 B가 부딪히면 충돌 이벤트가 발생합니다. 그러나 이후 특별한 변화가 일어나지 않을 것입니다. 충돌 이벤트 발생을 한 뒤 일어날 추가 액션이 없기 때문입니다. **TriggerComponent**를 활용하면 충돌 이벤트가 발생할 때 일어날 액션을 추가할 수 있습니다. 예를 들어 A와 B가 충
[task] | code [pass] | ⏳ 미판정 [title] | 엔티티와 컴포넌트 참조 [question] | UserService와 Entity의 CharacterStatus 컴포넌트를 사용해야 하며, OnBeginPlay에서 _UserService.LocalPlayer를 통해 엔티티를 가져와 직접 제작한 스크립트 컴포넌트 접근 예시를 구현해야 합니다. [answer] | 사용자가 요청한 조건에 따라 `OnBeginPlay` 생명주기 메서드 내에서 `_UserService.LocalPlayer`를 통해 내 플레이어 엔티티를 가져오고, 직접 제작한 `CharacterStatus` 스크립트 컴포넌트에 접근하는 코드를 작성합니다. mLua 스크립트 형식 규약에 따라 `Method:` 블록을 사용하여 `[client only]` 실행 공간으로 지정하며, 컴포넌트 접근 시 `Entity.컴포넌트 명` 형태(`myPlayerEntity.CharacterStatus`)를 따릅니다. 또한 컴포넌트가 존재하지 않을 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 컴포넌트는 엔티티를 작동시키는 구성품입니다. 그러므로 반드시 엔티티를 통해 컴포넌트로 접근해야 합니다. 일반적으로 **Entity.컴포넌트 명** 형태로 컴포넌트에 접근할 수 있습니다. 네이티브 컴포넌트는 스크립트 에디터에서 컴포넌트 명이 자동 완성됩니다. 다음은 내 플레이어 엔티티의 **RigidbodyComponent**에 접근하는 예시 코드입니다. ```lua [client only] void OnBeginPlay() { local myPlayerEntity = _UserService.LocalPlayer
[task] | instruction_following [pass] | ⏳ 미판정 [title] | Entity Event System [question] | TimeManager 스크립트에서 isSunrise 상태가 변경될 때 호출되는 메서드 이름과 해당 메서드 내부에서 생성되는 이벤트 객체 변수명을 2문장 이내로 답하세요. [answer] | 해당 메서드 이름은 `SendEvent`이며, 내부에서 생성되는 이벤트 객체 변수명은 `event`입니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 특정 시간마다 해가 뜨고 지는 로직을 만들어봅시다. 1. 해가 뜨고 지는 시간을 관리할 스크립트 컴포넌트가 필요합니다. **Workspace - MyDesk**의 콘텍스트 메뉴에서 **Create Scrips - Create Component**를 클릭해 새 컴포넌트를 만듭니다. 이름으로 **TimeManager**를 입력합니다. 2. **TimeManager** 스크립트 컴포넌트를 엽니다. `OnUpdate` 함수를 추가하여 해가 뜨고 지는 것을 판단하도록 합니다. ```lua Property: [Sy
[task] | single_turn [pass] | ⏳ 미판정 [title] | 엔티티의 충돌 [question] | 충돌 이벤트 핸들러의 매개 변수를 통해 충돌한 상대 엔티티 정보를 어떻게 가져와서 체력 감소 같은 액션을 적용할 수 있는지 코드 구조가 궁금합니다. [answer] | 충돌 이벤트 핸들러의 매개 변수로 전달되는 이벤트 객체를 통해 충돌한 상대 엔티티를 직접 참조할 수 있습니다. 이벤트 객체의 `TriggerBodyEntity` 프로퍼티에는 충돌한 상대 엔티티가 담겨 있으며, 이를 통해 상대 엔티티의 이름(`Name`)이나 ID(`Id`) 등을 확인하고 조건에 따라 액션을 실행할 수 있습니다. 체력 감소와 같은 액션을 적용하려면, 충돌한 상대 엔티티를 확인한 후 해당 엔티티의 `PlayerComponent`에 접근하여 `Hp` 값을 수정하면 됩니다. 서버 측에서 체력을 변경해야 하므로 스크립트 메 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 충돌 이벤트 이후 액션은 **Entity Event System**을 활용하거나, **확장된 TriggerComponent** 활용합니다. 월드에 **TriggerComponent**를 포함하는 A와 B, 두 엔티티가 있다고 가정해 봅시다. A와 B가 부딪히면 충돌 이벤트가 발생합니다. 그러나 이후 특별한 변화가 일어나지 않을 것입니다. 충돌 이벤트 발생을 한 뒤 일어날 추가 액션이 없기 때문입니다. **TriggerComponent**를 활용하면 충돌 이벤트가 발생할 때 일어날 액션을 추가할 수 있습니다. 예를 들어 A와 B가 충
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 엔티티를 탐색하는 EntityService [question] | GetEntityByPathExample() 코드 블록에 포함된 예제 코드를 그대로 출력하고, 각 라인별 동작을 주석으로만 설명하세요. [answer] | ```lua void GetEntityByPathExample() { -- "/maps/map01/npc-320_1" 경로를 가진 단일 엔티티를 탐색하여 변수 entity에 저장 local entity = _EntityService:GetEntityByPath("/maps/map01/npc-320_1") -- "/ui/DefaultGroup/Image_1" 경로를 가진 단일 엔티티를 탐색하여 변수 uiEntity에 저장 local uiEntity = _EntityService:GetEntityByPath [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 월드를 제작하다 보면 특정 엔티티를 탐색하여 받아오거나, 혹은 관련 있는 여러 엔티티를 한 번에 받아야 하는 상황이 자주 발생합니다. 이럴 때 [**EntityService**](/apiReference/Services/EntityService)를 활용할 수 있습니다. **EntityService**는 엔티티 탐색, 삭제, 유효성 체크 등의 기능을 제공하고 있습니다. 이번 과정에서는 **EntityService**에서 제공하는 기능의 사용법을 하나씩 알아보도록 하겠습니다. **테스트 환경** **common
[task] | two_turn [pass] | ⏳ 미판정 [title] | 함수 [question] | 동일 컴포넌트 내 메소드 호출 시 self 사용 규칙과, 다른 컴포넌트 또는 서비스 메소드 호출 시 참조 방식의 차이점을 설명해 주세요. [answer] | 메이플스토리 월드(mLua)에서 메소드 호출은 대상이 어디에 속해 있는지에 따라 `self`, `컴포넌트 객체`, `서비스명` 중 어떤 것을 앞에 붙이는지가 결정됩니다. ### 1. 동일 컴포넌트 내 메소드 호출 현재 실행 중인 메소드가 포함된 컴포넌트 내부의 다른 메소드를 호출할 때는 **`self:메소드명(매개 변수)`** 형식을 사용합니다. `self`는 현재 작동 중인 메소드를 포함하고 있는 컴포넌트 객체를 가리킵니다. ```lua void OnBeginPlay() { local param = "MethodCall [followup] | self:메소드명(매개 변수) 형식으로 동일 컴포넌트 메소드를 호출하는 예제와, _EntityService:GetEntityByPath를 통해 다른 컴포넌트 객체를 참조하여 메소드를 호출하는 구체적인 코드 예제를 작성해 주세요. [followup_answer] | 요청하신 두 가지 시나리오에 대한 mLua 코드 예제는 다음과 같습니다. ### 1. 동일 컴포넌트 내 메소드 호출 (`self:메소드명()`) `OnBeginPlay` 라이프사이클 메소드에서 같은 컴포넌트 내에 정의된 `MethodPractice` 메소드를 호출하는 예시입니다. ```lua Method: void OnBeginPlay() { local param = "MethodCallTest" self:MethodPractice(param) -- self:메소드명(매개 변수)으로 메소드 호출 } [scores] | [judge_reason] | [source_doc] | 메소드 내부에서는 다른 메소드를 호출해서 다른 함수의 기능을 작동시킬 수 있습니다. 기본적으로 메소드는 **컴포넌트 객체(또는 서비스):메소드명(매개 변수)** 형식으로 호출합니다. #### 동일한 컴포넌트 내 메소드 호출 시 동일 컴포넌트의 메소드를 호출할 때는 다음과 같이 **self:메소드명(매개 변수)** 형식으로 호출합니다. (**self**는 현재 작동 중인 메소드를 포함하고 있는 컴포넌트 객체를 의미합니다.) ```lua --개념 이해를 돕기 위한 코드로, 컴포넌트에 적용 시 정상적으로 동작하지 않을 수 있습니다.
[task] | single_turn [pass] | ⏳ 미판정 [title] | Entity Event System [question] | VampireComponent와 HunterComponent를 각각 NPC 엔티티에 추가한 후, 두 컴포넌트가 동일한 SunriseEvent를 수신하도록 핸들러를 등록하는 과정은 어떻게 진행되나요? [answer] | 참고 문서에는 `SunriseEvent`의 프로퍼티 정의와 NPC 엔티티에 컴포넌트를 배치하는 과정은 설명되어 있지만, **이벤트를 수신하기 위해 핸들러를 등록하는 구체적인 코드나 메서드 명세는 제공되지 않습니다.** 문서에서는 "각각의 컴포넌트는 엔티티를 통해 핸들러를 등록하고 이벤트를 발생시킬 수 있다"는 원리만 설명하고 있으며, `SunriseEvent`를 수신하는 `VampireComponent`와 `HunterComponent`의 실제 핸들러 구현 코드(예: `HandleSunriseEvent`)는 문서에 포함되어 있지 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 Entity Event System을 사용해 이벤트를 제어할 수 있습니다. 이번 시간에는 Entity Event System을 이용해 "뱀파이어 vs 헌터"의 게임 요소 중 하나를 만들어봅시다. 다음 가이드를 먼저 학습하면 이번 과정을 이해하는 데 많은 도움이 됩니다. [Event System](https://mod-developers.nexon.com/docs?postId=73) # Entity Event System 이벤트를 받고 보내려면 먼저 Entity Event System을
[task] | single_turn [pass] | ⏳ 미판정 [title] | 엔티티의 충돌 [question] | TriggerComponent의 함수를 직접 수정할 수 없어 확장 컴포넌트를 만들어야 하는 이유와, 확장 후 엔티티에 컴포넌트를 추가할 때 원본과 확장 버전 중 무엇을 사용해야 하는지 알려주세요. [answer] | TriggerComponent의 충돌 이벤트 처리 함수를 직접 수정할 수 있는 이유는 다음과 같습니다. **1. 직접 수정이 불가능한 이유** TriggerComponent는 게임 엔진에서 기본적으로 제공하는 네이티브 컴포넌트이며, 이 컴포넌트 내의 충돌 이벤트 핸들러 함수를 사용자가 직접 편집하거나 변경할 수 없습니다. 따라서 충돌 시 수행할 특정 액션(예: 체력 감소, 엔티티 삭제 등)을 추가하려면 반드시 **확장(Extend)된 컴포넌트**를 생성하여 해당 함수를 오버라이드(Override)해야 합니다. **2. 엔티티에 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 충돌 이벤트 이후 액션은 **Entity Event System**을 활용하거나, **확장된 TriggerComponent** 활용합니다. 월드에 **TriggerComponent**를 포함하는 A와 B, 두 엔티티가 있다고 가정해 봅시다. A와 B가 부딪히면 충돌 이벤트가 발생합니다. 그러나 이후 특별한 변화가 일어나지 않을 것입니다. 충돌 이벤트 발생을 한 뒤 일어날 추가 액션이 없기 때문입니다. **TriggerComponent**를 활용하면 충돌 이벤트가 발생할 때 일어날 액션을 추가할 수 있습니다. 예를 들어 A와 B가 충
[task] | two_turn [pass] | ⏳ 미판정 [title] | 함수 [question] | 루아 스크립트 내장 함수(table, string)와 Vector2 타입의 Static 메소드 호출 시 콜론(:)과 점(.) 사용 규칙이 다른 이유와 적용 범위를 알려 주세요. [answer] | mLua에서 메소드 호출 시 콜론(`:`)과 점(`.`)을 구분하는 핵심 원리는 **인스턴스 메소드**와 **Static 메소드(또는 글로벌 함수)**의 차이입니다. ### 1. 콜론(`:`)과 점(`.`) 사용 규칙 * **콜론(`:`) 사용: 인스턴스 메소드** * **적용 대상:** 특정 객체(컴포넌트, 서비스, 엔티티 등)에 속한 메소드. * **동작 방식:** 호출 대상 객체를 첫 번째 매개변수(self)로 자동으로 전달합니다. * **예외 포함:** 동일한 컴포넌트 내부 메소드 호출 [followup] | table.insert, string.len, Vector2.Distance 등 콜론이 아닌 점(.)으로 호출해야 하는 Static 메소드와 일반 루아 함수를 함께 사용하는 OnBeginPlay 코드 예제를 작성해 주세요. [followup_answer] | 참고 문서에 제시된 `table.insert`, `string.len`, `Vector2.Distance` 호출 방식을 포함하여, `OnBeginPlay` 라이프사이클 메서드 내부에서 점(`.`)으로 호출하는 Static 메소드와 일반 루아 함수를 함께 사용하는 코드 예제는 다음과 같습니다. ```lua Method: [server only] void OnBeginPlay() { -- 1. 루아 내장 함수 (Global/Static) 사용 예시 local tmpTable = {1, 2, 3, 4, 5} tab [scores] | [judge_reason] | [source_doc] | 메소드 내부에서는 다른 메소드를 호출해서 다른 함수의 기능을 작동시킬 수 있습니다. 기본적으로 메소드는 **컴포넌트 객체(또는 서비스):메소드명(매개 변수)** 형식으로 호출합니다. #### 동일한 컴포넌트 내 메소드 호출 시 동일 컴포넌트의 메소드를 호출할 때는 다음과 같이 **self:메소드명(매개 변수)** 형식으로 호출합니다. (**self**는 현재 작동 중인 메소드를 포함하고 있는 컴포넌트 객체를 의미합니다.) ```lua --개념 이해를 돕기 위한 코드로, 컴포넌트에 적용 시 정상적으로 동작하지 않을 수 있습니다.
[task] | two_turn [pass] | ⏳ 미판정 [title] | 함수 [question] | 메이플스토리 월드에서 기본 이벤트 메소드와 사용자 지정 메소드의 차이점은 무엇이며, 왜 기본 이벤트 메소드에서만 다른 함수를 호출할 수 없나요? [answer] | 메이플스토리 월드의 함수(메소드)는 호출 주체에 따라 **기본 이벤트 메소드**와 **사용자 지정 메소드**로 구분됩니다. 두 메소드의 차이점과 기본 이벤트 메소드에서 다른 함수를 호출할 수 없는 이유는 다음과 같습니다. ### 1. 기본 이벤트 메소드와 사용자 지정 메소드의 차이점 | 구분 | 기본 이벤트 메소드 | 사용자 지정 메소드 | | :--- | :--- | :--- | | **호출 시점** | 게임 시작, 플레이 중, 종료 등 특정 시스템 이벤트가 발생했을 때 **정해져 있음** | 개발자가 정의한 목적에 따라 ** [followup] | 기본 이벤트 메소드(예: OnBeginPlay)에서 사용자 지정 메소드를 호출하는 코드가 아니라, 사용자 지정 메소드끼리 직접 호출하는 코드가 가능한지 예외가 있는지 알려주세요. [followup_answer] | 참고 문서에 따르면, 사용자 지정 메소드끼리 직접 호출하는 것이 가능합니다. 문서에는 사용자 지정 메소드에 대해 "시스템에서 자동으로 호출하지 않기 때문에 **기본 이벤트 함수로부터 호출하여 실행**"한다고 명시하고 있습니다. 이는 모든 사용자 지정 메소드의 **최종 진입점**이 기본 이벤트 메소드여야 한다는 것을 의미하며, 사용자 지정 메소드 내부에서 다른 사용자 지정 메소드를 호출하는 것을 금지하는 내용은 없습니다. 즉, 로직을 모듈화하기 위해 `OnBeginPlay`에서 `MethodA`를 호출하고, `MethodA` 내부 [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 함수에 대한 간략한 소개와 함께 함수의 선언과 정의, 호출에 대해 알아봅니다. # 메소드 소개 **컴포넌트**는 기본적으로 **프로퍼티**와 **메소드**로 구성됩니다. 그중 함수는 객체지향 프로그래밍에서 사용되는 용어로, 특정 액션을 수행하기 위한 코드들의 집합체라 할 수 있습니다. 메이플스토리 월드의 함수는 함수의 호출 주체가 누구냐에 따라 **기본 이벤트 메소드**와 **사용자 지정 메소드**로 나눌 수 있습니다. 기본 이벤트 함수는 게임 시작, 플레이 중, 게임 종료 시 등 특정 이벤트가 발생했을 때
[task] | instruction_following [pass] | ⏳ 미판정 [title] | Entity Event System [question] | Z 키 입력 시 일출 이벤트를 트리거하는 HunterComponent의 이벤트 핸들러 코드 블록을 주석 포함으로 출력하고, 설명 문장은 쓰지 마세요. [answer] | ```lua Event Handler: [service: InputService] HandleKeyDownEvent(KeyDownEvent event) { -- Parameters local key = event.key -------------------------------------------------------------------------------- if key == KeyboardKey.Z then --Z 키를 누르면 `일출` 메시지가 Console 창에 나타납니다. log( [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 특정 시간마다 해가 뜨고 지는 로직을 만들어봅시다. 1. 해가 뜨고 지는 시간을 관리할 스크립트 컴포넌트가 필요합니다. **Workspace - MyDesk**의 콘텍스트 메뉴에서 **Create Scrips - Create Component**를 클릭해 새 컴포넌트를 만듭니다. 이름으로 **TimeManager**를 입력합니다. 2. **TimeManager** 스크립트 컴포넌트를 엽니다. `OnUpdate` 함수를 추가하여 해가 뜨고 지는 것을 판단하도록 합니다. ```lua Property: [Sy
[task] | single_turn [pass] | ⏳ 미판정 [title] | Entity Event System [question] | 맵 엔티티와 월드 엔티티가 서로 이벤트를 주고받을 때, 일반적인 자기 자신 엔티티 연결과 구조적으로 어떻게 다른가요? [answer] | 제공된 문서를 바탕으로 맵 엔티티와 월드 엔티티 간 이벤트 주고받기의 구조적 차이를 설명하면 다음과 같습니다. 일반적인 경우 컴포넌트는 **자기 자신의 엔티티**를 중계자로 사용하여 핸들러를 등록하고 이벤트를 발생시킵니다. 즉, 이벤트의 송신자(Sender)와 수신자(Receiver)가 동일한 엔티티 내의 컴포넌트들로 연결되는 구조입니다. 반면, **맵 엔티티와 월드 엔티티**는 서로 다른 엔티티에 존재하는 경우가 많아, 이벤트를 **다른 엔티티에 연결**하는 형태를 자주 사용합니다. 이는 이벤트의 송신자가 한 엔티티(예: 맵 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 Entity Event System을 사용해 이벤트를 제어할 수 있습니다. 이번 시간에는 Entity Event System을 이용해 "뱀파이어 vs 헌터"의 게임 요소 중 하나를 만들어봅시다. 다음 가이드를 먼저 학습하면 이번 과정을 이해하는 데 많은 도움이 됩니다. [Event System](https://mod-developers.nexon.com/docs?postId=73) # Entity Event System 이벤트를 받고 보내려면 먼저 Entity Event System을
[task] | single_turn [pass] | ⏳ 미판정 [title] | 엔티티를 탐색하는 EntityService [question] | GetEntityByTag는 여러 엔티티가 같은 태그를 가진 경우 왜 하나만 반환하나요? [answer] | `GetEntityByTag`는 여러 엔티티가 동일한 태그를 가지고 있을 때 가장 먼저 찾은 엔티티 하나만 반환하도록 설계되어 있습니다. 따라서 이 함수는 유니크한(고유한) 태그를 가진 엔티티를 탐색할 때 사용하는 것을 권장합니다. 만약 특정 태그를 가진 모든 엔티티를 받아오고 싶다면, 여러 엔티티를 반환하는 `GetEntitiesByTag`를 사용해야 합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 모델 ID와 일치하는 모델로부터 생성된 모든 엔티티를 반환합니다. 다음과 같이 수많은 엔티티가 배치된 상황에서 NPC와 같이 동일 모델로부터 생성된 모든 엔티티를 받고 싶을 때 유용하게 사용됩니다. 특정 엔티티에 접근하여 모델을 받은 뒤, 해당 모델로부터 생성된 모든 엔티티를 받을 수 있습니다. ```lua void GetEntitiesSpawnedByModelIdExample() { local modelId = _EntityService:GetEntityByPath("/maps/map02/npc-5396_1").Mode
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 엔티티를 탐색하는 EntityService [question] | 엔티티 생성 및 삭제 이벤트 핸들러를 설정할 때 확인해야 할 조건을 3문장 이내로 요약하세요. [answer] | 이벤트 핸들러를 추가한 뒤 이벤트 센더가 EntityService인지 확인해야 합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 매개 변수로 전달한 엔티티를 삭제합니다. ```lua void DestroyExample() { local entity = _EntityService:GetEntityByPath("/maps/map01/Monster1_1") _EntityService:Destroy(entity) if isvalid(entity) == false then log("Entity is destroyed") end } ``` 꼭 `EntityService:Destroy`를 사용하지 않고도, 엔티티의 `
[task] | single_turn [pass] | ⏳ 미판정 [title] | Entity Event System [question] | Workspace - MyDesk에서 Create EventType를 클릭해 SunriseEvent를 만든 후, 이벤트 스크립트 내에 isSunrise 속성을 추가해야 하는 이유는 무엇인가요? [answer] | `SunriseEvent` 이벤트 스크립트 내에 `isSunrise` 속성을 추가하는 이유는, 이벤트가 발생할 때 **해가 뜨고 지는 상태(진실/거짓)를 함께 전달하기 위해서**입니다. 이벤트 시스템에서 이벤트는 단순히 "발생했다는 사실"만 알리는 것이 아니라, 해당 상황과 관련된 데이터를 포함할 수 있습니다. `SunriseEvent`는 해가 뜨거나 지는 상황을 알리는 이벤트이므로, 수신 측(예: VampireComponent, HunterComponent)이 **현재가 "해가 뜬 상태"인지, "해가 진 상태"인지**를 구별할 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 Entity Event System을 사용해 이벤트를 제어할 수 있습니다. 이번 시간에는 Entity Event System을 이용해 "뱀파이어 vs 헌터"의 게임 요소 중 하나를 만들어봅시다. 다음 가이드를 먼저 학습하면 이번 과정을 이해하는 데 많은 도움이 됩니다. [Event System](https://mod-developers.nexon.com/docs?postId=73) # Entity Event System 이벤트를 받고 보내려면 먼저 Entity Event System을
[task] | single_turn [pass] | ⏳ 미판정 [title] | Entity Event System [question] | 기본 제공되는 네이티브 형 이벤트와 크리에이터가 직접 선언한 이벤트 타입의 차이점 및 Import 방식에 대해 알려주세요. [answer] | 참고 문서에 따르면, 이벤트 시스템에는 **기본 제공되는 네이티브 형 이벤트**와 **크리에이터가 직접 선언하거나 Import 할 수 있는 이벤트**가 존재합니다. 하지만 문서에는 이 두 가지의 구체적인 **차이점**이나 **Import 방식의 상세 절차**에 대한 설명이 포함되어 있지 않습니다. 문서에 명시된 내용은 다음과 같습니다. 1. **기본 제공되는 네이티브 형 이벤트**: 이벤트 시스템에 기본적으로 포함되어 있음을 언급하고 있습니다. 2. **직접 선언 또는 Import**: 크리에이터가 직접 이벤트 타입을 선언하 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 Entity Event System을 사용해 이벤트를 제어할 수 있습니다. 이번 시간에는 Entity Event System을 이용해 "뱀파이어 vs 헌터"의 게임 요소 중 하나를 만들어봅시다. 다음 가이드를 먼저 학습하면 이번 과정을 이해하는 데 많은 도움이 됩니다. [Event System](https://mod-developers.nexon.com/docs?postId=73) # Entity Event System 이벤트를 받고 보내려면 먼저 Entity Event System을
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 엔티티를 탐색하는 EntityService [question] | GetEntity()를 사용하여 특정 엔티티를 탐색하는 과정을 단계별 번호 목록으로 정리하세요. [answer] | `GetEntity()`를 사용하여 특정 엔티티를 탐색하는 과정은 다음과 같습니다. 1. **엔티티 ID 확보** `Hierarchy` 뷰에서 원하는 엔티티의 컨텍스트 메뉴에서 **Copy Entity ID**를 선택하거나, 스크립트 내에서 다른 메서드(예: `GetEntityByPath`)를 통해 먼저 엔티티를 찾아 `entity.Id` 속성에서 ID 값을 받아옵니다. 2. **EntityService 호출** 확보한 엔티티 ID를 매개 변수로 전달하여 `_EntityService:GetEntity(entit [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 월드를 제작하다 보면 특정 엔티티를 탐색하여 받아오거나, 혹은 관련 있는 여러 엔티티를 한 번에 받아야 하는 상황이 자주 발생합니다. 이럴 때 [**EntityService**](/apiReference/Services/EntityService)를 활용할 수 있습니다. **EntityService**는 엔티티 탐색, 삭제, 유효성 체크 등의 기능을 제공하고 있습니다. 이번 과정에서는 **EntityService**에서 제공하는 기능의 사용법을 하나씩 알아보도록 하겠습니다. **테스트 환경** **common
[task] | code [pass] | ⏳ 미판정 [title] | 엔티티의 충돌 [question] | TriggerEnterEvent 핸들러를 사용하여 자기가 포함된 엔티티와 충돌하는 상대 엔티티의 체력을 10 감소시키는 스크립트를 작성해줘 [answer] | `TriggerEnterEvent` 핸들러를 통해 충돌한 상대 엔티티(`TriggerBodyEntity`)의 체력을 10 감소시키는 스크립트는 다음과 같이 작성할 수 있습니다. 참고로, 상대 엔티티의 체력을 조작하기 위해서는 해당 상대 엔티티에 체력 값을 다루는 스크립트 컴포넌트(예: `Hp` 프로퍼티를 가진 스크립트)가 존재해야 하며, 이를 통해 접근해야 합니다. 아래 예시는 상대 엔티티에 `Hp` 프로퍼티가 있는 스크립트 컴포넌트가 있다는 가정 하에 작성되었습니다. ```lua Event Handler: [server onl [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 충돌 이벤트 이후 액션은 **Entity Event System**을 활용하거나, **확장된 TriggerComponent** 활용합니다. 월드에 **TriggerComponent**를 포함하는 A와 B, 두 엔티티가 있다고 가정해 봅시다. A와 B가 부딪히면 충돌 이벤트가 발생합니다. 그러나 이후 특별한 변화가 일어나지 않을 것입니다. 충돌 이벤트 발생을 한 뒤 일어날 추가 액션이 없기 때문입니다. **TriggerComponent**를 활용하면 충돌 이벤트가 발생할 때 일어날 액션을 추가할 수 있습니다. 예를 들어 A와 B가 충
[task] | two_turn [pass] | ⏳ 미판정 [title] | 엔티티의 충돌 [question] | ColliderOffset을 드래그로 편집하는 것과 코드/프로퍼티로 설정하는 방식의 차이점과, Box와 Circle 형태에서 각각의 크기 프로퍼티(X, Y, CircleRadius)를 어떻게 제어하는지 설명해 주세요. [answer] | 충돌체 편집 방식과 형태별 크기 프로퍼티 제어 방법은 다음과 같습니다. **1. ColliderOffset 편집 방식의 차이점** * **드래그 편집 (프로퍼티 에디터):** * 프로퍼티 에디터에서 충돌체 편집을 활성화(초록색 표시)한 후, 충돌체의 포인트를 마우스로 드래그하면 `ColliderOffset` 값이 시각적으로 설정됩니다. * 이는 크리에이터가 직관적으로 충돌체의 위치 오프셋을 조정하기 위한 인터페이스 방식입니다. * **코드/프로퍼티 설정:** * `ColliderOffset [followup] | HitComponent의 피격 범위를 설정할 때 ColliderType을 Circle로 지정하고 CircleRadius 값을 5로 고정하는 프로퍼티 선언부 예시를 작성해 주세요. [followup_answer] | HitComponent의 ColliderType을 Circle로 지정하고 CircleRadius 값을 5로 고정하는 프로퍼티 선언부 예시는 다음과 같습니다. ```lua Property: [None] ColliderType ColliderType = Circle [None] number CircleRadius = 5 ``` 참고로, `HitComponent`는 피격 범위를 설정할 때 사용되며, `ColliderType`을 `Circle`으로 설정하면 `CircleRadius` 값이 원의 반지름을 결정합니다. 위 선언부는 스크립트 [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 충돌 이벤트와 충돌 처리 방법에 대해 알아봅시다. ##### 참고 가이드 [Event System](https://mod-developers.nexon.com/docs?postId=73) [Entity Event System](https://mod-developers.nexon.com/docs?postId=176) # 충돌 **충돌**이란 충돌체를 포함하는 엔티티'의 충돌 영역이 서로 교차하는 것을 말합니다. 엔티티에 [TriggerComponent](/apiReference/Components/Trigge
[task] | single_turn [pass] | ⏳ 미판정 [title] | 엔티티의 충돌 [question] | TriggerEnterEvent와 TriggerStayEvent의 발생 빈도가 어떻게 다른지, 반복적인 액션 처리 시 어떤 이벤트를 선택해야 하는지 궁금합니다. [answer] | 충돌 이벤트의 발생 빈도는 이벤트 종류에 따라 명확하게 구분됩니다. **1. 발생 빈도 차이** * **TriggerEnterEvent**: 두 엔티티가 **처음** 충돌하는 시점에 **1회만** 발생합니다. * **TriggerStayEvent**: 두 엔티티가 **충돌 상태가 유지되는 동안** **프레임마다** 반복적으로 발생합니다. **2. 반복적인 액션 처리 시 선택 가이드** 어떤 이벤트를 사용해야 하는지 판단할 때는 액션이 **1회성**인지 **지속적(반복)** 인지에 따라 결정합니다. * **Trigg [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 충돌 이벤트 이후 액션은 **Entity Event System**을 활용하거나, **확장된 TriggerComponent** 활용합니다. 월드에 **TriggerComponent**를 포함하는 A와 B, 두 엔티티가 있다고 가정해 봅시다. A와 B가 부딪히면 충돌 이벤트가 발생합니다. 그러나 이후 특별한 변화가 일어나지 않을 것입니다. 충돌 이벤트 발생을 한 뒤 일어날 추가 액션이 없기 때문입니다. **TriggerComponent**를 활용하면 충돌 이벤트가 발생할 때 일어날 액션을 추가할 수 있습니다. 예를 들어 A와 B가 충
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 엔티티를 탐색하는 EntityService [question] | EntityService의 태그 기반 탐색 메서드인 GetEntityByTag와 GetEntitiesByTag 중 여러 엔티티를 모두 가져올 때 사용할 메서드와 그 이유를 2문장 이내로 설명하세요. [answer] | 여러 엔티티를 모두 가져올 때는 `GetEntitiesByTag`를 사용해야 합니다. `GetEntityByTag`는 일치하는 엔티티 중 가장 먼저 찾은 하나만 반환하기 때문입니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 모델 ID와 일치하는 모델로부터 생성된 모든 엔티티를 반환합니다. 다음과 같이 수많은 엔티티가 배치된 상황에서 NPC와 같이 동일 모델로부터 생성된 모든 엔티티를 받고 싶을 때 유용하게 사용됩니다. 특정 엔티티에 접근하여 모델을 받은 뒤, 해당 모델로부터 생성된 모든 엔티티를 받을 수 있습니다. ```lua void GetEntitiesSpawnedByModelIdExample() { local modelId = _EntityService:GetEntityByPath("/maps/map02/npc-5396_1").Mode