[task] | single_turn [pass] | ⏳ 미판정 [title] | 발판 만들기 [question] | FootholdDrag 값이 10인 발판과 1인 발판에서 엔티티가 멈추는 거리가 어떻게 달라지나요? [answer] | FootholdDrag 값이 클수록 엔티티가 발판에서 미끄러지는 거리가 짧아집니다. 구체적으로, 특정 지점에서 날아온 엔티티가 FootholdDrag 값이 1인 발판과 10인 발판에 각각 떨어졌을 때, 값이 10인 발판에서는 상대적으로 더 짧은 거리로 밀려난 후 정지하게 됩니다. 이는 FootholdDrag가 발판 위에서 적용되는 마찰력을 의미하며, 이 값이 커질수록 엔티티가 빠르게 감속해 멈추기 때문입니다. 참고로, 플레이어가 기본 이동(걷기)을 할 때는 이 값의 영향이 미미하여 플레이 중에는 눈에 띄지 않는 경우가 많습니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 새롭게 만든 발판에 속성을 바꿔 크리에이터만의 독특한 발판으로 만들 수 있습니다. 각 프로퍼티 값을 조정해 특정 방향에서 나아갈 수 없는 발판, 특별히 느리게 이동하는 발판 등으로 활용해 재미를 더할 수 있습니다. | 이름 | 설명 | | --- | --- | | FootholdDrag | RigidbodyComponent가 포함된 Entity가 발판 위에 있을 때 적용되는 마찰력을 의미합니다. 값이 클수록 엔티티가 발판에서 미끌어지다 빠르게 감속해 정지합니다. 특정 지점에서 엔티티가 날아와 해당 값이 1과 10인 발판에 각각
[task] | two_turn [pass] | ⏳ 미판정 [title] | 발판 만들기 [question] | FootholdComponent와 CustomFootholdComponent의 주요 차이점과 용도는 무엇인가요? [answer] | FootholdComponent와 CustomFootholdComponent는 모두 발판(Foothold)과 관련된 컴포넌트이지만, 개념과 용도가 명확히 다릅니다. **1. FootholdComponent** * **용도**: 맵 전체의 발판 정보를 저장하고 제공하는 역할을 합니다. * **특징**: 프로퍼티 에디터에서 검색 시 값은 확인될 수 있지만, 직접적으로 값을 수정하거나 조작하여 이용할 수 있는 컴포넌트가 아닙니다. 주로 시스템 내부적으로 맵의 발판 데이터를 관리하는 데 사용됩니다. **2. CustomFooth [followup] | CustomFootholdComponent의 edgeLists와 Size 프로퍼티를 설정하여 직선형 발판 경로를 만드는 구체적인 코드 예시를 보여주세요. [followup_answer] | 참고 문서에 제시된 mLua 코드 예시를 바탕으로, `CustomFootholdComponent`의 `edgeLists`와 `Size` 프로퍼티를 설정하여 직선형 발판 경로를 만드는 구체적인 코드는 다음과 같습니다. 발판의 좌표를 수정할 때는 기존 요소의 값을 단순히 수정하는 것이 아니라, 새로운 리스트(List)를 만들어 해당 인덱스에 덮어써야 변경 사항이 발판에 적용됩니다. ```lua -- 목표 엔티티 경로 (실제 엔티티 경로로 변경해야 합니다) local EntityPath = "/maps/map01/foothold_en [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 여러 오브젝트를 사용해 발판을 만들어 게임의 보는 재미를 풍성하게 만들어봅시다. **FootholdComponent**와 **CustomFootholdComponent** 개념과 발판 편집 방법을 소개합니다. # Foothold 모델로 발판 만들기 **Foothold** 모델을 이용해 발판을 만드는 방법입니다. 타일이 아닌 **Foothold** 모델을 이용해 다채로운 길을 만들 수 있습니다. 1. **Preset List** 패널에서 **Foothold**를 선택합니다. 2. 원하는 모델을 선택해 **S
[task] | instruction_following [pass] | ⏳ 미판정 [title] | Event System [question] | 일반 로직과 이벤트 시스템의 차이점을 3문장 이내로 설명해 주세요. [answer] | 일반 로직에서는 행위가 일어난 주체가 직접 후속 작업을 처리하지만, 이벤트 시스템에서는 주체가 상황만 전달하고 행동 실행 주체가 이를 구독하여 처리합니다. 이러한 구조는 다른 컴포넌트에 대한 의존성을 줄여 분산된 구조를 만들기 유리합니다. 반면, 전체적인 흐름 파악이 어려워지고 디버깅이 다소 복잡해질 수 있다는 단점이 있습니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 크리에이터는 로직을 여러 가지 방법으로 작성할 수 있습니다. 그 방법 중 하나는 **이벤트**를 활용하는 것입니다. 이번 시간에는 메이플스토리 월드의 이벤트 시스템과 여러 이벤트를 다루는 방법을 살펴봅니다. # 이벤트 기반의 로직 구성 로직을 작성하다 보면 **특정 타이밍에 해야 할 일**이 생깁니다. 그럴 때는 **행위가 일어난 주체**가 무엇을 할 것인지 결정해야 합니다. 예를 들어, 월드에서 캐릭터가 공격받았을 때 아래와 같이 구현한다고 가정해 봅시다. 1. **캐릭터의 HP를 감소시키고** 2.
[task] | instruction_following [pass] | ⏳ 미판정 [title] | Event System [question] | 이벤트 시스템의 장점과 단점을 각각 2개씩만 단계별 번호 목록으로 나열해 주세요. [answer] | 이벤트 시스템의 장점과 단점은 다음과 같습니다. **장점** 1. 다른 컴포넌트나 기능에 의존적이지 않아 분산된 구조를 만드는 데 유리합니다. 2. 행위가 일어난 주체는 수정하지 않고 행위에 대한 액션만 추가할 수 있습니다. **단점** 1. 어떤 사건이 발생했을 때 전체적인 흐름을 파악하기 어렵습니다. 2. 디버깅이 다소 어려울 수 있습니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 크리에이터는 로직을 여러 가지 방법으로 작성할 수 있습니다. 그 방법 중 하나는 **이벤트**를 활용하는 것입니다. 이번 시간에는 메이플스토리 월드의 이벤트 시스템과 여러 이벤트를 다루는 방법을 살펴봅니다. # 이벤트 기반의 로직 구성 로직을 작성하다 보면 **특정 타이밍에 해야 할 일**이 생깁니다. 그럴 때는 **행위가 일어난 주체**가 무엇을 할 것인지 결정해야 합니다. 예를 들어, 월드에서 캐릭터가 공격받았을 때 아래와 같이 구현한다고 가정해 봅시다. 1. **캐릭터의 HP를 감소시키고** 2.
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 스킬 이펙트를 뿌려보자! [question] | 제시된 `HandleKeyDownEvent` 코드 블록만 출력하고, 각 키(Q, W, E, R)별 이펙트 ID는 주석으로만 표기하세요. [answer] | ```lua [service: InputService] HandleKeyDownEvent(KeyDownEvent event) { -- Parameters local key = event.key -------------------------------------------------------- if key == KeyboardKey.Q then -- 이펙트 ID: f396262ddb6e4d5581360496bb4e9f86 _EffectService:PlayEffectAtta [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 위에서 살펴본 이펙트 호출 방법은 사실 스킬 이펙트에 적합한 방법은 아닙니다. 위의 예제처럼 구현하면 Q, W, E, R 키를 누른 후 캐릭터를 이동할 때 캐릭터가 이펙트를 벗어나 이동하게 됩니다. `PlayEffect`는 위에서 잠깐 언급한 것처럼 고정된 위치에 이펙트를 호출하는데 적합한 함수이기 때문에 버프류 스킬과 같이 항상 캐릭터 위에 떠 있어야 할 이펙트에는 적합하지 않습니다. 따라서 이러한 경우에 사용하는 함수가 바로 `PlayEffectAttached` 함수입니다. `PlayEffectAttached`의 경우 이펙트가
[task] | code [pass] | ⏳ 미판정 [title] | 아이템 생성 및 삭제 [question] | 아이템 획득 후 self.Entity:SetEnable(false)를 호출하여 현재 엔티티를 비활성화하고, _TimerService:SetTimerOnce를 통해 5초 뒤에 _EntityService:GetEntityByPath(self.Entity.Path)로 엔티티를 다시 검색하여 SetEnable(true)로 재활성화하는 로직을 포함하는 GiftBox 스크립트를 작성해줘. [answer] | 요청하신 로직을 포함하는 **GiftBox** 스크립트 컴포넌트를 작성했습니다. 1. **TriggerEnterEvent** 핸들러를 통해 캐릭터가 아이템에 닿으면 트리거됩니다. 2. 충돌한 엔티티(`TriggerBodyEntity`)의 `InventoryComponent`를 확인하고, 없으면 처리를 중단합니다. 3. 정의된 아이템 목록에서 랜덤으로 하나를 선택하여 `_ItemService:CreateItem`으로 인벤토리에 추가합니다. 4. 즉시 `self.Entity:SetEnable(false)`를 호출하여 아이템 엔 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 이번에는 생성된 아이템을 표시할 인벤토리 UI를 추가합니다. 상단 메뉴에 버튼을 눌러 UI 에디터를 엽니다. **Preset List**에서 **[인벤토리]**, **[버튼모음]** UI를 추가합니다. 만일 **Inventory** 엔티티의 **UIInventory** 컴포넌트에 **InventoryBtnPath**가 비어있으면, 햄버거 메뉴를 열어 **Reset All Properties**를 선택합니다. 그러면 아래와 같이 정상적인 경로가 설정됩니다. # 아이템 엔티티 배치 및 기능 추가 버튼을 눌러 UI 편집모드를
[task] | two_turn [pass] | ⏳ 미판정 [title] | 스킬 이펙트를 뿌려보자! [question] | `PlayEffect`와 `PlayEffectAttached` 함수의 주요 차이점과 각각 어떤 상황에서 사용해야 하는지 설명해 주세요 [answer] | `PlayEffect`와 `PlayEffectAttached` 함수의 주요 차이점과 적절한 사용 상황은 다음과 같습니다. ### 1. 주요 차이점 * **고정된 위치 vs. 엔티티 부착** * `PlayEffect`: 이펙트를 **고정된 위치**에 생성합니다. 호출 시점에 지정된 좌표에 이펙트가 생성되며, 이후 캐릭터가 이동하더라도 이펙트는 원래 생성된 위치에 그대로 남아 있습니다. * `PlayEffectAttached`: 이펙트를 특정 **엔티티(부모)에 부착**하여 생성합니다. 이펙트는 지정된 부모 [followup] | `PlayEffectAttached`에서 부모 엔티티로 `self.Entity`를 지정할 때, 이펙트가 캐릭터의 로컬 좌표계 기준 어디에 위치하게 되는지 `Vector3(0,0,0)` 인자의 의미를 구체적으로 알려 주세요 [followup_answer] | 제공된 참고 문서에는 `PlayEffectAttached` 함수의 세 번째 인자로 전달되는 `Vector3` 값이 **이펙트가 떠 있을 대상 엔티티(부모 엔티티)를 기준으로 한 위치**를 의미한다는 사실만 명시되어 있습니다. 문서에서 구체적으로 `Vector3(0,0,0)`이 캐릭터의 로컬 좌표계 기준 어디(예: 발밑, 중심, 머리 위 등)에 해당한다고 정의한 내용은 포함되어 있지 않습니다. 따라서 `Vector3(0,0,0)` 인자가 캐릭터의 어떤 특정 물리적 지점(오리진)을 가리키는지, 혹은 로컬 오프셋으로서의 정확한 수학적 [scores] | [judge_reason] | [source_doc] | 위에서 살펴본 이펙트 호출 방법은 사실 스킬 이펙트에 적합한 방법은 아닙니다. 위의 예제처럼 구현하면 Q, W, E, R 키를 누른 후 캐릭터를 이동할 때 캐릭터가 이펙트를 벗어나 이동하게 됩니다. `PlayEffect`는 위에서 잠깐 언급한 것처럼 고정된 위치에 이펙트를 호출하는데 적합한 함수이기 때문에 버프류 스킬과 같이 항상 캐릭터 위에 떠 있어야 할 이펙트에는 적합하지 않습니다. 따라서 이러한 경우에 사용하는 함수가 바로 `PlayEffectAttached` 함수입니다. `PlayEffectAttached`의 경우 이펙트가
[task] | instruction_following [pass] | ⏳ 미판정 [title] | Event System [question] | 이벤트 시스템의 3가지 구성 요소와 그 유사 용어를 표로 정리해서 답변해 주세요. [answer] | 메이플스토리 월드의 이벤트 시스템은 크게 3가지 요소로 구성되며, 각 요소에 대한 설명과 유사 용어는 다음과 같습니다. | 요소 | 설명 | 유사 용어 | | :--- | :--- | :--- | | 이벤트(Event) | 로직 상에서 어떤 사건의 발생을 의미하며, 이벤트 종류의 식별 정보 및 추가 정보 등을 들고 있는 자료형입니다. | - | | 핸들러(Handler) | 이벤트를 받았을 때 처리하는 행동의 주체입니다. | Listener, Subscriber | | 센더(Sender) | 이벤트를 발송하는 객체입니다. | Em [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 크리에이터는 로직을 여러 가지 방법으로 작성할 수 있습니다. 그 방법 중 하나는 **이벤트**를 활용하는 것입니다. 이번 시간에는 메이플스토리 월드의 이벤트 시스템과 여러 이벤트를 다루는 방법을 살펴봅니다. # 이벤트 기반의 로직 구성 로직을 작성하다 보면 **특정 타이밍에 해야 할 일**이 생깁니다. 그럴 때는 **행위가 일어난 주체**가 무엇을 할 것인지 결정해야 합니다. 예를 들어, 월드에서 캐릭터가 공격받았을 때 아래와 같이 구현한다고 가정해 봅시다. 1. **캐릭터의 HP를 감소시키고** 2.
[task] | single_turn [pass] | ⏳ 미판정 [title] | 발판 만들기 [question] | 발판을 이을 때 시작점을 하나로 만드는 것과 여러 개로 나누는 것의 차이가 무엇인가요? [answer] | 발판을 이을 때 시작점을 하나로 만드는 것과 여러 개로 나누는 것의 차이는 발판의 연결 방식과 형태에 있습니다. * **시작점을 하나로 만드는 경우:** 하나의 연속된 경로로 발판이 이어지는 형태를 만들 수 있습니다. 이는 여러 조각의 발판을 자연스럽게 연결하여 긴 이동 경로를 구성할 때 적합합니다. * **시작점을 여러 개로 나누는 경우:** 서로 독립적이거나 분기되는 여러 개의 발판 경로를 만들 수 있습니다. 이는 하나의 지점에서 여러 방향으로 갈 수 있는 구조나, 서로 떨어져 있는 여러 발판들을 개별적으로 배치할 때 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 새롭게 만든 발판에 속성을 바꿔 크리에이터만의 독특한 발판으로 만들 수 있습니다. 각 프로퍼티 값을 조정해 특정 방향에서 나아갈 수 없는 발판, 특별히 느리게 이동하는 발판 등으로 활용해 재미를 더할 수 있습니다. | 이름 | 설명 | | --- | --- | | FootholdDrag | RigidbodyComponent가 포함된 Entity가 발판 위에 있을 때 적용되는 마찰력을 의미합니다. 값이 클수록 엔티티가 발판에서 미끌어지다 빠르게 감속해 정지합니다. 특정 지점에서 엔티티가 날아와 해당 값이 1과 10인 발판에 각각
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 플레이어 카메라 제어 [question] | UseCustomBound가 True일 때 카메라 제한 영역을 시각적으로 확인하고 조절하는 방법을 2문장 이내로 설명하세요. [answer] | Collider Edit 버튼을 누르면 Scene에 기즈모가 표시되어 카메라 제한 영역을 시각적으로 확인할 수 있습니다. 이후 핸들러를 통해 영역을 손쉽게 조절할 수 있습니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 카메라 제한 영역을 직접 정의해서 사용할 지 여부를 설정합니다. **UseCustomBound** 값이 **True**라면 **LeftBottom, RightTop** 프로퍼티를 사용해 카메라 제한 영역을 정의할 수 있습니다. **Collider Edit** 버튼을 누르면 Scene에 표시되는 기즈모를 통해 카메라 제한 영역을 시각적으로 확인하거나 핸들러를 통해 손쉽게 영역을 조절할 수 있습니다. CameraComponent - UseCustomBound 값이 **False**라면 맵 영역을 카메라 제한 영역으로 사용합니다. 맵
[task] | single_turn [pass] | ⏳ 미판정 [title] | 스킬 이펙트를 뿌려보자! [question] | PlayEffectAttached를 호출할 때 부모 엔티티로 self.Entity를 지정하면 이펙트가 캐릭터에 부착되는 원리가 무엇인가요? [answer] | `PlayEffectAttached` 함수는 일반 이펙트 호출 함수인 `PlayEffect`와 달리, 이펙트가 고정된 공간 좌표에 생성되는 것이 아니라 **지정된 엔티티(부모)에 부착(attach)** 되어 생성됩니다. 질문하신 `self.Entity`를 부모 엔티티로 지정했을 때의 원리는 다음과 같습니다. 1. **부모-자식 관계 형성:** `PlayEffectAttached`를 통해 생성된 이펙트 엔티티는 `self.Entity`(즉, 스크립트가 붙어 있는 캐릭터 엔티티)의 자식 엔티티가 됩니다. 2. **위치 및 회전 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 위에서 살펴본 이펙트 호출 방법은 사실 스킬 이펙트에 적합한 방법은 아닙니다. 위의 예제처럼 구현하면 Q, W, E, R 키를 누른 후 캐릭터를 이동할 때 캐릭터가 이펙트를 벗어나 이동하게 됩니다. `PlayEffect`는 위에서 잠깐 언급한 것처럼 고정된 위치에 이펙트를 호출하는데 적합한 함수이기 때문에 버프류 스킬과 같이 항상 캐릭터 위에 떠 있어야 할 이펙트에는 적합하지 않습니다. 따라서 이러한 경우에 사용하는 함수가 바로 `PlayEffectAttached` 함수입니다. `PlayEffectAttached`의 경우 이펙트가
[task] | single_turn [pass] | ⏳ 미판정 [title] | 플레이어 카메라 제어 [question] | isAllowZoomInOut이 True일 때 플레이어는 어떤 조작으로 화면 줌을 변경할 수 있나요? [answer] | `isAllowZoomInOut`이 True로 설정되어 있으면, 플레이어는 마우스 휠을 위쪽 또는 아래쪽으로 이동시켜 화면을 줌 인/아웃할 수 있습니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 게임의 메인 카메라는 항상 플레이어를 따라다닙니다. 메인 카메라를 제어하는 camera 컴포넌트는 MapleStoryPlayer 모델이 가지고 있으며 이 모델의 프로퍼티 에디터나 스크립트를 이용해 주요 값을 수정할 수 있습니다. 이번 과정에서는 Camera 컴포넌트를 프로퍼티 에디터를 통해 수정해보며 전반적인 기능을 알아보는 시간을 가져보도록 하겠습니다. # Camera 컴포넌트 접근 Workspace에서 DefaultPlayer 모델을 선택합니다. 프로퍼티 에디터에서 CameraComponent를 확인
[task] | single_turn [pass] | ⏳ 미판정 [title] | 스킬 이펙트를 뿌려보자! [question] | 이펙트 ID를 잘못 입력하거나 파라미터 순서가 틀리면 어떤 오류가 발생하며, 이펙트가 안 나올 때 먼저 확인해야 할 항목은 무엇인가요? [answer] | 제공된 참고 문서에는 `PlayEffectAttached` 함수의 파라미터 순서나 잘못된 ID 입력 시 발생하는 구체적인 오류 메시지, 그리고 디버깅 시 체크리스트가 명시되어 있지 않습니다. 문서에서 확인할 수 있는 정보는 다음과 같습니다. 1. **함수 선택의 중요성**: 캐릭터와 함께 이동해야 하는 이펙트(버프류 등)에는 고정된 위치에 이펙트를 호출하는 `PlayEffect` 대신, 부모 엔티티를 지정할 수 있는 `PlayEffectAttached`를 사용해야 합니다. `PlayEffect`를 사용하면 캐릭터 이동 시 이펙 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 위에서 살펴본 이펙트 호출 방법은 사실 스킬 이펙트에 적합한 방법은 아닙니다. 위의 예제처럼 구현하면 Q, W, E, R 키를 누른 후 캐릭터를 이동할 때 캐릭터가 이펙트를 벗어나 이동하게 됩니다. `PlayEffect`는 위에서 잠깐 언급한 것처럼 고정된 위치에 이펙트를 호출하는데 적합한 함수이기 때문에 버프류 스킬과 같이 항상 캐릭터 위에 떠 있어야 할 이펙트에는 적합하지 않습니다. 따라서 이러한 경우에 사용하는 함수가 바로 `PlayEffectAttached` 함수입니다. `PlayEffectAttached`의 경우 이펙트가
[task] | single_turn [pass] | ⏳ 미판정 [title] | 스킬 이펙트를 뿌려보자! [question] | EffectService에서 PlayEffect와 PlayEffectAttached 함수의 가장 큰 차이점과 각각 어떤 상황에 적합하게 사용해야 하는지 알고 싶습니다. [answer] | `_EffectService`의 `PlayEffect`와 `PlayEffectAttached` 함수의 가장 큰 차이점은 **이펙트의 위치 기준점과 엔티티와의 관계**입니다. ### 1. 핵심 차이점 * **PlayEffect**: * **절대 위치 기반**: 맵의 좌표계(`position`)에서 직접 지정된 위치에 이펙트를 생성합니다. * **독립 존재**: 생성된 이펙트는 특정 엔티티의 자식으로 연결되지 않으며, 지정된 좌표에 고정됩니다. * **매개변수**: `instigator`는 맵 정 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 메이플스토리에서 사용되었던 수많은 이펙트 리소스들을 제공하고 있습니다. 그리고 우리는 이러한 이펙트들을 적절한 시점과 위치에 호출해 줌으로써 한층 더 멋진 연출을 구사할 수 있습니다. 이번 과정에서는 특정 키를 누를 때마다 스킬 이펙트가 노출되는 예제를 진행해봄으로써 스크립트를 통해 이펙트를 호출하는 방법에 대해 알아보도록 합니다. 다음 가이드를 먼저 학습하면 이번 과정을 진행하는 데 많은 도움이 될 것입니다. [스크립트 에디터 오리엔테이션](https://mod-developers.
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 플레이어 카메라 제어 [question] | 카메라 제한 영역을 직접 정의할 때 사용되는 프로퍼티 이름과 편집 버튼 이름을 나열하되, 각 항목 뒤에는 해당 프로퍼티가 적용되는 조건(UseCustomBound 값)을 괄호 안에 표기하세요. [answer] | 카메라 제한 영역을 직접 정의할 때 사용되는 프로퍼티와 편집 버튼은 다음과 같습니다. * **LeftBottom** (CameraComponent - UseCustomBound가 True일 때) * **RightTop** (CameraComponent - UseCustomBound가 True일 때) * **Collider Edit** (CameraComponent - UseCustomBound가 True일 때) [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 카메라 제한 영역을 직접 정의해서 사용할 지 여부를 설정합니다. **UseCustomBound** 값이 **True**라면 **LeftBottom, RightTop** 프로퍼티를 사용해 카메라 제한 영역을 정의할 수 있습니다. **Collider Edit** 버튼을 누르면 Scene에 표시되는 기즈모를 통해 카메라 제한 영역을 시각적으로 확인하거나 핸들러를 통해 손쉽게 영역을 조절할 수 있습니다. CameraComponent - UseCustomBound 값이 **False**라면 맵 영역을 카메라 제한 영역으로 사용합니다. 맵
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 플레이어 카메라 제어 [question] | CameraComponent와 MapComponent의 UseCustomBound 설정 조합에 따른 카메라 제한 영역 결정 방식을 3행 표로 정리하세요. [answer] | | CameraComponent - UseCustomBound | MapComponent - UseCustomBound | 카메라 제한 영역 | | :--- | :--- | :--- | | **True** | (무관) | 크리에이터가 정의한 카메라 제한 영역 사용 | | **False** | **True** | 크리에이터가 정의한 맵 영역을 카메라 제한 영역으로 사용 | | **False** | **False** | 기본 맵 영역을 바탕으로 보정된 영역을 카메라 제한 영역으로 사용 | [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 카메라 제한 영역을 직접 정의해서 사용할 지 여부를 설정합니다. **UseCustomBound** 값이 **True**라면 **LeftBottom, RightTop** 프로퍼티를 사용해 카메라 제한 영역을 정의할 수 있습니다. **Collider Edit** 버튼을 누르면 Scene에 표시되는 기즈모를 통해 카메라 제한 영역을 시각적으로 확인하거나 핸들러를 통해 손쉽게 영역을 조절할 수 있습니다. CameraComponent - UseCustomBound 값이 **False**라면 맵 영역을 카메라 제한 영역으로 사용합니다. 맵
[task] | code [pass] | ⏳ 미판정 [title] | 아이템 생성 및 삭제 [question] | GiftBox 스크립트에서 _UtilLogic:RandomIntegerRange(1,5)를 호출하여 랜덤 인덱스를 구하고, itemNames 테이블에서 해당 인덱스의 아이템 이름과 타입을 추출한 뒤 _ItemService:CreateItem을 사용해 충돌한 엔티티의 InventoryComponent에 아이템을 추가하는 HandleTriggerEnterEvent를 작성해줘. [answer] | GiftBox 스크립트에서 필요한 로직은 `HandleTriggerEnterEvent` 이벤트 핸들러 내에 구현됩니다. 충돌한 엔티티의 인벤토리를 확인하고, 준비된 아이템 목록에서 랜덤으로 하나를 선택하여 `_ItemService:CreateItem` 메서드를 통해 인벤토리에 추가하는 순서로 진행합니다. 아래는 요청하신 기능을 포함하여, 충돌 후 아이템 엔티티를 숨기고 5초 후 다시 보이도록 예약하는 전체 로직이 포함된 `GiftBox` 스크립트 컴포넌트입니다. ```lua Event Handler: [self] HandleTr [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 이번에는 생성된 아이템을 표시할 인벤토리 UI를 추가합니다. 상단 메뉴에 버튼을 눌러 UI 에디터를 엽니다. **Preset List**에서 **[인벤토리]**, **[버튼모음]** UI를 추가합니다. 만일 **Inventory** 엔티티의 **UIInventory** 컴포넌트에 **InventoryBtnPath**가 비어있으면, 햄버거 메뉴를 열어 **Reset All Properties**를 선택합니다. 그러면 아래와 같이 정상적인 경로가 설정됩니다. # 아이템 엔티티 배치 및 기능 추가 버튼을 눌러 UI 편집모드를
[task] | two_turn [pass] | ⏳ 미판정 [title] | 발판 만들기 [question] | CustomFootholdComponent에서 edgeLists의 Size 값을 1로 설정할 때 연결점이 어떻게 생성되고 조정되나요? [answer] | `CustomFootholdComponent`의 `edgeLists`에서 `Size` 값을 1로 설정하면, 발판의 **시작점**이 1개 생성됩니다. 이때 연결점이 생성되고 조정되는 과정은 다음과 같습니다. 1. **시작점 생성**: `edgeLists`의 `Size`에 1을 입력하면, 발판 경로의 시작점이 1개 만들어집니다. 2. **연결점 개수 설정**: 해당 시작점(예: `[1]`) 안의 `Size` 값을 설정합니다. 이 값은 그 시작점에서 이어지는 **연결점의 개수**를 의미합니다. 3. **연결점 추가 및 위치 조정 [followup] | Scene 패널에서 Add Point를 통해 연결점을 추가한 후, x, y 좌표를 직접 코드로 수정하여 발판의 기울기를 변경하는 방법은 무엇인가요? [followup_answer] | `Scene` 패널에서 `Add Point`를 통해 연결점을 추가한 후, 코드로 x, y 좌표를 수정하여 발판의 기울기를 변경하려면 `CustomFootholdComponent`의 `edgeLists` 프로퍼티에 접근해야 합니다. 참고 문서에 따르면, 발판 경로의 개별 요소 값을 직접 수정하면(예: `target.CustomFootholdComponent.edgeLists[1][1] = Vector2(3, 0)`), 변경 사항이 발판에 적용되지 않습니다. 반드시 **새로운 리스트를 만들어 기존 값을 덮어써야** 변경 사항이 반영됩 [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 여러 오브젝트를 사용해 발판을 만들어 게임의 보는 재미를 풍성하게 만들어봅시다. **FootholdComponent**와 **CustomFootholdComponent** 개념과 발판 편집 방법을 소개합니다. # Foothold 모델로 발판 만들기 **Foothold** 모델을 이용해 발판을 만드는 방법입니다. 타일이 아닌 **Foothold** 모델을 이용해 다채로운 길을 만들 수 있습니다. 1. **Preset List** 패널에서 **Foothold**를 선택합니다. 2. 원하는 모델을 선택해 **S
[task] | single_turn [pass] | ⏳ 미판정 [title] | 플레이어 카메라 제어 [question] | Screen Offset에서 0.5와 0.8을 입력했을 때 플레이어 아바타가 화면에 어떻게 배치되는지 설명해 주세요. [answer] | Screen Offset은 플레이어 아바타가 화면 전체 내에서 어떤 비율의 위치에 비추어질지를 결정하는 값입니다. 이 값은 0부터 1 사이를 사용하며, 0.5는 화면의 정중앙을 의미합니다. 따라서 각 값이 입력되었을 때의 배치 상태는 다음과 같습니다: * **0.5 입력 시**: 카메라가 중앙에 위치하여 플레이어 아바타가 화면의 **정중앙**에 배치됩니다. * **0.8 입력 시**: X 값으로 0.8을 설정하면 플레이어 아바타가 화면의 **오른쪽**에 위치하게 됩니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 게임의 메인 카메라는 항상 플레이어를 따라다닙니다. 메인 카메라를 제어하는 camera 컴포넌트는 MapleStoryPlayer 모델이 가지고 있으며 이 모델의 프로퍼티 에디터나 스크립트를 이용해 주요 값을 수정할 수 있습니다. 이번 과정에서는 Camera 컴포넌트를 프로퍼티 에디터를 통해 수정해보며 전반적인 기능을 알아보는 시간을 가져보도록 하겠습니다. # Camera 컴포넌트 접근 Workspace에서 DefaultPlayer 모델을 선택합니다. 프로퍼티 에디터에서 CameraComponent를 확인
[task] | single_turn [pass] | ⏳ 미판정 [title] | 플레이어 카메라 제어 [question] | Damping 값을 너무 높게 설정하면 발생할 수 있는 문제점과 그에 따른 조정을 어떻게 해야 하나요? [answer] | Damping 값을 너무 높게 설정하면 카메라가 플레이어 아바타를 추적하는 속도가 극단적으로 느려집니다. 이로 인해 플레이어 아바타가 카메라의 시야에서 이탈하는 상황이 발생할 수 있습니다. 이는 특히 SoftZone 값과 Damping 값을 모두 큰 수치로 높인 경우에 더 뚜렷하게 나타납니다. 이 문제를 해결하기 위해 Damping 값을 낮추어 카메라가 플레이어의 움직임을 보다 빠르고 자연스럽게 따라오도록 조정해야 합니다. 또한, 카메라가 과도하게 흔들리지 않으면서도 플레이어를 적절히 추적할 수 있도록 DeadZone, SoftZ [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 게임의 메인 카메라는 항상 플레이어를 따라다닙니다. 메인 카메라를 제어하는 camera 컴포넌트는 MapleStoryPlayer 모델이 가지고 있으며 이 모델의 프로퍼티 에디터나 스크립트를 이용해 주요 값을 수정할 수 있습니다. 이번 과정에서는 Camera 컴포넌트를 프로퍼티 에디터를 통해 수정해보며 전반적인 기능을 알아보는 시간을 가져보도록 하겠습니다. # Camera 컴포넌트 접근 Workspace에서 DefaultPlayer 모델을 선택합니다. 프로퍼티 에디터에서 CameraComponent를 확인
[task] | single_turn [pass] | ⏳ 미판정 [title] | 스킬 이펙트를 뿌려보자! [question] | PlayEffect와 PlayEffectAttached 함수의 가장 큰 차이점과 각각 어떤 스킬 연출에 적합하게 사용해야 하는지 궁금해요. [answer] | `PlayEffect`와 `PlayEffectAttached`의 가장 큰 차이점은 **이펙트의 위치 고정 방식**입니다. 1. **`PlayEffect`**: * 이펙트를 **고정된 위치**에 생성합니다. * 호출 시점에 지정한 좌표로 이펙트가 배치되며, 이후 캐릭터가 이동해도 이펙트는 그 자리에 그대로 남아 있습니다. * **적합한 연출**: 캐릭터가 이동하지 않거나, 특정 지점에 잠시 머물러야 하는 **버프류 스킬**이나, 캐릭터와 분리되어 독립적으로 존재해야 하는 이펙트 연출에 적합합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 위에서 살펴본 이펙트 호출 방법은 사실 스킬 이펙트에 적합한 방법은 아닙니다. 위의 예제처럼 구현하면 Q, W, E, R 키를 누른 후 캐릭터를 이동할 때 캐릭터가 이펙트를 벗어나 이동하게 됩니다. `PlayEffect`는 위에서 잠깐 언급한 것처럼 고정된 위치에 이펙트를 호출하는데 적합한 함수이기 때문에 버프류 스킬과 같이 항상 캐릭터 위에 떠 있어야 할 이펙트에는 적합하지 않습니다. 따라서 이러한 경우에 사용하는 함수가 바로 `PlayEffectAttached` 함수입니다. `PlayEffectAttached`의 경우 이펙트가
[task] | code [pass] | ⏳ 미판정 [title] | 스킬 이펙트를 뿌려보자! [question] | _EffectService:PlayEffect 를 사용하여 특정 엔티티의 현재 위치에서 RUID "effect_001" 이펙트를 Vector3(1, 1, 1) 크기로 한 번만 재생하는 스크립트를 작성해줘 [answer] | 요청하신 조건에 맞는 mLua 스크립트는 다음과 같습니다. ```lua Method: [server only] void PlayMyEffect() { _EffectService:PlayEffect("effect_001", self.Entity, self.Entity.TransformComponent.Position, 0, Vector3(1, 1, 1), false) } ``` **설명:** * `_EffectService:PlayEffect` 함수를 사용합니다. * 첫 번째 인자로는 요청하신 RUID `"effec [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 메이플스토리에서 사용되었던 수많은 이펙트 리소스들을 제공하고 있습니다. 그리고 우리는 이러한 이펙트들을 적절한 시점과 위치에 호출해 줌으로써 한층 더 멋진 연출을 구사할 수 있습니다. 이번 과정에서는 특정 키를 누를 때마다 스킬 이펙트가 노출되는 예제를 진행해봄으로써 스크립트를 통해 이펙트를 호출하는 방법에 대해 알아보도록 합니다. 다음 가이드를 먼저 학습하면 이번 과정을 진행하는 데 많은 도움이 될 것입니다. [스크립트 에디터 오리엔테이션](https://mod-developers.
[task] | code [pass] | ⏳ 미판정 [title] | 아이템 생성 및 삭제 [question] | 맵에 배치된 아이템 엔티티에 GiftBox 스크립트 컴포넌트와 TriggerComponent가 모두 추가되어 있어야 하며, TriggerEnterEvent 발생 시 충돌한 엔티티의 인벤토리에 아이템을 생성하고 5초 후 아이템 엔티티가 다시 나타나도록 동작하는 전체 GiftBox 스크립트를 작성해줘. [answer] | 맵에 배치된 아이템 엔티티에는 **GiftBox** 스크립트 컴포넌트와 **TriggerComponent**가 모두 부착되어 있어야 합니다. `TriggerComponent`는 충돌 감지를 담당하며, `GiftBox` 스크립트는 `TriggerEnterEvent` 이벤트를 수신하여 로직을 실행합니다. 요청하신 동작(충돌 시 인벤토리에 랜덤 아이템 생성, 5초 후 엔티티 재활성)을 수행하는 전체 `GiftBox` 스크립트 컴포넌트 코드는 다음과 같습니다. ```lua Event Handler: [self] HandleTrigger [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 이번에는 생성된 아이템을 표시할 인벤토리 UI를 추가합니다. 상단 메뉴에 버튼을 눌러 UI 에디터를 엽니다. **Preset List**에서 **[인벤토리]**, **[버튼모음]** UI를 추가합니다. 만일 **Inventory** 엔티티의 **UIInventory** 컴포넌트에 **InventoryBtnPath**가 비어있으면, 햄버거 메뉴를 열어 **Reset All Properties**를 선택합니다. 그러면 아래와 같이 정상적인 경로가 설정됩니다. # 아이템 엔티티 배치 및 기능 추가 버튼을 눌러 UI 편집모드를
[task] | single_turn [pass] | ⏳ 미판정 [title] | 스킬 이펙트를 뿌려보자! [question] | 버프 스킬처럼 캐릭터 위에 항상 떠 있어야 하는 이펙트인데도 불구하고 PlayEffect를 사용했을 때 왜 캐릭터와 이펙트가 분리되는 현상이 일어나나요? [answer] | `PlayEffect` 함수는 이펙트를 고정된 위치에 호출하도록 설계되어 있습니다. 이 함수를 사용하면 이펙트가 처음 생성된 좌표 기준의 세계 좌표(world position)에 정지하게 됩니다. 반면, 캐릭터는 이동할 때 자체의 위치가 실시간으로 변합니다. 이펙트가 고정된 위치에 남아 있는 동안 캐릭터만 이동하기 때문에, 두 개체가 서로 분리되는 현상이 발생합니다. 이 문제를 해결하기 위해 캐릭터 위에 항상 떠 있어야 하는 버프류 이펙트에는 `PlayEffectAttached` 함수를 사용해야 합니다. `PlayEffectAt [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 위에서 살펴본 이펙트 호출 방법은 사실 스킬 이펙트에 적합한 방법은 아닙니다. 위의 예제처럼 구현하면 Q, W, E, R 키를 누른 후 캐릭터를 이동할 때 캐릭터가 이펙트를 벗어나 이동하게 됩니다. `PlayEffect`는 위에서 잠깐 언급한 것처럼 고정된 위치에 이펙트를 호출하는데 적합한 함수이기 때문에 버프류 스킬과 같이 항상 캐릭터 위에 떠 있어야 할 이펙트에는 적합하지 않습니다. 따라서 이러한 경우에 사용하는 함수가 바로 `PlayEffectAttached` 함수입니다. `PlayEffectAttached`의 경우 이펙트가
[task] | single_turn [pass] | ⏳ 미판정 [title] | 발판 만들기 [question] | FootholdForce 값을 양수로 설정했는데 왜 엔티티가 오른쪽으로 밀려나지 않나요? [answer] | `FootholdForce` 값을 양수로 설정해도 엔티티가 즉시 또는 항상 오른쪽으로 밀려나지 않을 수 있는 주된 원인은 **엔티티가 발판 위에 실제로 있지 않기 때문**입니다. 문서에서 명시하듯, `FootholdForce`는 `RigidbodyComponent`가 포함된 Entity가 **발판 위에 있을 때**에만 가해지는 힘입니다. 따라서 아래 조건을 확인해 보세요. 1. **엔티티에 RigidbodyComponent가 장착되어 있어야 합니다.** * `RigidbodyComponent`가 없는 엔티티에는 `F [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 새롭게 만든 발판에 속성을 바꿔 크리에이터만의 독특한 발판으로 만들 수 있습니다. 각 프로퍼티 값을 조정해 특정 방향에서 나아갈 수 없는 발판, 특별히 느리게 이동하는 발판 등으로 활용해 재미를 더할 수 있습니다. | 이름 | 설명 | | --- | --- | | FootholdDrag | RigidbodyComponent가 포함된 Entity가 발판 위에 있을 때 적용되는 마찰력을 의미합니다. 값이 클수록 엔티티가 발판에서 미끌어지다 빠르게 감속해 정지합니다. 특정 지점에서 엔티티가 날아와 해당 값이 1과 10인 발판에 각각
[task] | code [pass] | ⏳ 미판정 [title] | 발판 만들기 [question] | FootholdDrag 프로퍼티를 10으로 설정해 엔티티가 빠르게 정지하도록 하는 발판 스크립트를 작성해줘 [answer] | 제공된 참고 문서에 `FootholdDrag`, `FootholdForce`, `FootholdWalkSpeedFactor` 프로퍼티의 **설명**만 포함되어 있고, 이 프로퍼티들을 mLua 스크립트에서 직접 선언하거나 수정하는 코드 예제나 API 명세는 포함되어 있지 않습니다. 따라서 `FootholdDrag` 값을 10으로 설정하는 구체적인 mLua 스크립트 코드를 생성할 수 없습니다. 이 값들은 게임 에디터의 지형 발판 컴포넌트에서 직접 조정하는 설정값일 가능성이 높으며, 문서에는 이를 스크립트로 조작하는 방법이 명시되어 있 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 새롭게 만든 발판에 속성을 바꿔 크리에이터만의 독특한 발판으로 만들 수 있습니다. 각 프로퍼티 값을 조정해 특정 방향에서 나아갈 수 없는 발판, 특별히 느리게 이동하는 발판 등으로 활용해 재미를 더할 수 있습니다. | 이름 | 설명 | | --- | --- | | FootholdDrag | RigidbodyComponent가 포함된 Entity가 발판 위에 있을 때 적용되는 마찰력을 의미합니다. 값이 클수록 엔티티가 발판에서 미끌어지다 빠르게 감속해 정지합니다. 특정 지점에서 엔티티가 날아와 해당 값이 1과 10인 발판에 각각
[task] | code [pass] | ⏳ 미판정 [title] | 스킬 이펙트를 뿌려보자! [question] | _EffectService:PlayEffectAttached 를 사용하여 부모 엔티티 기준 로컬 위치 Vector3(0, 2, 0) 에서 RUID "effect_004" 이펙트를 localZRotation 45 도로 회전시켜 Vector3(0.5, 0.5, 0.5) 크기로 한 번만 재생하는 스크립트를 작성해줘 [answer] | _EffectService:PlayEffectAttached 함수를 사용하여 요청하신 조건으로 스크립트를 작성하면 다음과 같습니다. ```lua [server] void OnBeginPlay() { _EffectService:PlayEffectAttached("effect_004", self.Entity, Vector3(0, 2, 0), 45, Vector3(0.5, 0.5, 0.5), false) } ``` **설명:** * `PlayEffectAttached`의 두 번째 매개변수에 부모 엔티티로 `self.Enti [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 메이플스토리에서 사용되었던 수많은 이펙트 리소스들을 제공하고 있습니다. 그리고 우리는 이러한 이펙트들을 적절한 시점과 위치에 호출해 줌으로써 한층 더 멋진 연출을 구사할 수 있습니다. 이번 과정에서는 특정 키를 누를 때마다 스킬 이펙트가 노출되는 예제를 진행해봄으로써 스크립트를 통해 이펙트를 호출하는 방법에 대해 알아보도록 합니다. 다음 가이드를 먼저 학습하면 이번 과정을 진행하는 데 많은 도움이 될 것입니다. [스크립트 에디터 오리엔테이션](https://mod-developers.
[task] | instruction_following [pass] | ⏳ 미판정 [title] | NPC 대화창 만들기 [question] | Name 엔티티의 UITransformComponent 프로퍼티 설정값을 표로 정리하세요. [answer] | Name 엔티티의 UITransformComponent 프로퍼티 설정값은 다음과 같습니다. | 프로퍼티 | 값 | | --- | --- | | PosX | -600 | | PosY | 110 | | Width | 300 | | Height | 100 | [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 결과물은 다음과 같습니다. 10. 새로운 텍스트 엔티티를 추가합니다. 추가한 텍스트 엔티티를 클릭하고 이름을 **Name**으로 변경합니다. 11. **Name** 엔티티를 **TalkPanel**로 드래그하여 **TalkPanel**의 자식으로 설정합니다. 12. **Name** 엔티티의 프로퍼티를 다음과 같이 수정합니다. | 컴포넌트 | 프로퍼티 | 값 | | --- | --- | --- | | @cols=1:@rows=4:UITransformComponent | PosX | -600 |
[task] | instruction_following [pass] | ⏳ 미판정 [title] | NPC 대화창 만들기 [question] | Text 엔티티의 TextComponent Alignment 값을 3문장 이내로 설명하세요. [answer] | Text 엔티티의 TextComponent Alignment 값은 `UpperLeft`입니다. 이는 텍스트가 영역의 왼쪽 상단부터 시작하도록 정렬 방식을 설정합니다. 따라서 대화 텍스트가 좌측 상단 기준에서 아래로 이어지게 표시됩니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 결과물은 다음과 같습니다. 10. 새로운 텍스트 엔티티를 추가합니다. 추가한 텍스트 엔티티를 클릭하고 이름을 **Name**으로 변경합니다. 11. **Name** 엔티티를 **TalkPanel**로 드래그하여 **TalkPanel**의 자식으로 설정합니다. 12. **Name** 엔티티의 프로퍼티를 다음과 같이 수정합니다. | 컴포넌트 | 프로퍼티 | 값 | | --- | --- | --- | | @cols=1:@rows=4:UITransformComponent | PosX | -600 |
[task] | single_turn [pass] | ⏳ 미판정 [title] | 발판 만들기 [question] | Foothold 모델을 배치했을 때 빨간색 선으로 발판 영역이 표시되는 기능을 어떻게 확인하고, 이 기능이 게임 제작에 어떤 도움이 되나요? [answer] | Foothold 모델을 Scene 패널에 배치한 후, 해당 발판 엔티티의 **발판 정보 아이콘**을 클릭하면 발판 영역이 빨간색 선으로 표시됩니다. 이 기능이 게임 제작에 도움이 되는 이유는 다음과 같습니다. * **발판 범위 확인:** 빨간색 선을 통해 실제로 아바타가 이동할 수 있는 발판의 정확한 경계와 형태를 시각적으로 확인할 수 있습니다. * **정밀한 조정:** 예상과 다르게 발판이 인식되거나 범위가 좁을 경우, 빨간색 선을 기준으로 CustomFootholdComponent의 연결점이나 시작점을 조정하여 플레이어 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 여러 오브젝트를 사용해 발판을 만들어 게임의 보는 재미를 풍성하게 만들어봅시다. **FootholdComponent**와 **CustomFootholdComponent** 개념과 발판 편집 방법을 소개합니다. # Foothold 모델로 발판 만들기 **Foothold** 모델을 이용해 발판을 만드는 방법입니다. 타일이 아닌 **Foothold** 모델을 이용해 다채로운 길을 만들 수 있습니다. 1. **Preset List** 패널에서 **Foothold**를 선택합니다. 2. 원하는 모델을 선택해 **S