[task] | code [pass] | ⏳ 미판정 [title] | 행동 트리를 활용한 AI 만들기 [question] | RandomSelector Node를 활용해 30% 확률로 스킬 사용, 70% 확률로 일반 공격을 무작위로 선택해 실행하는 AI 로직을 구현하는 스크립트를 작성해줘 [answer] | 참고 문서에는 `RandomSelector` 노드가 자식 노드 중 하나를 무작위로 선택하여 실행하고, 각 자식 노드가 반환한 `Success` 또는 `Failure` 값을 부모 노드로 그대로 반환한다고 설명되어 있습니다. 또한, 노드 확률은 자식 노드의 순서와 누적 확률(예: 0.2, 0.5, 1.0)에 기반하여 난수가 속한 범위에 따라 선택된다고 명시되어 있습니다. 그러나 제공된 참고 문서에는 **`RandomSelector` 노드를 mLua 스크립트로 직접 생성하거나(`CreateNode` 등) 확률 값을 설정하는 구체적인 A [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | **Selector Node**는 자식 노드를 순서대로 실행하다가 자식 노드가 Success를 반환하면 실행을 멈추고 부모 노드로 Success를 반환합니다. 모든 자식 노드가 Failure를 반환하면 부모 노드에 Failure를 반환합니다. ![[object Object]](https://mod-file.dn.nexoncdn.co.kr/bbs/17168858785873218b87041fd46df9756a267a30ce29e.png "SelectorNode") #### RandomSelector Node **RandomSelec
[task] | single_turn [pass] | ⏳ 미판정 [title] | 행동 트리를 활용한 AI 만들기 [question] | AIComponent의 CreateNode와 CreateLeafNode의 차이점과 각각 언제 사용해야 하는지 알고 싶습니다. [answer] | AIComponent의 `CreateNode()`와 `CreateLeafNode()`는 행동 트리(Behaviour Tree)의 노드를 생성하는 방법에서 차이가 있으며, 노드의 복잡성과 정의 방식에 따라 각각 다른 용도로 사용됩니다. ### 1. CreateNode() * **특징**: `BTNodeType`을 명시적으로 지정하여 노드 객체를 생성합니다. * **매개 변수**: 생성될 `BTNodeType`(타입 이름)과 노드 이름을 전달합니다. * **사용 시점**: * 기존에 정의된 행동 트리 노드 타입( [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | AI로 사용할 엔티티에는 **AIComponent 또는 확장한 AIComponent**가 포함되어 있어야 합니다. AIComponent는 BTNodeType에서 정의된 내용으로 Action Node를 별도의 객체로 생성하거나, 만들어진 행동 트리의 최상위 노드를 Root 노드로 설정하여 엔티티에 AI를 부여하기 때문입니다. Action Node를 만들 때는 AIComponent의 `CreateNode()`, `CreateLeafNode()`를 활용해 Action Node를 생성할 수 있습니다. > **Tip** > Action N
[task] | two_turn [pass] | ⏳ 미판정 [title] | 행동 트리를 활용한 AI 만들기 [question] | 행동 트리(Behaviour Tree)가 유한 상태 기계(FSM)나 계층적 유한 상태 기계(HFSM)와 비교했을 때 어떤 구조적 장점을 가지고 있나요? [answer] | 행동 트리(Behaviour Tree, BT)는 유한 상태 기계(FSM)와 계층적 유한 상태 기계(HFSM)에 비해 다음과 같은 구조적 장점을 가집니다. 1. **개별 로직의 모듈화와 재사용성** * **FSM의 한계:** 상태(State)와 전이(Transition)로 구성되어 있어 상태와 액션이 복잡해지면 연결과 유지보수 부담이 커지며, 규모가 커지면 상태 흐름 파악이 어려워지고 재사용이 불가능해집니다. * **HFSM의 한계:** 상태 변화의 흐름을 모듈화하여 재사용할 수 있다는 장점이 있지만, 개별 [followup] | 행동 트리의 개별 노드가 결합 순서에 따라 어떻게 순차적으로 실행되는지, 그리고 특정 행동의 연결과 해제가 용이하다는 점을 구체적인 상황 예를 들어 설명해 주세요. [followup_answer] | 행동 트리의 개별 노드 실행 방식과 연결/해제 용이성에 대해 참고 문서에 근거하여 설명드리겠습니다. ### 1. 결합 순서에 따른 순차적 실행 행동 트리의 각 노드는 **결합 순서에 따라 순차적으로 실행**됩니다. 이는 노드가 트리 구조상에서 부모-자식 관계로 연결되어 있으며, 실행 흐름이 이 연결 순서를 따라 진행된다는 의미입니다. 문서에서는 구체적인 실행 알고리즘(예: SequenceNode의 모든 자식 노드가 성공해야 성공하는 방식 등)을 상세히 서술하지는 않지만, 제공된 API Reference 목록에 `Sequence [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 행동 트리와 BTNodeType 개념을 이해하고, AIComponent를 활용해 Action Node를 생성하는 방법을 알아봅시다. [행동 트리 노드 만들기](/docs?postId=1155)에서 행동 트리 구현 방법과 예제를 소개합니다. ##### 참고 가이드 * [행동 트리 노드 만들기](/docs?postId=1155) * [Behaviour Tree Editor로 행동 트리 만들기](/docs?postId=1399) ##### 참고 API Reference * [BTNode](/apiReference
[task] | single_turn [pass] | ⏳ 미판정 [title] | 효과음 만들기 [question] | SetCameraAsListener 프로퍼티와 SetListenerEntity 함수를 동시에 사용했을 때 실제 리스너로 작동하는 것은 어느 쪽인가요? [answer] | **SetListenerEntity** 함수를 통해 따로 지정한 리스너 엔티티가 있으면, **SetCameraAsListener** 프로퍼티가 활성화되어 있더라도 지정한 엔티티가 리스너로 작동합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | **SetCameraAsListener** 프로퍼티를 활용하는 방법도 있습니다. **SoundComponent** 프로퍼티에서 설명했듯이 **SetCameraAsListener**를 활성화하면 화면 중앙과 음원 사이의 거리에 따라 소리 크기를 조절합니다. 간단하게 **SetCameraAsListener** 프로퍼티를 활용하는 방법을 살펴봅시다. 1. **Preset List**에서 아무 맵 오브젝트나 **Scene**에 배치한 뒤 **SpriteRendererComponent - SpriteRUID**에 아래의 **RUID**를
[task] | single_turn [pass] | ⏳ 미판정 [title] | 효과음 만들기 [question] | SpriteRendererComponent에 효과음용 스프라이트를 배치할 때 지정해야 하는 SpriteRUID 값은 무엇인가요? [answer] | 문서에 명시된 효과음용 스프라이트의 SpriteRUID 값은 `c5cf1b7c8d6447f7979b544e166965fc`입니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | **SetCameraAsListener** 프로퍼티를 활용하는 방법도 있습니다. **SoundComponent** 프로퍼티에서 설명했듯이 **SetCameraAsListener**를 활성화하면 화면 중앙과 음원 사이의 거리에 따라 소리 크기를 조절합니다. 간단하게 **SetCameraAsListener** 프로퍼티를 활용하는 방법을 살펴봅시다. 1. **Preset List**에서 아무 맵 오브젝트나 **Scene**에 배치한 뒤 **SpriteRendererComponent - SpriteRUID**에 아래의 **RUID**를
[task] | single_turn [pass] | ⏳ 미판정 [title] | 행동 트리를 활용한 AI 만들기 [question] | 행동 트리의 실행 순서가 '위에서 아래, 왼쪽에서 오른쪽'이라고 하는데, 부모 노드 안에 자식 노드 A, B, C가 있을 때 A의 자식 노드 D, F까지 포함하면 정확한 실행 순서가 어떻게 되나요? [answer] | 문서에 명시된 실행 규칙에 따라 정확한 순서를 설명해 드리겠습니다. 행동 트리는 **부모 노드가 자식 노드를 실행하며, 각 부모에 등록된 순서대로** 실행됩니다. 이때 핵심은 **"A의 자식 노드 D, F를 모두 실행한 후 노드 B가 실행된다"** 는 점입니다. 즉, 한 노드가 실행되면 그 노드의 자식들까지 완전히 처리된 후에야 같은 레벨의 다음 형제 노드로 넘어가는 **깊이 우선(Depth-First)** 방식의 순차 실행이 이루어집니다. 따라서 부모 노드에 자식 노드 A, B, C가 순서대로 등록되어 있고, A의 자식으로 D [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 행동 트리는 프레임마다 Root 노드에서 시작합니다. 그 후 순차적으로 실행됩니다. 실행 순서는 위에서 아래, 왼쪽에서 오른쪽입니다. 부모 노드가 자식 노드를 실행하며 실행 순서는 각 부모에 등록된 순서대로 실행됩니다. 부모 노드는 종류에 따라 자식 노드 실행 조건을 달리하며, 조건에 부합할 때 부모가 가진 자식 노드를 모두 순차적으로 실행합니다. 예를 들어 부모 노드에 자식 노드 A, B, C가 순차적으로 등록된 경우 A가 가장 좌측에, 노드 C가 가장 우측에 배치됩니다. 부모 노드 실행 시 자식 노드는 A, B, C 순으로 실행
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 이동 발판 만들기 [question] | IsDynamicFoothold 프로퍼티를 활성화해야 하는 이유를 한 문장으로 설명하세요. [answer] | CustomFootholdComponent가 움직이는 발판으로 동작하도록 활성화하기 위해 필요합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 움직이는 발판을 만들어 이동에 재미를 더해보세요. CustomFootholdComponent의 IsDynamicFoothold 프로퍼티를 이용해 나만의 움직이는 발판을 만들 수 있습니다. [발판 만들기](/docs/?postId=71%7B%22target%22:%22_self%22%7D)에서 기본 발판 제작 방법을 배울 수 있습니다. # 이동 발판 만들기 이동 발판은 CustomFootholdComponent를 활용해 크리에이터가 직접 만들어야 합니다. 발판의 움직임을 만드는 방식은 다르지만, 기본 Cus
[task] | code [pass] | ⏳ 미판정 [title] | 행동 트리를 활용한 AI 만들기 [question] | Decorator Node를 활용해 자식 노드의 실행 결과를 반전(Success를 Failure로, Failure를 Success로)하여 반환하는 커스텀 데코레이터 로직을 구현하는 스크립트 [answer] | 제공된 참고 문서의 "여러 프레임 동안 동작하는 노드" 섹션에 있는 mLua 예제 코드를 기반으로, 자식 노드의 실행 결과를 반전시키는 커스텀 Decorator Node 스크립트를 구현할 수 있습니다. 문서에 따르면, 커스텀 Decorator Node는 `Property` 블록에 자식 노드를 참조하는 변수를 선언하고, `Method` 블록에 `OnBehave` 함수를 정의하여 실행 로직을 처리합니다. 자식 노드가 `Success`를 반환하면 `Failure`를, `Failure`를 반환하면 `Success`를 반환하도록 분기 처리 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | **Selector Node**는 자식 노드를 순서대로 실행하다가 자식 노드가 Success를 반환하면 실행을 멈추고 부모 노드로 Success를 반환합니다. 모든 자식 노드가 Failure를 반환하면 부모 노드에 Failure를 반환합니다. ![[object Object]](https://mod-file.dn.nexoncdn.co.kr/bbs/17168858785873218b87041fd46df9756a267a30ce29e.png "SelectorNode") #### RandomSelector Node **RandomSelec
[task] | code [pass] | ⏳ 미판정 [title] | 행동 트리를 활용한 AI 만들기 [question] | AIComponent를 통해 CreateLeafNode()로 함수를 전달할 때, 매개변수로 노드 이름과 실행 시 log를 출력하고 BehaviourTreeStatus.Success를 반환하는 익명 함수를 지정해줘. [answer] | ```lua local func = function() log("ActionNode!") return BehaviourTreeStatus.Success end local node = self.Entity.AIComponent:CreateLeafNode("NodeInstanceName", func) ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | AI로 사용할 엔티티에는 **AIComponent 또는 확장한 AIComponent**가 포함되어 있어야 합니다. AIComponent는 BTNodeType에서 정의된 내용으로 Action Node를 별도의 객체로 생성하거나, 만들어진 행동 트리의 최상위 노드를 Root 노드로 설정하여 엔티티에 AI를 부여하기 때문입니다. Action Node를 만들 때는 AIComponent의 `CreateNode()`, `CreateLeafNode()`를 활용해 Action Node를 생성할 수 있습니다. > **Tip** > Action N
[task] | code [pass] | ⏳ 미판정 [title] | 행동 트리를 활용한 AI 만들기 [question] | OnBehave(number delta) 의 매개변수 delta 를 활용하여 3초 동안 이동한 후 BehaviourTreeStatus.Success 를 반환하는 액션 노드 스크립트를 작성해줘 [answer] | 3초 동안 이동한 후 `BehaviourTreeStatus.Success`를 반환하는 액션 노드 스크립트는 다음과 같습니다. ```lua Property: [None] number ElapsedTime = 0 [None] number MoveTime = 3 Method: void OnInit() { -- 실행될 때마다 경과 시간을 초기화합니다. self.ElapsedTime = 0 -- 실제 이동 로직(예: 이동 방향 지정)이 필요한 경우 여기에 추가할 수 있습니다. -- 예를 들어: sel [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 자식 노드가 Success 또는 Failure를 반환하면 부모 노드는 다음 자식 노드를 실행합니다. 그러나 자식 노드가 Running을 반환하면 부모 노드는 Running을 반환했던 자식 노드를 다음 프레임에 다시 실행합니다. 이 특성을 활용해 여러 프레임 동안 동작하는 노드를 만들 수 있습니다. 아래 그림과 같이 자식 노드 A, B, C가 있을 때 Sequence Node와 Selector Node의 경우 B 노드가 Running을 반환하는 동안 C 노드를 실행하지 않습니다. RandomSelector Node는 선택된 노드를 계
[task] | two_turn [pass] | ⏳ 미판정 [title] | 행동 트리를 활용한 AI 만들기 [question] | 문서에 소개된 `AIComponent`를 활용해 `Action Node`를 생성하는 일반적인 절차나 코드는 어떻게 작성하나요? [answer] | 참고 문서에 포함된 예제를 바탕으로 `AIComponent`를 활용해 `Action Node`(Leaf Node)를 생성하는 일반적인 절차는 다음과 같습니다. 1. `self.Entity.AIComponent` 를 통해 현재 엔티티에 부착된 `AIComponent` 를 가져옵니다. 2. `AIComponent` 의 `CreateLeafNode` 메서드를 호출합니다. 3. `CreateLeafNode` 에는 노드 이름(string)과, 매 프레임마다 실행될 로직을 담은 함수(callback)를 인수로 전달합니다. 4. 이 함 [followup] | `AIComponent` API를 직접 호출하여 `Action Node`를 생성하고, 이를 행동 트리 구조에 등록하는 mLua 스크립트 예제를 보여주세요. [followup_answer] | 참고 문서에 포함된 예제를 바탕으로 `AIComponent` 를 직접 호출하여 `Action Node`(Leaf Node)를 생성하고, 이를 다른 노드(Decorator)에 연결하는 mLua 스크립트 예제는 다음과 같습니다. ```lua [server only] void OnBeginPlay() { local aiComponent = self.Entity.AIComponent local childNode = aiComponent:CreateLeafNode("childNode", function(delta) [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 행동 트리와 BTNodeType 개념을 이해하고, AIComponent를 활용해 Action Node를 생성하는 방법을 알아봅시다. [행동 트리 노드 만들기](/docs?postId=1155)에서 행동 트리 구현 방법과 예제를 소개합니다. ##### 참고 가이드 * [행동 트리 노드 만들기](/docs?postId=1155) * [Behaviour Tree Editor로 행동 트리 만들기](/docs?postId=1399) ##### 참고 API Reference * [BTNode](/apiReference
[task] | single_turn [pass] | ⏳ 미판정 [title] | 행동 트리를 활용한 AI 만들기 [question] | Wait 노드를 만들 때 OnInit 함수가 Running 상태에서는 다시 호출되지 않는다는 점은 어떤 상황에서 주의해야 하나요? [answer] | Wait 노드를 만들 때 `OnInit()` 함수가 `Running` 상태에서는 다시 호출되지 않는다는 점은 **초기값이 노드 실행 시작 시점에만 한 번만 설정되며, `Running` 상태가 유지되는 동안에는 초기화 로직이 재실행되지 않는다**는 의미를 갖습니다. 이 특성을 활용할 때 주의해야 하는 상황과 그 이유는 다음과 같습니다. ### 1. 초기화 로직에 반복적 설정이 필요한 경우 `OnInit()` 내부에서 무작위 값 생성이나 외부 서비스 호출 등 **매 프레임마다 갱신되거나 재계산이 필요한 로직**을 넣으면 안 됩니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 자식 노드가 Success 또는 Failure를 반환하면 부모 노드는 다음 자식 노드를 실행합니다. 그러나 자식 노드가 Running을 반환하면 부모 노드는 Running을 반환했던 자식 노드를 다음 프레임에 다시 실행합니다. 이 특성을 활용해 여러 프레임 동안 동작하는 노드를 만들 수 있습니다. 아래 그림과 같이 자식 노드 A, B, C가 있을 때 Sequence Node와 Selector Node의 경우 B 노드가 Running을 반환하는 동안 C 노드를 실행하지 않습니다. RandomSelector Node는 선택된 노드를 계
[task] | two_turn [pass] | ⏳ 미판정 [title] | 카드와 UI 만들기 [question] | 카드 짝 맞추기 게임에서 UI에 카드를 배치하기 위해 CardBoard 컴포넌트와 CardSpawnRoot 프로퍼티를 설정하는 과정이 궁금합니다 [answer] | 카드 짝 맞추기 게임에서 UI에 카드를 배치하기 위해 `CardBoard` 컴포넌트와 `CardSpawnRoot` 프로퍼티를 설정하는 과정은 다음과 같습니다. ### 1. CardBoard 컴포넌트 추가 및 프로퍼티 설정 1. **CardBoard** 컴포넌트를 **CardPairGameUI** 그룹에 추가합니다. 2. **CardBoard** 컴포넌트를 선택하여 스크립트 에디터를 엽니다. 3. **CardSpawnRoot** 프로퍼티를 추가하고, 반환 타입을 `Entity`로 변경합니다. 4. **CardSpawnRoot**의 [followup] | CardSpawnRoot의 반환 타입을 Entity로 변경하고 UI_Block_Group 엔티티를 지정하는 구체적인 코드와, CreateCardEntities 함수 내에서 _SpawnService:SpawnByModelId() 호출 시 부모 엔티티(self.CardSpawnRoot)를 인자로 전달하는 정확한 문법을 알려주세요. [followup_answer] | `CardSpawnRoot` 프로퍼티 설정과 `_SpawnService:SpawnByModelId()` 호출 시 부모 엔티티를 인자로 전달하는 정확한 문법은 다음과 같습니다. ### 1. CardSpawnRoot 프로퍼티 설정 `CardBoard` 컴포넌트의 스크립트 에디터에서 `CardSpawnRoot` 프로퍼티의 반환 타입을 `Entity`로 변경하고, 값을 `UI_Block_Group` 엔티티 경로로 지정합니다. ```lua Property: [None] Entity CardSpawnRoot = /ui/CardParirGa [scores] | [judge_reason] | [source_doc] | 1. **CardBoard** 컴포넌트를 **CardPairGameUI** 그룹에 추가합니다. 2. **CardBoard** 컴포넌트를 선택해 스크립트 에디터를 엽니다. 3. **CardSpawnRoot** 프로퍼티를 추가하고, 반환 타입을 Entity로 변경합니다. 4. 엔티티는 **UI_Block_Group**으로 지정합니다. ```lua Property: [None] Entity CardSpawnRoot = /ui/CardParirGameUi/UI_Board/UI_Blocks/UI
[task] | code [pass] | ⏳ 미판정 [title] | 행동 트리를 활용한 AI 만들기 [question] | AIComponent의 CreateNode() 메서드를 사용하여 BTNodeType인 "NewBTNode"와 이름 "actionNode"를 전달하여 노드 객체를 생성해줘. [answer] | AIComponent의 `CreateNode()` 메서드는 생성할 노드 타입(`BTNodeType`)과 노드 이름을 매개 변수로 받아 새로운 노드 객체를 반환합니다. 요청하신 내용(`BTNodeType`이 `"NewBTNode"`, 이름이 `"actionNode"`)에 맞춰 작성한 코드는 다음과 같습니다. ```lua local node = self.Entity.AIComponent:CreateNode("NewBTNode", "actionNode") ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | AI로 사용할 엔티티에는 **AIComponent 또는 확장한 AIComponent**가 포함되어 있어야 합니다. AIComponent는 BTNodeType에서 정의된 내용으로 Action Node를 별도의 객체로 생성하거나, 만들어진 행동 트리의 최상위 노드를 Root 노드로 설정하여 엔티티에 AI를 부여하기 때문입니다. Action Node를 만들 때는 AIComponent의 `CreateNode()`, `CreateLeafNode()`를 활용해 Action Node를 생성할 수 있습니다. > **Tip** > Action N
[task] | two_turn [pass] | ⏳ 미판정 [title] | 행동 트리를 활용한 AI 만들기 [question] | 행동 트리에서 `ParallelNode`, `RandomSelectorNode`, `SelectorNode`, `SequenceNode` 같은 노드 타입들은 각각 어떤 역할을 하며, AI의 동작 흐름을 설계할 때 어떻게 조합해야 하나요? [answer] | 제공된 참고 문서에는 `ParallelNode`, `RandomSelectorNode`, `SelectorNode`, `SequenceNode`의 구체적인 내부 동작 방식이나 역할 설명이 포함되어 있지 않습니다. 문서에는 해당 노드들의 API Reference 링크(`/apiReference?postId=456` 등)와 코드 예제에서 변수 선언 및 인스턴스 생성 시 사용되는 이름(`Parallel`, `RandomSelector`, `Selector`, `Sequence`)만 언급되어 있습니다. 따라서 문서에 근거하여 각 노드의 [followup] | 플레이어가 접근하면 공격하고, 멀어지면 대기하는 단순한 몬스터 AI를 만들기 위해 `SelectorNode`와 `SequenceNode`를 어떻게 조합해야 하는지 논리 구조를 설명해 주세요. [followup_answer] | 제공된 참고 문서에는 `SelectorNode`와 `SequenceNode`의 구체적인 내부 동작 방식(예: 조건 분기 순서, 실패 시 처리 등)에 대한 상세 설명이 포함되어 있지 않습니다. 문서에는 해당 노드들의 API Reference 링크와 코드 예제에서 변수 선언 및 인스턴스 생성 시 사용되는 이름(`Selector`, `Sequence`)만 언급되어 있습니다. 따라서 문서에 명시된 사실만으로 "플레이어가 접근하면 공격하고, 멀어지면 대기하는" 논리 구조를 `SelectorNode`와 `SequenceNode`로 구체적으로 [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 행동 트리와 BTNodeType 개념을 이해하고, AIComponent를 활용해 Action Node를 생성하는 방법을 알아봅시다. [행동 트리 노드 만들기](/docs?postId=1155)에서 행동 트리 구현 방법과 예제를 소개합니다. ##### 참고 가이드 * [행동 트리 노드 만들기](/docs?postId=1155) * [Behaviour Tree Editor로 행동 트리 만들기](/docs?postId=1399) ##### 참고 API Reference * [BTNode](/apiReference
[task] | code [pass] | ⏳ 미판정 [title] | 행동 트리를 활용한 AI 만들기 [question] | AIComponent의 CreateLeafNode() 함수를 매개변수로 전달하여 실행 시 Success 상태를 반환하고 로그를 출력하는 Action Node를 생성해줘. [answer] | AIComponent의 `CreateLeafNode()` 함수를 사용하여 실행 시 로그를 출력하고 `BehaviourTreeStatus.Success`를 반환하는 Action Node를 생성하는 스크립트는 다음과 같습니다. ```lua [server only] void OnBeginPlay() { local func = function() log("ActionNode!") return BehaviourTreeStatus.Success end local printLogNode [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | AI로 사용할 엔티티에는 **AIComponent 또는 확장한 AIComponent**가 포함되어 있어야 합니다. AIComponent는 BTNodeType에서 정의된 내용으로 Action Node를 별도의 객체로 생성하거나, 만들어진 행동 트리의 최상위 노드를 Root 노드로 설정하여 엔티티에 AI를 부여하기 때문입니다. Action Node를 만들 때는 AIComponent의 `CreateNode()`, `CreateLeafNode()`를 활용해 Action Node를 생성할 수 있습니다. > **Tip** > Action N
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 이동 발판 만들기 [question] | RigidbodyMovementOption의 RelativeX와 Absolute의 차이를 2행 표로 정리하세요. [answer] | | 옵션 | 설명 | | :--- | :--- | | **RelativeX** | x축 관성만 적용하고 y축 관성은 적용하지 않습니다. 플레이어가 발판의 이동 방향과 반대로 움직이면 속도가 감속하고, 같은 방향으로 움직이면 가속합니다. | | **Absolute** | 플레이어가 어느 방향으로 움직여도 속도가 동일하게 적용됩니다. | [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 움직이는 발판을 만들어 이동에 재미를 더해보세요. CustomFootholdComponent의 IsDynamicFoothold 프로퍼티를 이용해 나만의 움직이는 발판을 만들 수 있습니다. [발판 만들기](/docs/?postId=71%7B%22target%22:%22_self%22%7D)에서 기본 발판 제작 방법을 배울 수 있습니다. # 이동 발판 만들기 이동 발판은 CustomFootholdComponent를 활용해 크리에이터가 직접 만들어야 합니다. 발판의 움직임을 만드는 방식은 다르지만, 기본 Cus
[task] | single_turn [pass] | ⏳ 미판정 [title] | 효과음 만들기 [question] | SoundComponent에서 HearingDistance 값을 10으로 설정했을 때 플레이어와 음원 사이의 거리 변화에 따른 소리 크기는 어떻게 변하나요? [answer] | 제공된 문서에는 `HearingDistance` 값을 10으로 설정했을 때, 플레이어와 음원 사이의 거리 변화에 따른 소리 크기의 구체적인 수치적 비율이나 감쇠 공식이 명시되어 있지 않습니다. 문서에서 확인할 수 있는 정보만으로는 다음 사항만 설명할 수 있습니다. 1. **`SetCameraAsListener` 활성화 시:** 화면 중앙(카메라)과 음원 사이의 거리에 따라 소리 크기가 조절됩니다. 2. **`HearingDistance`의 역할:** 예제 설정에서 `HearingDistance`가 10으로 지정되어 있으며, [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | **SetCameraAsListener** 프로퍼티를 활용하는 방법도 있습니다. **SoundComponent** 프로퍼티에서 설명했듯이 **SetCameraAsListener**를 활성화하면 화면 중앙과 음원 사이의 거리에 따라 소리 크기를 조절합니다. 간단하게 **SetCameraAsListener** 프로퍼티를 활용하는 방법을 살펴봅시다. 1. **Preset List**에서 아무 맵 오브젝트나 **Scene**에 배치한 뒤 **SpriteRendererComponent - SpriteRUID**에 아래의 **RUID**를
[task] | code [pass] | ⏳ 미판정 [title] | 효과음 만들기 [question] | SoundComponent의 AudioRUID와 Loop 프로퍼티를 설정하여 OnBeginPlay 시 재생을 시작하고, 5초 후 정지되도록 하는 스크립트를 작성해줘 [answer] | SoundComponent의 `AudioClipRUID`와 `Loop` 프로퍼티를 설정하여 `OnBeginPlay`에서 재생을 시작하고, 5초 후 정지하는 스크립트입니다. ```lua [client only] void OnBeginPlay() { self.Entity.SoundComponent.AudioClipRUID = "여기_음원_RUID_입력" self.Entity.SoundComponent.Loop = true self.Entity.SoundComponent:Play() wait(5) [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 월드를 입체적으로 만들기 위해 [**SoundComponent**](/apiReference/Components/SoundComponent)와 [**SoundService**](/apiReference/Services/SoundService)를 활용해 음원을 재생하고, 때에 맞게 제어하는 방법을 소개합니다. # SoundComponent 월드를 더욱 입체적으로 만들기 위해 다양한 소리가 이곳저곳에서 재생되게 만들거나, 플레이어와 특정 엔티티의 거리에 따라 다른 음량으로 들리게 만들 수 있습니다. **Soun
[task] | code [pass] | ⏳ 미판정 [title] | 행동 트리를 활용한 AI 만들기 [question] | BehaviourTreeStatus.Running 을 반환하는 동안 OnInit() 이 호출되지 않는 특성을 활용해 이동 중에는 초기화 로직이 재실행되지 않도록 보장하는 이동 액션 노드 스크립트를 작성해줘 [answer] | BehaviourTreeStatus.Running을 반환하는 동안 OnInit()이 호출되지 않는 특성을 활용하면, 이동 시작 시점(OnInit)에만 이동 방향과 시간을 결정하고, 이후 프레임에서는 OnBehave()만 호출되어 이동이 지속되도록 보장할 수 있습니다. 아래 스크립트는 랜덤한 방향으로 일정 시간 이동하는 액션 노드입니다. ```lua Property: [None] Vector2 MoveDirection = Vector2(0,0) [None] number MoveTime = 0 [None] number Elapsed [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 자식 노드가 Success 또는 Failure를 반환하면 부모 노드는 다음 자식 노드를 실행합니다. 그러나 자식 노드가 Running을 반환하면 부모 노드는 Running을 반환했던 자식 노드를 다음 프레임에 다시 실행합니다. 이 특성을 활용해 여러 프레임 동안 동작하는 노드를 만들 수 있습니다. 아래 그림과 같이 자식 노드 A, B, C가 있을 때 Sequence Node와 Selector Node의 경우 B 노드가 Running을 반환하는 동안 C 노드를 실행하지 않습니다. RandomSelector Node는 선택된 노드를 계
[task] | single_turn [pass] | ⏳ 미판정 [title] | 행동 트리를 활용한 AI 만들기 [question] | OnBehave 함수에서 delta 매개변수를 활용해 이동이나 시간 계산을 구현할 때 주의할 점이 있을까요? [answer] | `OnBehave(number delta)` 함수에서 `delta` 매개변수를 활용할 때 가장 중요한 점은 **`delta`가 프레임 간격(time step)을 나타낸다는 것**입니다. 이를 바탕으로 이동이나 시간 계산을 구현할 때 다음과 같은 사항에 주의해야 합니다. 1. **누적 시간 계산 시 `delta`를 더해야 합니다.** 특정 시간(예: 2초) 동안 동작을 유지하려면, 매 프레임마다 `delta`를 현재 누적 시간 변수에 더하는 방식으로 구현해야 합니다. 단순히 프레임 수를 세거나 고정 값을 더하면 화면 프레임 레 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 자식 노드가 Success 또는 Failure를 반환하면 부모 노드는 다음 자식 노드를 실행합니다. 그러나 자식 노드가 Running을 반환하면 부모 노드는 Running을 반환했던 자식 노드를 다음 프레임에 다시 실행합니다. 이 특성을 활용해 여러 프레임 동안 동작하는 노드를 만들 수 있습니다. 아래 그림과 같이 자식 노드 A, B, C가 있을 때 Sequence Node와 Selector Node의 경우 B 노드가 Running을 반환하는 동안 C 노드를 실행하지 않습니다. RandomSelector Node는 선택된 노드를 계
[task] | code [pass] | ⏳ 미판정 [title] | 카드와 UI 만들기 [question] | UI_Block_Group의 CellSize, Spacing, ConstraintCount 프로퍼티를 확인하고 해당 값에 맞춰 카드 간격을 동적으로 계산하는 로직을 포함하는 스크립트를 작성해줘 [answer] | UI_Block_Group에 적용된 프로퍼티 값은 다음과 같습니다. * **CellSize**: `90, 90` (카드의 너비와 높이가 90입니다.) * **Spacing**: `95, 50` (수평 간격 95, 수직 간격 50입니다.) * **ConstraintCount**: `6` (가로에 6개의 카드가 배치됩니다.) 이 값들을 바탕으로 카드의 실제 레이아웃 위치나 간격을 동적으로 계산하는 로직을 포함하는 스크립트를 작성합니다. `ScrollLayoutGroupComponent`가 자식 엔티티들을 자동으로 배치하기 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 이제 카드를 화면에 불러낼 차례입니다. 카드를 불러내기 위해선 **/ui/CardPairGameUI/UI_Board/UI_Blocks/UI_Block_Group**를 활용합니다. **UI_Block_Group**은 [ScrollLayoutGroupComponent](/apiReference?postId=382%7B%22target%22:%22_self%22%7D)를 활용했습니다. **ScollLayoutGroupComponent**는 여러 개의 엔티티를 펼쳐야할 때 사용합니다. 주로 상점이나, 인벤토리처럼 한 눈에 봐야하는 이미지
[task] | single_turn [pass] | ⏳ 미판정 [title] | 효과음 만들기 [question] | SoundComponent의 SetListenerEntity를 사용했는데, 플레이어가 텔레포트로 이동하면 음량이 즉시 0으로 떨어지는 현상을 원치 않을 경우 어떻게 설정해야 하나요? [answer] | 제공된 참고 문서에는 `SetListenerEntity()`를 사용할 때 플레이어가 텔레포트 등으로 이동하면 음량이 즉시 줄어든다는 현상만 설명되어 있을 뿐, 이를 방지하거나 변경하는 설정 방법이나 관련 API(프로퍼티, 메서드)에 대한 정보는 포함되어 있지 않습니다. 따라서 현재 문서 기준으로는 텔레포트 시 음량이 즉시 0으로 떨어지는 현상을 원치 않을 경우 적용할 수 있는 설정 방법은 안내드리기 어렵습니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 월드를 입체적으로 만들기 위해 [**SoundComponent**](/apiReference/Components/SoundComponent)와 [**SoundService**](/apiReference/Services/SoundService)를 활용해 음원을 재생하고, 때에 맞게 제어하는 방법을 소개합니다. # SoundComponent 월드를 더욱 입체적으로 만들기 위해 다양한 소리가 이곳저곳에서 재생되게 만들거나, 플레이어와 특정 엔티티의 거리에 따라 다른 음량으로 들리게 만들 수 있습니다. **Soun
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 효과음 만들기 [question] | SetCameraAsListener 활성화 시 소리가 조절되는 거리 기준과, SetListenerEntity 함수를 통해 리스너를 지정했을 때의 우선순위를 설명하되, 3문장 이내로 작성하세요. [answer] | `SetCameraAsListener`를 활성화하면 화면 중앙(카메라)과 음원 사이의 거리에 따라 소리 크기가 조절됩니다. 다만 `SetListenerEntity` 함수를 통해 특정 엔티티를 리스너로 지정해 둔 경우, 해당 지정한 엔티티가 우선적으로 리스너로 적용됩니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | **SetCameraAsListener** 프로퍼티를 활용하는 방법도 있습니다. **SoundComponent** 프로퍼티에서 설명했듯이 **SetCameraAsListener**를 활성화하면 화면 중앙과 음원 사이의 거리에 따라 소리 크기를 조절합니다. 간단하게 **SetCameraAsListener** 프로퍼티를 활용하는 방법을 살펴봅시다. 1. **Preset List**에서 아무 맵 오브젝트나 **Scene**에 배치한 뒤 **SpriteRendererComponent - SpriteRUID**에 아래의 **RUID**를
[task] | single_turn [pass] | ⏳ 미판정 [title] | 효과음 만들기 [question] | UI 버튼 클릭 시 효과음을 재생하려면 어떤 이벤트 핸들러와 함수를 조합해서 사용해야 하나요? [answer] | UI 버튼 클릭 시 효과음을 재생하려면 버튼에 **ButtonClickEvent** 이벤트 핸들러를 추가하고, 해당 핸들러 안에서 `_SoundService:PlaySound` 함수를 호출해야 합니다. 이때 주의할 점은 효과음 재생 로직은 클라이언트에서만 실행되어야 하므로 이벤트 핸들러의 실행 공간을 `[client only]`로 설정하는 것입니다. `_SoundService:PlaySound` 함수에는 재생할 음원의 `AudioClipRUID`와 음량을 인수로 전달합니다. 아래는 UI 버튼 클릭 시 효과음을 재생하는 스크립트 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | **SetCameraAsListener** 프로퍼티를 활용하는 방법도 있습니다. **SoundComponent** 프로퍼티에서 설명했듯이 **SetCameraAsListener**를 활성화하면 화면 중앙과 음원 사이의 거리에 따라 소리 크기를 조절합니다. 간단하게 **SetCameraAsListener** 프로퍼티를 활용하는 방법을 살펴봅시다. 1. **Preset List**에서 아무 맵 오브젝트나 **Scene**에 배치한 뒤 **SpriteRendererComponent - SpriteRUID**에 아래의 **RUID**를
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 이동 발판 만들기 [question] | 대각선으로 이동하는 발판 스크립트에서 TransformComponent:Translate 호출 시 x와 y 값을 모두 입력하는 코드를 주석 없이 출력하세요. [answer] | ```lua Property: [Sync] number totalTime = 0 Method: [Server only] void OnUpdate(number delta) { self.totalTime = self.totalTime + delta if self.totalTime > 0 and self.totalTime <= 5.0 then self.Entity.TransformComponent:Translate(0.009, 0.009) elseif self.totalTime > 5.0 and se [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 움직이는 발판을 만들어 이동에 재미를 더해보세요. CustomFootholdComponent의 IsDynamicFoothold 프로퍼티를 이용해 나만의 움직이는 발판을 만들 수 있습니다. [발판 만들기](/docs/?postId=71%7B%22target%22:%22_self%22%7D)에서 기본 발판 제작 방법을 배울 수 있습니다. # 이동 발판 만들기 이동 발판은 CustomFootholdComponent를 활용해 크리에이터가 직접 만들어야 합니다. 발판의 움직임을 만드는 방식은 다르지만, 기본 Cus
[task] | single_turn [pass] | ⏳ 미판정 [title] | 효과음 만들기 [question] | 기본 공격 스킬에 효과음을 붙이려면 어떤 컴포넌트를 생성하여 어디에 추가해야 하나요? [answer] | 기본 공격 스킬에 효과음을 추가하려면 **SkillSound** 스크립트 컴포넌트를 생성하여 **DefaultPlayer**에 추가해야 합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 기본 공격 스킬에 이펙트 스킬과 효과음을 추가해 역동적으로 연출할 수 있습니다. 1. **MyDesk**에 새로운 **SkillSound** 스크립트 컴포넌트를 생성하고, **DefaultPlayer**에 추가합니다. 2. 이벤트 핸들러에 **KeyDownEvent**를 추가하고 아래와 같이 내용을 작성합니다. ```lua Event Handler: [clinet only] [service: InputService] HandleKeyDownEvent(KeyDownEvent event) { -- Parameters l
[task] | single_turn [pass] | ⏳ 미판정 [title] | 행동 트리를 활용한 AI 만들기 [question] | 스크립트로 행동 트리를 직접 만들 때 Action Node를 생성하는 구체적인 코드 문법은 어떻게 되나요? [answer] | 행동 트리(Behaviour Tree)에서 Action Node를 스크립트로 직접 생성할 때는 `AIComponent`의 `CreateNode()` 또는 `CreateLeafNode()` 메서드를 사용합니다. 이 두 메서드는 노드의 복잡도와 목적에 따라 선택됩니다. ### 1. CreateLeafNode() 사용 (단순 액션 노드 생성) 구체적인 로직(함수)을 직접 전달하여 가장 단순한 형태의 Action Node를 만들 때 사용합니다. BTNodeType을 지정할 필요가 없습니다. * **매개변수:** 1. 노드 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | AI로 사용할 엔티티에는 **AIComponent 또는 확장한 AIComponent**가 포함되어 있어야 합니다. AIComponent는 BTNodeType에서 정의된 내용으로 Action Node를 별도의 객체로 생성하거나, 만들어진 행동 트리의 최상위 노드를 Root 노드로 설정하여 엔티티에 AI를 부여하기 때문입니다. Action Node를 만들 때는 AIComponent의 `CreateNode()`, `CreateLeafNode()`를 활용해 Action Node를 생성할 수 있습니다. > **Tip** > Action N
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 효과음 만들기 [question] | UI 버튼 클릭 시 효과음을 재생하는 mLua 스크립트 컴포넌트 코드를 출력하되, 설명은 주석으로만 작성하고 코드 블록 밖에는 아무 텍스트도 쓰지 마세요. [answer] | ```lua Event Handler: [client only] HandleButtonClickEvent(ButtonClickEvent event) { -- UI 버튼 클릭 시 효과음 재생 _SoundService:PlaySound("21600ec9d3a04cfeb69c6fe0c50e197c",1) } ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | **SetCameraAsListener** 프로퍼티를 활용하는 방법도 있습니다. **SoundComponent** 프로퍼티에서 설명했듯이 **SetCameraAsListener**를 활성화하면 화면 중앙과 음원 사이의 거리에 따라 소리 크기를 조절합니다. 간단하게 **SetCameraAsListener** 프로퍼티를 활용하는 방법을 살펴봅시다. 1. **Preset List**에서 아무 맵 오브젝트나 **Scene**에 배치한 뒤 **SpriteRendererComponent - SpriteRUID**에 아래의 **RUID**를
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 효과음 만들기 [question] | 문서에 제시된 망치질 효과음 예시의 SoundComponent 프로퍼티 설정값을 '프로퍼티'와 '값' 두 개의 열을 가진 표로 정리하세요. [answer] | ```markdown | 프로퍼티 | 값 | |---|---| | AudioClipRUID | 74222ba4b41d48dd97175fd691124a67 | | HearingDistance | 10 | | PlayOnEnable | true | | SetCameraAsListener | true | | Loop | true | ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | **SetCameraAsListener** 프로퍼티를 활용하는 방법도 있습니다. **SoundComponent** 프로퍼티에서 설명했듯이 **SetCameraAsListener**를 활성화하면 화면 중앙과 음원 사이의 거리에 따라 소리 크기를 조절합니다. 간단하게 **SetCameraAsListener** 프로퍼티를 활용하는 방법을 살펴봅시다. 1. **Preset List**에서 아무 맵 오브젝트나 **Scene**에 배치한 뒤 **SpriteRendererComponent - SpriteRUID**에 아래의 **RUID**를