[task] | instruction_following [pass] | ⏳ 미판정 [title] | 카드 섞기, 선택하기 [question] | SetCards 함수의 카드 셔플 로직을 단계별 번호 목록으로 요약하세요. [answer] | `SetCards` 함수의 카드 셔플 로직은 다음과 같은 단계로 이루어져 있습니다. 1. **데이터 로드**: `_DataService:GetRowCount("CardSet")`을 호출하여 `CardSet` 데이터 행의 개수(`deckCount`)를 구합니다. 2. **덱 구성**: `1`부터 `deckCount`까지 반복하며, `_DataService:GetCell("CardSet", i, 1)`로 각 카드의 `spriteRUID`를 가져와 `deckTable` 배열에 추가합니다. 3. **덱 셔플**: `1`부터 `dec [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | ```lua Property: [None] Entity CardSpawnRoot = /ui/CardParirGameUi/UI_Board/UI_Blocks/UI_Block_Group [None] Card SelectedCard = nil Method: [client only] Void SetCards() { local deckTable = {} local cardTable = {} local deckCount = _DataService:GetRowCount("CardSet")
[task] | single_turn [pass] | ⏳ 미판정 [title] | 스크립트 라이프 사이클 [question] | 테스트 플레이를 시작하면 편집용 월드가 비활성화되고 서버와 클라이언트에 테스트 플레이용 월드가 새로 생성된다고 하는데, 이때 기존에 저장되어 있던 변수 값들이 초기화되는지 아니면 유지되는지 알고 싶습니다. [answer] | 제공된 참고 문서에는 테스트 플레이 시작 시 편집용 월드가 비활성화되고 서버와 클라이언트에 테스트 플레이용 월드가 새로 생성된다는 내용은 명시되어 있습니다. 하지만, 이 과정에서 **기존에 저장되어 있던 변수 값(스크립트 프로퍼티 등)이 초기화되는지 유지되는지에 대한 구체적인 설명은 문서에 없습니다.** 문서에는 편집용 엔티티의 `OnBeginPlay`, `OnUpdate`, `OnEndPlay`가 호출되지 않는다는 사실과, 테스트 플레이 시 서버와 클라이언트에서 각각 새로운 월드가 생성된다는 사실만 언급하고 있을 뿐, 데이터의 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 서버와 클라이언트가 호출되는 전체 흐름을 알아봅시다. 플레이 라이프 사이클은 **제작 중인 월드**와 **출시된 월드**에서 약간의 차이가 있습니다. 가장 큰 차이점은 맵을 불러오는 방식입니다. * **제작 중인 월드**에서 플레이할 때는 10개의 맵을 만들었더라도 플레이어가 있는 맵만 불러옵니다. * **출시된 월드**에서는 플레이어 유무와 상관없이 모든 맵을 불러옵니다. 이와 같은 차이를 알고 있다면 **제작 중인 월드** 또는 **출시된 월드**에서 크리에이터 의도대로 동작하지 않는 무언가가 있을 때, 그 원인이 잘못된
[task] | single_turn [pass] | ⏳ 미판정 [title] | 공동 제작 [question] | Hierarchy에서 엔티티를 선택했을 때 표시되는 '내가 작업 중' 아이콘과 '다른 멤버가 작업 중' 아이콘은 각각 어떤 동작을 의미하나요? [answer] | Hierarchy에서 엔티티를 선택했을 때 표시되는 두 아이콘의 의미와 동작은 다음과 같습니다. **1. 내가 작업 중인 엔트리/엔티티 아이콘** * **의미:** 현재 사용자가 해당 엔티티에 대해 **Check Out** 한 상태임을 의미합니다. * **동작:** * 편집 권한을 획득하여 해당 엔티티를 자유롭게 수정할 수 있습니다. * 다른 멤버들은 이 엔티티에 접근할 수 없으며, **Check In**을 하기 전까지는 잠금(Locked) 상태가 유지됩니다. * 작업을 마친 후 **Chec [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 다양한 사람들이 함께 모여 월드를 제작할 수 있는 방법에 대해 알아봅시다. ##### 참고 가이드 * [그룹 생성과 멤버 관리](/docs/?postId=1325"target":"_self"}) * [공동 제작 그룹 멤버의 등급과 권한](/docs/?postId=1077) * [LocalWorkspace](/docs/?postId=1165) * [ExtendedScriptFormat](/docs/?postId=1166) # 공동 제작 함께 월드를 제작하기 위해서는 우선 그룹을 형성하고, 멤버 권한을 설정해
[task] | single_turn [pass] | ⏳ 미판정 [title] | 카드 섞기, 선택하기 [question] | CardPairGameLogic의 OnCardClicked 함수에서 기존에 선택된 카드가 없다면 어떤 처리가 이루어지나요? [answer] | CardPairGameLogic의 `OnCardClicked` 함수에서 기존에 선택된 카드(`oldCard`)가 없다면(`oldCard == nil`), 새로 클릭된 카드(`newCard`)를 선택하는 처리가 이루어집니다. 구체적으로 `CardBoard` 컴포넌트의 `SelectCard` 메서드를 호출하여 `newCard`를 선택 상태로 만듭니다. ```lua if oldCard == nil then cardboard:SelectCard(newCard) end ``` 이때 `SelectCard` 메서드는 선택된 카드의 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 1. **CardBoard** 컴포넌트에서 새로운 프로퍼티를 추가하고 프로퍼티 타입을 **Component**로 지정합니다. ```lua Property: [None] Card SelectedCard = nil ``` 2. CardBoard 컴포넌트에서 `SelctCard` 함수를 찾습니다. 매개 변수를 추가하고 타입을 Component로 변경합니다. Component를 **Card**로 지정합니다. ```lua [client only] void SelectCard (C
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 카드 섞기, 선택하기 [question] | CardPairGameLogic 슬립트의 OnCardClicked 메서드에서 oldCard가 nil인 경우와 아닌 경우의 로직 분기를 코드만 출력하고 설명은 주석으로 작성하세요. [answer] | ```lua -- oldCard가 nil이면 새 카드 선택, 아니면 현재 선택 해제 if oldCard == nil then cardboard:SelectCard(newCard) else cardboard:DeselectCard() end ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | ```lua Property: [None] string SpriteRUID = "" Method: void CardOn () { self.Entity.SpriteGUIRendererComponent.Color = Color(81/255,81/255,81/255,1) } void CardOff () { self.Entity.SpriteGUIRendererComponent.Color = Color(255/255,255/255,255/255,1) } Event Handler: [self] HandleButtonClic
[task] | code [pass] | ⏳ 미판정 [title] | 스크립트 라이프 사이클 [question] | DefaultPlayer 엔티티에 LifeCycle 컴포넌트를 추가하고, 포털을 이용해 맵을 이동했을 때 OnMapLeave와 OnMapEnter 로그가 순차적으로 출력되는지 확인하기 위한 LifeCycle 스크립트를 작성해줘 [answer] | 요청하신 시나리오(새로운 LifeCycle 컴포넌트 생성, DefaultPlayer에 추가, 맵 이동 시 로그 확인)를 위한 mLua 스크립트입니다. 문서에 명시된 기본 이벤트 함수(`OnInitialize`, `OnBeginPlay`, `OnMapEnter`, `OnMapLeave`, `OnEndPlay`, `OnDestroy`) 중, 라이프 사이클 흐름 확인에 필수적인 함수들을 포함하여 작성했습니다. 각 함수 내부에 `log`를 사용하여 호출 순서를 확인할 수 있게 했습니다. ```lua Property: [None] str [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 기본 이벤트 함수의 라이프 사이클과 플레이할 때의 전체 라이프 사이클을 알아봅시다. 라이프 사이클을 이해하면 특정 함수가 언제 불리는지 예상할 수 있고, 전체 월드의 동작을 고려하며 제작할 수 있습니다. # 기본 이벤트 함수의 라이프 사이클 월드에 필요한 로직을 만들기 위해서는 컴포넌트 스크립트를 만들어야만 합니다. 필요한 컴포넌트 스크립트를 만들 때 호출되는 시점을 예상해 의도한 로직에 맞게 동작할 수 있도록 작성해야 합니다. 라이프 사이클의 개념을 익혀두면 전체 흐름을 파악할 수 있기에 스크립트를 작성
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 카드 섞기, 선택하기 [question] | Card 스크립트의 HandleButtonClickEvent에서 카드가 선택될 때와 선택 해제될 때 각각 어떤 조건과 메서드 호출이 일어나는지 3문장 이내로 설명하세요. [answer] | `CardPairGameLogic`의 `OnCardClicked` 메서드에서 `cardboard.SelectedCard`가 `nil`이면 `cardboard:SelectCard(newCard)`를 호출하여 카드를 선택합니다. 이미 선택된 카드가 존재하면(`oldCard`가 `nil`이 아니면) `cardboard:DeselectCard()`를 호출하여 선택을 해제합니다. 이로써 첫 번째 클릭은 선택, 두 번째 클릭은 선택 해제(또는 다음 카드 선택 전 해제) 로직을 수행합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | ```lua Property: [None] string SpriteRUID = "" Method: void CardOn () { self.Entity.SpriteGUIRendererComponent.Color = Color(81/255,81/255,81/255,1) } void CardOff () { self.Entity.SpriteGUIRendererComponent.Color = Color(255/255,255/255,255/255,1) } Event Handler: [self] HandleButtonClic
[task] | two_turn [pass] | ⏳ 미판정 [title] | 공동 제작 [question] | Panels - Cooperation 메뉴에서 Local Changes 창을 열었을 때 확인할 수 있는 정보와 수행할 수 있는 주요 기능은 무엇인가요? [answer] | **Panels - Cooperation - Local Changes** 창을 열면 그룹 월드에서 작업자가 Check Out한 항목들을 모아볼 수 있습니다. 이 창에서 확인하고 수행할 수 있는 주요 기능은 다음과 같습니다. 1. **변경 항목 확인**: Hierarchy 또는 Workspace에서 내가 변경한 항목을 확인할 수 있습니다. 2. **일괄 Check In**: 확인한 변경 사항들을 한 번에 **Check In**할 수 있습니다. [followup] | Hierarchy와 Workspace에서 변경한 항목을 한 번에 Check In하는 과정 중, 특정 항목만 선택하여 체크인하는 것이 가능한지 혹은 전체적으로만 처리되는지에 대한 구체적인 동작 방식은 어떻게 되나요? [followup_answer] | 제공된 문서에는 Local Changes 창에서 "한 번에 **Check In**할 수 있습니다"라고만 명시되어 있으며, 특정 항목만 선택하여 체크인하는 개별 선택 기능이나 그 동작 방식에 대한 구체적인 설명은 포함되어 있지 않습니다. 따라서 문서 근거만으로 부분 선택이 가능한지 여부는 확인할 수 없습니다. [scores] | [judge_reason] | [source_doc] | 함께 제작하는 그룹 월드에서 **Panels - Cooperation**을 누릅니다. 해당 월드에 함께 접속 중인 사람들의 닉네임과 메이커 아이디가 보입니다. ## Local Changes 그룹 월드에서 작업자가 Check Out한 항목을 모아 볼 수 있는 창입니다. Hierarchy, Workspace에서 내가 변경한 항목을 확인하고, 한 번에 **Check In**할 수 있습니다. **Panels - Cooperation - Local Changes**를 눌러 창을 엽니다. ## 복구 모드 그룹 월드의 리비전을 되돌리기나
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 여러 개의 카드 보여주기 [question] | SetCards() 함수에서 CreateCardEntities()를 호출할 때 전달해야 하는 매개 변수를 포함하는 코드 줄 하나만 출력하세요. [answer] | ```lua self:CreateCardEntities(cardTable) ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | ```lua local cardCount = #cardTable for i = 1, cardCount do local spriteRUID = cardTable[i] ``` 6. `CreateCardEntities()` 함수에서 `local card = _SpawnService:SpawnByModelId(cardModelId, "Card", Vector3(0,0,0), self.CardSpawnRoot)`를 찾습니다. `"Card"` 부분을 `"Card " .. tostring(i)`로 변경하며 아
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 여러 개의 카드 보여주기 [question] | CreateCardEntities() 함수 내에서 카드 이름을 고유하게 변경하는 코드를 코드 블록으로만 출력하세요. [answer] | ```lua local card = _SpawnService:SpawnByModelId(cardModelId, "Card " .. tostring(i), Vector3(0,0,0), self.CardSpawnRoot) ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | ```lua local cardCount = #cardTable for i = 1, cardCount do local spriteRUID = cardTable[i] ``` 6. `CreateCardEntities()` 함수에서 `local card = _SpawnService:SpawnByModelId(cardModelId, "Card", Vector3(0,0,0), self.CardSpawnRoot)`를 찾습니다. `"Card"` 부분을 `"Card " .. tostring(i)`로 변경하며 아
[task] | single_turn [pass] | ⏳ 미판정 [title] | 카드 섞기, 선택하기 [question] | DeselectCard 함수에서 선택 해제 후 SelectedCard 프로퍼티를 nil로 설정하는 이유는 무엇인가요? [answer] | `DeselectCard` 함수에서 `SelectedCard` 프로퍼티를 `nil`로 설정하는 이유는 현재 선택된 카드가 없음을 상태적으로 명확하게 표시하기 위해서입니다. `OnCardClicked` 로직을 보면 이전에 선택된 카드(`oldCard`)가 있는지 확인하는 조건문이 `if oldCard == nil then` 이며, 이 `oldCard`는 `cardboard.SelectedCard`에서 가져옵니다. 1. **첫 번째 카드 선택 시**: `SelectedCard`가 `nil`이므로 `oldCard == nil` 조건 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 1. **CardBoard** 컴포넌트에서 새로운 프로퍼티를 추가하고 프로퍼티 타입을 **Component**로 지정합니다. ```lua Property: [None] Card SelectedCard = nil ``` 2. CardBoard 컴포넌트에서 `SelctCard` 함수를 찾습니다. 매개 변수를 추가하고 타입을 Component로 변경합니다. Component를 **Card**로 지정합니다. ```lua [client only] void SelectCard (C
[task] | two_turn [pass] | ⏳ 미판정 [title] | 카드 섞기, 선택하기 [question] | 카드 짝 맞추기 게임에서 카드 덱을 짝을 이루도록 생성하고 섞는 로직은 어떻게 구현하나요? [answer] | 카드 덱을 짝을 이루도록 생성하고 섞는 로직은 `CardBoard` 컴포넌트의 `SetCards()` 함수 내에서 구현합니다. 기존에 전체 덱 개수만큼 반복하던 과정을 덱 개수의 절반만큼만 반복하도록 수정하여, 각 카드를 두 번씩 `cardTable`에 추가함으로써 동일한 카드 한 쌍을 만듭니다. 이후 생성된 `cardTable`의 전체 길이에 대해 무작위 인덱스를 생성하여 위치를 교환하는 방식으로 카드를 섞습니다. 구현 코드는 다음과 같습니다. ```lua for i = 1, (deckCount / 2) do table [followup] | `SetCards()` 함수에서 `deckCount`의 절반만 반복하며 `table.insert`로 쌍을 만들고, 이후 `#cardTable` 길이만큼 무작위 인덱스를 교환하여 섞는 구체적인 코드 구조를 알려주세요. [followup_answer] | `SetCards()` 함수에서 카드를 쌍으로 생성하고 섞는 구체적인 코드 구조는 다음과 같습니다. 1. **짝 생성**: `deckCount`의 절반만큼 반복하며, 각 `deckTable`의 항목을 `cardTable`에 두 번씩 삽입하여 동일한 카드 한 쌍을 만듭니다. 2. **섞기**: 생성된 `cardTable`의 전체 길이(`#cardTable`)만큼 반복하며, `_UtilLogic:RandomIntegerRange(1, #cardTable)`을 이용해 무작위 인덱스를 생성하고 해당 위치의 값을 서로 교환합니다. ` [scores] | [judge_reason] | [source_doc] | # 카드 섞기 카드 보여주기에 성공했으니 이번에는 한 쌍의 카드가 나오게 만들어 봅시다. 1. **CardBoard** 컴포넌트의 `SetCards()` 함수에서 세 번째 `for i = 1, deckCount do`를 찾습니다. 처음에는 deckCount의 수만큼 실행했지만, 이번에는 deckCount의 절반만큼만 실행하기 위해 (deckCount / 2)로 변경합니다. 그 절반을 동일하게 두 번 불러와 쌍을 이루는 판을 만듭니다. `table.insert`는 [table](/apiReference/Lua/table) 레
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 카드 섞기, 선택하기 [question] | `Model_Card`에 추가된 `ButtonComponent`가 카드 선택 시 색상 변화를 처리하는 `CardOn` 및 `CardOff` 함수의 구현 내용을, 함수명과 함께 표로 정리해서 제시하세요. [answer] | `Model_Card`에 `ButtonComponent`가 추가된 후, 카드 선택 상태에 따라 색상을 변경하는 `CardOn`과 `CardOff` 함수의 구현 내용은 다음과 같습니다. | 함수명 | 기능 설명 | 구현 코드 | | :--- | :--- | :--- | | `CardOn` | 카드가 선택(누름) 상태가 되었을 때 스프라이트 색상을 회색(RGB: 81/255)으로 변경합니다. | ```lua<br>void CardOn()<br>{<br> self.Entity.SpriteGUIRendererComponent.Col [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 카드 섞기 카드 보여주기에 성공했으니 이번에는 한 쌍의 카드가 나오게 만들어 봅시다. 1. **CardBoard** 컴포넌트의 `SetCards()` 함수에서 세 번째 `for i = 1, deckCount do`를 찾습니다. 처음에는 deckCount의 수만큼 실행했지만, 이번에는 deckCount의 절반만큼만 실행하기 위해 (deckCount / 2)로 변경합니다. 그 절반을 동일하게 두 번 불러와 쌍을 이루는 판을 만듭니다. `table.insert`는 [table](/apiReference/Lua/table) 레
[task] | code [pass] | ⏳ 미판정 [title] | 스크립트 라이프 사이클 [question] | 서버에서 `_TimerService`를 사용하여 5초 후 지정된 경로에 있는 엔티티를 `_EntityService:GetEntityByPath`로 조회하고 존재 여부를 로그로 출력하는 스크립트를 작성해줘 [answer] | 요청하신 기능은 `OnBeginPlay` 라이프사이클 메서드에서 `_TimerService:SetTimerOnce`를 호출하여 5초 후 실행될 콜백 함수를 등록하는 방식으로 구현할 수 있습니다. 콜백 함수 내에서 `_EntityService:GetEntityByPath`를 통해 엔티티를 조회한 후, `nil` 체크를 수행하여 존재 여부를 `log` 함수로 출력하면 됩니다. 아래는 해당 요구사항을 충족하는 mLua 스크립트입니다. ```lua Method: [server only] void OnBeginPlay() { -- [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 서버와 클라이언트가 호출되는 전체 흐름을 알아봅시다. 플레이 라이프 사이클은 **제작 중인 월드**와 **출시된 월드**에서 약간의 차이가 있습니다. 가장 큰 차이점은 맵을 불러오는 방식입니다. * **제작 중인 월드**에서 플레이할 때는 10개의 맵을 만들었더라도 플레이어가 있는 맵만 불러옵니다. * **출시된 월드**에서는 플레이어 유무와 상관없이 모든 맵을 불러옵니다. 이와 같은 차이를 알고 있다면 **제작 중인 월드** 또는 **출시된 월드**에서 크리에이터 의도대로 동작하지 않는 무언가가 있을 때, 그 원인이 잘못된
[task] | single_turn [pass] | ⏳ 미판정 [title] | 카드 섞기, 선택하기 [question] | _Client only로 지정된 SetCards 함수에서 _DataService:GetRowCount로 데이터를 가져오는 과정에서 서버와 클라이언트 간 동기화 문제가 발생할 수 있는 이유는 무엇인가요? [answer] | 제공된 참고 문서에는 `_DataService:GetRowCount` 호출 시 서버와 클라이언트 간 동기화 문제가 발생하는 구체적인 이유나, `_DataService`의 서버/클라이언트 실행 공간에 대한 설명이 포함되어 있지 않습니다. 문서에는 `SetCards` 함수가 `[client only]`로 지정되어 있고, 해당 함수 내에서 `_DataService:GetRowCount("CardSet")` 및 `_DataService:GetCell`을 사용하여 데이터를 가져온 뒤 카드를 생성하는 과정만 기술되어 있을 뿐, 동기화 문제의 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | ```lua Property: [None] Entity CardSpawnRoot = /ui/CardParirGameUi/UI_Board/UI_Blocks/UI_Block_Group [None] Card SelectedCard = nil Method: [client only] Void SetCards() { local deckTable = {} local cardTable = {} local deckCount = _DataService:GetRowCount("CardSet")
[task] | single_turn [pass] | ⏳ 미판정 [title] | 카드 섞기, 선택하기 [question] | _UI_Block_Group 경로의 CardSpawnRoot 프로퍼티가 유효하지 않거나 경로가 잘못되었을 때 _SpawnService:SpawnByModelId 호출 시 나타나는 오류 원인은 무엇인가요? [answer] | 제시된 참고 문서에는 `_SpawnService:SpawnByModelId` 호출 시 `CardSpawnRoot` 경로가 잘못되었거나 유효하지 않을 때 발생하는 구체적인 오류 메시지나 예외 처리 로직에 대한 설명이 포함되어 있지 않습니다. 문서에는 `_SpawnService:SpawnByModelId(cardModelId, "Card" .. tostring(i), Vector3(0,0,0), self.CardSpawnRoot)`와 같이 `self.CardSpawnRoot`를 부모 엔티티로 전달하는 코드 예시만 존재하며, 이 경로가 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | ```lua Property: [None] Entity CardSpawnRoot = /ui/CardParirGameUi/UI_Board/UI_Blocks/UI_Block_Group [None] Card SelectedCard = nil Method: [client only] Void SetCards() { local deckTable = {} local cardTable = {} local deckCount = _DataService:GetRowCount("CardSet")
[task] | single_turn [pass] | ⏳ 미판정 [title] | 스크립트 라이프 사이클 [question] | 제작 중인 월드에서 EntityService로 다른 맵의 엔티티를 접근할 때 해당 맵이 즉시 로드되는지, 아니면 포탈 이동처럼 특정 조건에서만 로드되는지 차이를 알고 싶습니다. [answer] | 제시된 문서에 따르면, **제작 중인 월드**에서 맵 로딩은 "접근 방식"에 따라 명확히 구분됩니다. ### 1. 즉시 로드되는 경우: `EntityService` 사용 문서에서 **"EntityService를 사용해 다른 맵의 엔티티를 얻거나"**라고 명시하고 있습니다. 즉, 스크립트 내에서 `_EntityService:GetEntityByPath("/maps/다른맵/엔티티")`와 같은 방법으로 다른 맵의 엔티티에 접근하는 시점에, 해당 맵은 **즉시 로드**됩니다. 이는 플레이어가 물리적으로 이동하지 않아도 코드로 접근했다는 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 서버와 클라이언트가 호출되는 전체 흐름을 알아봅시다. 플레이 라이프 사이클은 **제작 중인 월드**와 **출시된 월드**에서 약간의 차이가 있습니다. 가장 큰 차이점은 맵을 불러오는 방식입니다. * **제작 중인 월드**에서 플레이할 때는 10개의 맵을 만들었더라도 플레이어가 있는 맵만 불러옵니다. * **출시된 월드**에서는 플레이어 유무와 상관없이 모든 맵을 불러옵니다. 이와 같은 차이를 알고 있다면 **제작 중인 월드** 또는 **출시된 월드**에서 크리에이터 의도대로 동작하지 않는 무언가가 있을 때, 그 원인이 잘못된
[task] | single_turn [pass] | ⏳ 미판정 [title] | 카드 섞기, 선택하기 [question] | Card 컴포넌트에서 OnCardClicked 함수를 호출할 때 self를 매개변수로 전달해야 하는 이유는 무엇인가요? [answer] | `Card` 컴포넌트에서 `OnCardClicked` 함수를 호출할 때 `self`를 매개변수로 전달해야 하는 이유는, `OnCardClicked` 함수가 **어떤 Card가 클릭되었는지**를 직접 알 수 없기 때문입니다. `OnCardClicked` 함수는 `CardPairGameLogic` (또는 관련 로직 컴포넌트) 에 정의되어 있으며, 이 함수는 클릭 이벤트가 발생했다는 사실만 알지 구체적인 대상 객체를 모릅니다. 따라서 `Card` 컴포넌트의 `HandleButtonClickEvent` 핸들러에서 `self`를 전달함으로 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 1. **CardBoard** 컴포넌트에서 새로운 프로퍼티를 추가하고 프로퍼티 타입을 **Component**로 지정합니다. ```lua Property: [None] Card SelectedCard = nil ``` 2. CardBoard 컴포넌트에서 `SelctCard` 함수를 찾습니다. 매개 변수를 추가하고 타입을 Component로 변경합니다. Component를 **Card**로 지정합니다. ```lua [client only] void SelectCard (C
[task] | two_turn [pass] | ⏳ 미판정 [title] | 스크립트 라이프 사이클 [question] | 메이플스토리 월드에서 스크립트 라이프 사이클이 제작 중 월드와 출시된 월드에서 어떻게 다른가요? [answer] | 메이플스토리 월드에서 스크립트 라이프 사이클은 **제작 중인 월드**와 **출시된 월드**에서 맵 불러오기 방식과 엔티티 생명주기 호출에 차이가 있습니다. ### 1. 맵 불러오기 방식 차이 * **제작 중인 월드:** 플레이어가 있는 맵만 불러옵니다. 10개의 맵을 만들었더라도 현재 테스트 플레이 중인 맵만 로드됩니다. * **출시된 월드:** 플레이어 유무와 상관없이 서버는 시작 시 **모든 맵**을 불러옵니다. 클라이언트는 여전히 플레이어 엔티티가 존재하는 맵만 불러옵니다. ### 2. 엔티티 생명주기(OnBegin [followup] | 출시된 월드에서 서버와 클라이언트 각각 어떤 맵을 불러오며, `OnBeginPlay` 같은 생명주기 함수 호출에 어떤 차이가 있나요? [followup_answer] | 출시된 월드에서 서버와 클라이언트는 맵을 불러오는 방식이 달라지며, 이로 인해 `OnBeginPlay` 등 생명주기 함수가 호출되는 엔티티의 범위에도 차이가 있습니다. ### 1. 맵 불러오기 방식 * **서버:** 게임 시작 시 **전체 맵**을 모두 불러옵니다. 플레이어의 위치나 유무와 관계없이 월드에 존재하는 모든 맵이 로드됩니다. * **클라이언트:** 플레이어의 엔티티가 **존재하는 맵만** 불러옵니다. 플레이어가 이동하지 않는 한 다른 맵은 로드되지 않습니다. ### 2. 생명주기 함수(`OnBeginPlay` [scores] | [judge_reason] | [source_doc] | 서버와 클라이언트가 호출되는 전체 흐름을 알아봅시다. 플레이 라이프 사이클은 **제작 중인 월드**와 **출시된 월드**에서 약간의 차이가 있습니다. 가장 큰 차이점은 맵을 불러오는 방식입니다. * **제작 중인 월드**에서 플레이할 때는 10개의 맵을 만들었더라도 플레이어가 있는 맵만 불러옵니다. * **출시된 월드**에서는 플레이어 유무와 상관없이 모든 맵을 불러옵니다. 이와 같은 차이를 알고 있다면 **제작 중인 월드** 또는 **출시된 월드**에서 크리에이터 의도대로 동작하지 않는 무언가가 있을 때, 그 원인이 잘못된
[task] | single_turn [pass] | ⏳ 미판정 [title] | 카드 섞기, 선택하기 [question] | OnCardClicked 함수 내에서 isvalid 체크를 생략하면 어떤 문제가 발생할 수 있나요? [answer] | `OnCardClicked` 함수에서 `isvalid` 체크를 생략하면, 참조가 더 이상 유효하지 않은 상태인 객체(예: 이미 제거(destroy)된 엔티티나 nil로 설정된 값)에 메서드를 호출하거나 프로퍼티에 접근하게 되어 런타임 에러가 발생할 수 있습니다. 특히 카드 짝 맞추기 게임 로직에서는 카드가 매칭되면 `SetDestroyed()`가 호출되어 해당 카드 객체가 비활성화되거나 삭제될 수 있습니다. 만약 이미 파괴된 카드 객체를 `cardboard.SelectedCard`로 가지고 있거나, 이벤트가 전달된 `card` 파 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 1. **CardBoard** 컴포넌트에서 새로운 프로퍼티를 추가하고 프로퍼티 타입을 **Component**로 지정합니다. ```lua Property: [None] Card SelectedCard = nil ``` 2. CardBoard 컴포넌트에서 `SelctCard` 함수를 찾습니다. 매개 변수를 추가하고 타입을 Component로 변경합니다. Component를 **Card**로 지정합니다. ```lua [client only] void SelectCard (C
[task] | two_turn [pass] | ⏳ 미판정 [title] | 공동 제작 [question] | 복구 모드를 켤 수 있는 권한이 있는 사용자 유형과, 두 가지 다른 경로(월드 관리 창, Cooperation 창)를 통해 복구 모드를 활성화하는 구체적인 방법은 무엇인가요? [answer] | 복구 모드를 켤 수 있는 권한이 있는 사용자 유형은 **그룹장** 또는 **매니저**입니다. 두 가지 다른 경로를 통해 복구 모드를 활성화하는 구체적인 방법은 다음과 같습니다. 1. **월드 관리 창에서 복구 모드 켜기** 로비에서 '만들기' 메뉴의 `[⋯]` 버튼을 클릭한 후 '월드 관리'로 이동하여 '복구 모드 켜기'를 선택합니다. 2. **Cooperation 창에서 복구 모드 켜기** 메이커(Maker) 환경에서 `Panels - Cooperation - Members` 경로를 따라 들어가 '복구 모드 켜기' [followup] | 매니저가 Cooperation 창을 통해 복구 모드를 켜는 단계별 조작 순서와, 이 과정에서 발생할 수 있는 다른 멤버들의 메이커 접속 상태 관련 예외 상황은 어떻게 처리해야 하나요? [followup_answer] | 매니저가 Cooperation 창을 통해 복구 모드를 켜는 단계별 조작 순서는 다음과 같습니다. 1. 메이커에서 `Panels - Cooperation` 메뉴를 엽니다. 2. `Members` 섹션으로 이동합니다. 3. `복구 모드 켜기`를 선택합니다. 이 과정에서 발생할 수 있는 다른 멤버들의 메이커 접속 상태 관련 예외 상황 및 처리 방법은 다음과 같습니다. * **예외 상황:** 아직 다른 멤버가 메이커에 접속 중인 상태에서 복구 모드를 켜는 경우입니다. * **처리 방법:** 복구 모드를 켜면 체크인하지 않은 작 [scores] | [judge_reason] | [source_doc] | 함께 제작하는 그룹 월드에서 **Panels - Cooperation**을 누릅니다. 해당 월드에 함께 접속 중인 사람들의 닉네임과 메이커 아이디가 보입니다. ## Local Changes 그룹 월드에서 작업자가 Check Out한 항목을 모아 볼 수 있는 창입니다. Hierarchy, Workspace에서 내가 변경한 항목을 확인하고, 한 번에 **Check In**할 수 있습니다. **Panels - Cooperation - Local Changes**를 눌러 창을 엽니다. ## 복구 모드 그룹 월드의 리비전을 되돌리기나
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 여러 개의 카드 보여주기 [question] | CardBoard 컴포넌트의 SetCards() 함수에서 _DataService를 활용하여 카드 데이터를 불러오고 섞는 과정을 설명할 때, '3문장 이내로' 작성하세요. [answer] | `_DataService:GetRowCount("CardSet")`으로 데이터셋의 행 개수를 구하고, `GetCell`로 각 행의 카드 RUID를 `deckTable`에 수집합니다. 이후 무작위 인덱스를 선택하여 원소의 위치를 서로 교환하는 방식으로 `deckTable`을 섞습니다. 마지막으로 섞인 데이터를 순서대로 `cardTable`에 삽입하여 카드 배치에 사용할 준비를 마칩니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 하나의 카드를 보여주는 것에 성공했으니, 이제는 모든 카드를 켜줄 차례입니다. 아래 그림과 같이 모든 카드가 나타나게 만들어 봅시다. # 여러 개의 카드 보여주기 하나의 카드가 잘 나타나는 걸 확인했으니 이제는 모든 카드를 모든 카드를 뒤섞어 보여줄 차례입니다. 이 과정에서 다양한 함수와 이전에 완성한 **CardSet** 데이터 셋을 활용합니다. [DataService](/apiReference/Services/DataService)를 참고하세요. 1. **Card** 컴포넌트를 활용해 여러 개의 RUID 값을 가지고 올 수
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 여러 개의 카드 보여주기 [question] | 카드 생성 루프에서 SpriteRUID를 할당하는 두 가지 컴포넌트 접근 방법을 나열하는 표로 정리하세요. [answer] | 카드 생성 루프에서 `SpriteRUID`를 할당하는 두 가지 컴포넌트 접근 방법은 다음과 같습니다. | 접근 방법 | 코드 예시 | 설명 | | :--- | :--- | :--- | | `Card` 스크립트 프로퍼티 직접 접근 | `card.Card.SpriteRUID = spriteRUID` | 생성된 엔티티(`card`)에 붙어있는 `Card` 컴포넌트의 `SpriteRUID` 프로퍼티를 직접 설정합니다. | | `SpriteGUIRendererComponent` 접근 | `card.SpriteGUIRendererCompon [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | ```lua local cardCount = #cardTable for i = 1, cardCount do local spriteRUID = cardTable[i] ``` 6. `CreateCardEntities()` 함수에서 `local card = _SpawnService:SpawnByModelId(cardModelId, "Card", Vector3(0,0,0), self.CardSpawnRoot)`를 찾습니다. `"Card"` 부분을 `"Card " .. tostring(i)`로 변경하며 아
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 여러 개의 카드 보여주기 [question] | CreateCardEntities() 함수의 시그니처를 table 타입의 매개변수를 받도록 수정한 내용을, '코드만 출력하고 설명은 주석으로' 작성하세요. [answer] | ```lua Property: [None] Entity CardSpawnRoot = /ui/CardParirGameUi/UI_Board/UI_Blocks/UI_Block_Group Method: [client only] void CreateCardEntities (table cardTable) { local cardModelId = "Model_Card EntiryID" -- cardTable 을 기반으로 카드 엔티티 생성 로직 } ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 하나의 카드를 보여주는 것에 성공했으니, 이제는 모든 카드를 켜줄 차례입니다. 아래 그림과 같이 모든 카드가 나타나게 만들어 봅시다. # 여러 개의 카드 보여주기 하나의 카드가 잘 나타나는 걸 확인했으니 이제는 모든 카드를 모든 카드를 뒤섞어 보여줄 차례입니다. 이 과정에서 다양한 함수와 이전에 완성한 **CardSet** 데이터 셋을 활용합니다. [DataService](/apiReference/Services/DataService)를 참고하세요. 1. **Card** 컴포넌트를 활용해 여러 개의 RUID 값을 가지고 올 수
[task] | single_turn [pass] | ⏳ 미판정 [title] | 스크립트 라이프 사이클 [question] | 서버와 클라이언트 모두에서 테스트 플레이용 월드가 생성된다고 하지만, 맵 로드 범위가 서버는 편집 중인 맵 또는 접근한 맵, 클라이언트는 플레이어 위치 맵으로 달라지는 이유가 무엇인지 설명해 주실 수 있나요? [answer] | 서버와 클라이언트의 맵 로드 범위가 다른 이유는 각 시스템이 담당하는 역할과 데이터 처리 방식이 다르기 때문입니다. **클라이언트 (Client)** 클라이언트는 사용자가 직접 보고 상호작용하는 화면을 렌더링하는 역할입니다. 따라서 네트워크 대역폭과 CPU/GPU 자원을 효율적으로 사용하기 위해, **플레이어 엔티티가 현재 존재하는 맵만** 불러옵니다. 이는 출시된 월드에서도 동일하게 적용되는 기본 원칙이며, 불필요한 맵 데이터를 전송하거나 처리하지 않음으로써 부드러운 플레이 경험을 제공합니다. **서버 (Server)** 서버 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 서버와 클라이언트가 호출되는 전체 흐름을 알아봅시다. 플레이 라이프 사이클은 **제작 중인 월드**와 **출시된 월드**에서 약간의 차이가 있습니다. 가장 큰 차이점은 맵을 불러오는 방식입니다. * **제작 중인 월드**에서 플레이할 때는 10개의 맵을 만들었더라도 플레이어가 있는 맵만 불러옵니다. * **출시된 월드**에서는 플레이어 유무와 상관없이 모든 맵을 불러옵니다. 이와 같은 차이를 알고 있다면 **제작 중인 월드** 또는 **출시된 월드**에서 크리에이터 의도대로 동작하지 않는 무언가가 있을 때, 그 원인이 잘못된
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 카드 섞기, 선택하기 [question] | CardPairGameLogic 스크립트의 StartGame 메서드와 OnBeginPlay 메서드 간의 호출 관계와 실행 공간([client only])을 표로 정리해서 출력하세요. [answer] | CardPairGameLogic 스크립트에서 `OnBeginPlay`와 `StartGame`의 관계는 다음과 같습니다. * **`OnBeginPlay`**: 스크립트가 실행 공간에 진입할 때 자동으로 호출되는 표준 생명주기 메서드입니다. 이 메서드 내부에서 `self:StartGame()`을 호출하여 게임 초기화 절차를 시작합니다. * **`StartGame`**: 게임 시작 로직을 수행하는 메서드입니다. UI를 활성화하고 카드 보드를 설정합니다. `OnBeginPlay`에 의해 간접적으로 호출됩니다. 두 메서드 모두 ` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | ```lua Property: [None] string SpriteRUID = "" Method: void CardOn () { self.Entity.SpriteGUIRendererComponent.Color = Color(81/255,81/255,81/255,1) } void CardOff () { self.Entity.SpriteGUIRendererComponent.Color = Color(255/255,255/255,255/255,1) } Event Handler: [self] HandleButtonClic
[task] | single_turn [pass] | ⏳ 미판정 [title] | 카드 섞기, 선택하기 [question] | 카드 짝 맞추기에서 `deckCount`의 절반만큼만 반복문을 돌리며 `table.insert`를 두 번 호출하는 것이 왜 필요한지 궁금합니다. [answer] | 카드 짝 맞추기 게임의 규칙상 한 쌍(2장)의 카드가 필요하기 때문입니다. `deckCount`의 절반만큼 반복문을 돌리고 `table.insert`를 두 번 호출하면, 동일한 카드(`deckTable[i]`)가 `cardTable`에 두 번씩 추가됩니다. 이렇게 하면 서로 같은 그림의 카드가 정확히 한 쌍씩 만들어져, 플레이어는 이 쌍을 찾아서 짝을 맞추는 게임을 진행할 수 있게 됩니다. 만약 `table.insert`를 한 번만 호출했다면 중복되는 카드가 없어 짝을 맞출 수 없게 되며, 두 번 이상 호출했다면 짝이 아닌 중복 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 카드 섞기 카드 보여주기에 성공했으니 이번에는 한 쌍의 카드가 나오게 만들어 봅시다. 1. **CardBoard** 컴포넌트의 `SetCards()` 함수에서 세 번째 `for i = 1, deckCount do`를 찾습니다. 처음에는 deckCount의 수만큼 실행했지만, 이번에는 deckCount의 절반만큼만 실행하기 위해 (deckCount / 2)로 변경합니다. 그 절반을 동일하게 두 번 불러와 쌍을 이루는 판을 만듭니다. `table.insert`는 [table](/apiReference/Lua/table) 레
[task] | code [pass] | ⏳ 미판정 [title] | 스크립트 라이프 사이클 [question] | `UserService`의 `UserEnterEvent` 이벤트 핸들러를 구현하여 플레이어 진입 시 `_SpawnService:SpawnByModelId`를 통해 특정 모델 ID의 엔티티를 스포awn하고, 해당 엔티티를 부모 엔티티로 설정하는 스크립트를 작성해줘 [answer] | 사용자가 요청한 `UserService`의 `UserEnterEvent` 이벤트 핸들러를 구현하고, 해당 이벤트 발생 시 `_SpawnService:SpawnByModelId`를 통해 엔티티를 스폰하며 부모를 설정하는 스크립트는 다음과 같습니다. 참고 문서에 따르면, `UserService`의 `UserEnterEvent` 이벤트 핸들러는 `[service: UserService]` 블록을 사용하며, 이벤트 인자로는 `event.UserId` 등을 활용할 수 있습니다. `_SpawnService:SpawnByModelId`는 모델 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 서버와 클라이언트가 호출되는 전체 흐름을 알아봅시다. 플레이 라이프 사이클은 **제작 중인 월드**와 **출시된 월드**에서 약간의 차이가 있습니다. 가장 큰 차이점은 맵을 불러오는 방식입니다. * **제작 중인 월드**에서 플레이할 때는 10개의 맵을 만들었더라도 플레이어가 있는 맵만 불러옵니다. * **출시된 월드**에서는 플레이어 유무와 상관없이 모든 맵을 불러옵니다. 이와 같은 차이를 알고 있다면 **제작 중인 월드** 또는 **출시된 월드**에서 크리에이터 의도대로 동작하지 않는 무언가가 있을 때, 그 원인이 잘못된
[task] | single_turn [pass] | ⏳ 미판정 [title] | 여러 개의 카드 보여주기 [question] | DataService의 GetRowCount 메서드를 사용할 때 매개변수로 데이터셋 이름을 어떻게 전달해야 하나요? [answer] | `DataService`의 `GetRowCount` 메서드는 데이터셋 이름을 문자열(string) 타입의 매개변수로 전달해야 합니다. 제공된 문서의 `SetCards()` 함수 예시를 보면, 데이터셋 이름 `"CardSet"`을 직접 문자열로 인수로 전달하는 방식을 사용하고 있습니다. ```lua local deckCount = _DataService:GetRowCount("CardSet") ``` 따라서 특정 데이터셋의 행 수를 구하려면, 해당 데이터셋의 이름을 큰따옴표(`"`)로 감싸서 문자열 형식으로 함수에 전달하면 됩니 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 하나의 카드를 보여주는 것에 성공했으니, 이제는 모든 카드를 켜줄 차례입니다. 아래 그림과 같이 모든 카드가 나타나게 만들어 봅시다. # 여러 개의 카드 보여주기 하나의 카드가 잘 나타나는 걸 확인했으니 이제는 모든 카드를 모든 카드를 뒤섞어 보여줄 차례입니다. 이 과정에서 다양한 함수와 이전에 완성한 **CardSet** 데이터 셋을 활용합니다. [DataService](/apiReference/Services/DataService)를 참고하세요. 1. **Card** 컴포넌트를 활용해 여러 개의 RUID 값을 가지고 올 수
[task] | single_turn [pass] | ⏳ 미판정 [title] | 카드 섞기, 선택하기 [question] | _CreateCardEntities에서 생성된 카드 엔티티에 card.Card.SpriteRUID와 card.SpriteGUIRendererComponent.ImageRUID를 모두 설정하는 이유는 무엇인가요? [answer] | `CreateCardEntities` 메서드에서 `card.Card.SpriteRUID`와 `card.SpriteGUIRendererComponent.ImageRUID`를 모두 설정하는 이유는 각각의 역할이 다르기 때문입니다. 1. **`card.Card.SpriteRUID` (데이터 저장 및 로직 사용)** * 이 값은 **Card 컴포넌트**의 프로퍼티로, 카드를 식별하는 **논리적 데이터**로 사용됩니다. * 참고 문서의 `Card` 컴포넌트 예제에서 `IsPairOf` 메서드를 보면, 두 카드가 짝인 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | ```lua Property: [None] Entity CardSpawnRoot = /ui/CardParirGameUi/UI_Board/UI_Blocks/UI_Block_Group [None] Card SelectedCard = nil Method: [client only] Void SetCards() { local deckTable = {} local cardTable = {} local deckCount = _DataService:GetRowCount("CardSet")