← 목록

mLua · Nemotron SDG 질문-응답 (SFT)

총 21,567개 · 페이지 348/719
🔀 랜덤
불러오는 중…

[task] | two_turn [pass] | ⏳ 미판정 [title] | Data DB 저장 및 불러오기 [question] | GlobalDataStorage를 통해 게임 데이터 저장과 불러오기를 구현하는 기본 과정은 무엇인가요? [answer] | GlobalDataStorage를 통해 게임 데이터를 저장하고 불러오기 위한 기본 과정은 다음과 같습니다. **1. GlobalDataStorage 생성 및 조회** 데이터를 저장하거나 불러올 대상인 `GlobalDataStorage` 객체를 생성하거나 기존 객체를 조회합니다. 이는 `_DataStorageService:GetGlobalDataStorage(name)` 함수를 사용하여 수행합니다. * `name` 인자에 따라 고유한 `GlobalDataStorage`가 생성되며, 이미 해당 이름의 객체가 존재하면 기존 객체를 [followup] | GetGlobalDataStorage의 name 매개변수 역할과 Server Only 제약 조건에 따른 서버 공간에서의 올바른 호출 예제 코드를 작성해 주세요. [followup_answer] | `_DataStorageService:GetGlobalDataStorage`의 `name` 매개변수는 `GlobalDataStorage` 객체를 식별하는 역할을 합니다. 1. **생성 및 조회 구분**: `name` 값에 따라 `GlobalDataStorage`가 생성되거나 기존 객체가 반환됩니다. * 해당 `name`이 처음인 경우: 새로운 `GlobalDataStorage`를 생성하여 반환합니다. * 해당 `name`이 이미 등록된 경우: 이전에 생성했던 `GlobalDataStorage` 객체를 반환합 [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 게임 중 변경된 데이터 값을 GlobalDataStorage에 저장하고 불러오는 방법에 대해 알아봅니다. # Data 생성 및 불러오기 GlobalDataStorage는 데이터의 저장과 불러오기를 할 수 있는 "보관소"라 할 수 있습니다. 우리는 데이터베이스에서 데이터를 저장하거나 불러올 일이 있을 때 이 "보관소"를 이용하면 됩니다. GlobalDataStorage는 `_DataStorageService:GetGlobalDataStorage`를 통해 생성하거나 불러오기가 가능합니다. GetGlobalDat

[task] | code [pass] | ⏳ 미판정 [title] | 아이템 생성 및 삭제 [question] | TriggerEnterEvent 의 TriggerBodyEntity 가 가진 InventoryComponent 의 아이템을 _ItemService:RemoveItem() 으로 삭제하는 ItemDelete 스크립트를 작성해줘 [answer] | ```lua Event Handler: [self] HandleTriggerEnterEvent(TriggerEnterEvent event) { --Parameters local TriggerBodyEntity = event.TriggerBodyEntity -------------------------------------------------------- local inventory = TriggerBodyEntity.InventoryComponent local items = inventory:G [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | **Preset List**에서 임의의 엔티티를 배치합니다. 그리고 **ItemDelete**라는 이름의 스크립트 컴포넌트를 추가합니다. **ItemDelete** 스크립트를 열고, **TriggerEnterEvent**를 추가합니다. 그리고 아래와 같이 내용을 작성합니다. ```lua [self] HandleTriggerEnterEvent(TriggerEnterEvent event) { --Parameters local TriggerBodyEntity = event.TriggerBodyEntity

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 스킬 이펙트를 뿌려보자! [question] | `PlayEffectAttached`에서 `localPosition`이 `Vector3(0,0,0)`일 때 이펙트가 생성되는 위치를 1문장으로 설명하고 [answer] | `localPosition`이 `Vector3(0,0,0)`일 때 이펙트는 부모 엔티티와 동일한 위치에 생성됩니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 메이플스토리에서 사용되었던 수많은 이펙트 리소스들을 제공하고 있습니다. 그리고 우리는 이러한 이펙트들을 적절한 시점과 위치에 호출해 줌으로써 한층 더 멋진 연출을 구사할 수 있습니다. 이번 과정에서는 특정 키를 누를 때마다 스킬 이펙트가 노출되는 예제를 진행해봄으로써 스크립트를 통해 이펙트를 호출하는 방법에 대해 알아보도록 합니다. 다음 가이드를 먼저 학습하면 이번 과정을 진행하는 데 많은 도움이 될 것입니다. [스크립트 에디터 오리엔테이션](https://mod-developers.

[task] | single_turn [pass] | ⏳ 미판정 [title] | Data DB 저장 및 불러오기 [question] | GlobalDataStorage의 SetAsync를 호출한 직후 같은 key로 값을 다시 저장하면 이전 값이 즉시 덮어씌워지나요? [answer] | 아니요, 즉시 덮어씌워지지 않습니다. `SetAsync`는 비동기식으로 동작하며, 호출 시점에 값이 DB에 저장되는 것이 아니라 저장 요청만 보냅니다. 요청받은 DB는 이전에 들어온 요청들부터 순차적으로 저장을 수행하기 때문에, `SetAsync` 호출 뒤에 바로 같은 key로 다시 `SetAsync`를 호출하더라도 어떤 값이 최종적으로 저장될지 그 시점은 보장되지 않습니다. 따라서 `SetAsync` 호출 직후 같은 key로 값을 다시 저장하면, 두 요청이 DB에 순서대로 처리되어 나중에 요청한 값이 최종적으로 저장될 가능성이 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 데이터의 저장은 GlobalDataStorage의 SetAsync를 활용해 할 수 있습니다. `SetAsync`는 매개 변수로 key와 value, 그리고 콜백 함수를 받는데, 저장할 데이터가 있으면 key와 value 매개 변수로 값을 넘겨 저장하게 됩니다. key는 매번 변경되어 저장되는 value 값을 불러오기 위한 용도로 사용됩니다. 따라서 key 값으로는 프로퍼티 명이나 혹은 저장된 value 값이 의미하는 것으로 입력해 주는 것이 좋습니다. 예를 들어 power라는 프로퍼티(또는 스탯)의 값을 저장한다면 key에는 "Po

[task] | code [pass] | ⏳ 미판정 [title] | 아이템 생성 및 삭제 [question] | HandleTriggerEnterEvent 이벤트 핸들러에서 event.TriggerBodyEntity 의 InventoryComponent 를 통해 아이템 목록을 순회하며 _ItemService:RemoveItem() 을 호출하여 인벤토리 비우기 기능을 만드는 스크립트를 작성해줘 [answer] | 요청하신 대로 `event.TriggerBodyEntity`의 `InventoryComponent`를 통해 아이템 목록을 순회하며 `_ItemService:RemoveItem()`을 호출하는 스크립트 컴포넌트입니다. ```lua Event Handler: [self] HandleTriggerEnterEvent(TriggerEnterEvent event) { --Parameters local TriggerBodyEntity = event.TriggerBodyEntity ----------------------- [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | **Preset List**에서 임의의 엔티티를 배치합니다. 그리고 **ItemDelete**라는 이름의 스크립트 컴포넌트를 추가합니다. **ItemDelete** 스크립트를 열고, **TriggerEnterEvent**를 추가합니다. 그리고 아래와 같이 내용을 작성합니다. ```lua [self] HandleTriggerEnterEvent(TriggerEnterEvent event) { --Parameters local TriggerBodyEntity = event.TriggerBodyEntity

[task] | single_turn [pass] | ⏳ 미판정 [title] | Data DB 저장 및 불러오기 [question] | SetAsync 함수의 세 번째 매개변수인 콜백 함수에 nil을 전달할 경우 어떤 결과가 발생합니까? [answer] | 콜백 함수에 `nil`을 전달하면 데이터 저장 요청(`SetAsync`)은 정상적으로 수행되지만, 저장이 완료되었을 때 호출되는 콜백 처리가 실행되지 않습니다. 즉, 저장이 성공했는지 여부에 대한 알림이나 저장 완료 시점의 추가 로직을 처리할 수 없게 됩니다. 참고 문서에 따르면, "만일 콜백 함수를 등록하지 않으려면 nil을 넘겨줍니다."라고 명시되어 있어, `nil`은 콜백을 생략하는 표준적인 방법입니다. ```lua Property: [Sync] number Power = 100 Method: [server only [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 데이터의 저장은 GlobalDataStorage의 SetAsync를 활용해 할 수 있습니다. `SetAsync`는 매개 변수로 key와 value, 그리고 콜백 함수를 받는데, 저장할 데이터가 있으면 key와 value 매개 변수로 값을 넘겨 저장하게 됩니다. key는 매번 변경되어 저장되는 value 값을 불러오기 위한 용도로 사용됩니다. 따라서 key 값으로는 프로퍼티 명이나 혹은 저장된 value 값이 의미하는 것으로 입력해 주는 것이 좋습니다. 예를 들어 power라는 프로퍼티(또는 스탯)의 값을 저장한다면 key에는 "Po

[task] | code [pass] | ⏳ 미판정 [title] | 아이템 생성 및 삭제 [question] | TriggerEnterEvent 를 처리하여 이벤트의 TriggerBodyEntity 에서 InventoryComponent 의 GetItemList() 로 아이템 목록을 조회하고 _ItemService:RemoveItem() 으로 각 아이템을 삭제하는 ItemDelete 스크립트를 작성해줘 [answer] | 요청하신 `ItemDelete` 스크립트는 `TriggerEnterEvent` 핸들러를 통해 트리거 영역에 진입한 엔티티(`TriggerBodyEntity`)의 인벤토리에서 모든 아이템을 조회하고, `_ItemService:RemoveItem()` 메서드를 호출하여 순차적으로 삭제하는 방식으로 구현됩니다. ```lua Event Handler: [self] HandleTriggerEnterEvent(TriggerEnterEvent event) { --Parameters local TriggerBodyEntity = [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | **Preset List**에서 임의의 엔티티를 배치합니다. 그리고 **ItemDelete**라는 이름의 스크립트 컴포넌트를 추가합니다. **ItemDelete** 스크립트를 열고, **TriggerEnterEvent**를 추가합니다. 그리고 아래와 같이 내용을 작성합니다. ```lua [self] HandleTriggerEnterEvent(TriggerEnterEvent event) { --Parameters local TriggerBodyEntity = event.TriggerBodyEntity

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 데이터 편집 [question] | GoogleSpreadSheet 데이터 가져오기 시 사용할 수 있는 URL의 조건과 CSV 파일 불러오기 시 정상적으로 동작하기 위한 인코딩 방식을 표로 정리해서 작성하세요. [answer] | 요청하신 GoogleSpreadSheet URL 조건과 CSV 파일 인코딩 방식은 다음과 같습니다. | 구분 | 조건 | | :--- | :--- | | **GoogleSpreadSheet URL** | 웹에 게시한 URL만 사용할 수 있습니다. | | **CSV 파일 인코딩** | `utf-8`로 저장된 파일만 정상적으로 가져올 수 있습니다. | [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 데이터 셋을 이용해 데이터를 추가하거나 수정할 수 있습니다. 이번 가이드에서는 데이터의 생성 및 편집 방법, 스크립트로 데이터를 불러오는 방법에 대해 알아봅니다. # 데이터 셋 생성 및 데이터 에디터 열기 1. **Workspace - MyDesk**의 콘텍스트 메뉴에서 **Create DataSet**을 클릭합니다. 2. 생성된 데이터를 더블클릭하여 데이터 에디터를 엽니다. # 데이터 에디터 | 번호 | 설명 | | --- | --- | | | **컬럼 셀** 각 열의 데이터명, 즉 컬럼 명을 정의합

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 데이터 편집 [question] | `_DataService:GetTable`과 `UserDataSet:GetCell`을 사용하여 3행 2열의 데이터를 콘솔에 출력하는 `OnBeginPlay()` 함수 코드만 출력하고 설명은 주석으로 작성하세요. [answer] | ```lua [server only] void OnBeginPlay() { -- 데이터셋 이름으로 테이블 객체를 가져옵니다. local dataSet = _DataService:GetTable("NewDataSet") -- 3행 2열에 해당하는 셀의 값을 문자열로 가져옵니다. local cellValue = dataSet:GetCell(3, 2) -- 콘솔에 가져온 값을 출력합니다. log("cellValue : " .. tostring(cellValue)) } ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 데이터 셋을 이용해 데이터를 추가하거나 수정할 수 있습니다. 이번 가이드에서는 데이터의 생성 및 편집 방법, 스크립트로 데이터를 불러오는 방법에 대해 알아봅니다. # 데이터 셋 생성 및 데이터 에디터 열기 1. **Workspace - MyDesk**의 콘텍스트 메뉴에서 **Create DataSet**을 클릭합니다. 2. 생성된 데이터를 더블클릭하여 데이터 에디터를 엽니다. # 데이터 에디터 | 번호 | 설명 | | --- | --- | | | **컬럼 셀** 각 열의 데이터명, 즉 컬럼 명을 정의합

[task] | single_turn [pass] | ⏳ 미판정 [title] | Data DB 저장 및 불러오기 [question] | 데이터 스토리지에서 특정 키를 불러왔는데 값이 nil로 나오면 어떻게 처리해야 하나요? [answer] | 데이터 스토리지에서 특정 키를 불러왔을 때 값이 `nil`로 나오는 경우, 해당 키에 저장된 데이터가 존재하지 않는 것을 의미합니다. 이 상황을 처리하려면 `GetAsync` 메서드에 전달하는 콜백 함수 내부에서 `value` 매개 변수가 `nil`인지 확인하고, 그에 맞는 기본값을 지정하거나 다른 로직을 수행해야 합니다. 다음은 `value`가 `nil`인 경우를 체크하여 기본값을 적용하는 mLua 코드 예시입니다. ```lua Property: [Sync] number Power = 0 Method: [server o [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | `GetAsync`는 데이터를 불러오기 위한 함수로 value 값 저장 시 함께 저장된 key 값을 통해 value 값을 가져옵니다. 이때 GetAsync도 SetAsync와 마찬가지로 key 값에 해당하는 value 값을 요청하게 되는데, 요청한 value 값을 함수 내에서 직접 리턴 받는 것이 아닌 GetAsync에 등록한 콜백 함수의 매개 변수로 key 값과 함께 들어옵니다. 이유는 GetAsync 역시 비동기식으로 동작을 하기 때문에 불러오기 요청을 보냈을 때 value 값을 언제 보내줄지는 보장되지 않기 때문입니다. 따라서

[task] | single_turn [pass] | ⏳ 미판정 [title] | Data DB 저장 및 불러오기 [question] | 서버와 클라이언트 모두에서 데이터를 수정해야 하는 경우, GlobalDataStorage를 어떻게 구분해서 사용해야 하나요? [answer] | GlobalDataStorage는 `_DataStorageService:GetGlobalDataStorage`가 **Server Only** 함수이므로, 클라이언트 공간에서 직접 GlobalDataStorage를 생성하거나 데이터를 수정(저장/불러오기)할 수 없습니다. 따라서 서버와 클라이언트 모두에서 데이터를 수정해야 하는 상황에서는 다음과 같이 처리해야 합니다. 1. **서버 공간**: `_DataStorageService:GetGlobalDataStorage`를 사용하여 GlobalDataStorage를 생성하고, `SetA [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 게임 중 변경된 데이터 값을 GlobalDataStorage에 저장하고 불러오는 방법에 대해 알아봅니다. # Data 생성 및 불러오기 GlobalDataStorage는 데이터의 저장과 불러오기를 할 수 있는 "보관소"라 할 수 있습니다. 우리는 데이터베이스에서 데이터를 저장하거나 불러올 일이 있을 때 이 "보관소"를 이용하면 됩니다. GlobalDataStorage는 `_DataStorageService:GetGlobalDataStorage`를 통해 생성하거나 불러오기가 가능합니다. GetGlobalDat

[task] | single_turn [pass] | ⏳ 미판정 [title] | 아이템 생성 및 삭제 [question] | GiftBox 스크립트에서 5초 후 아이템이 다시 나타나도록 예약할 때 self.Entity:SetEnable(false)를 먼저 호출해야 하는 이유는 무엇인가요? [answer] | GiftBox 스크립트에서 `self.Entity:SetEnable(false)`를 타이머 예약(`_TimerService:SetTimerOnce`) **이후**에 호출하는 이유는, 타이머 콜백 내부에서 엔티티를 다시 활성화할 때 해당 엔티티가 여전히 유효한 상태여야 하기 때문입니다. 구체적인 흐름은 다음과 같습니다. 1. **즉시 비활성화:** 캐릭터가 아이템과 충돌하면 `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] | Data DB 저장 및 불러오기 [question] | 테스트 플레이 중 저장된 데이터는 플레이 종료 후에도 유지되는 것이 맞나요? [answer] | 네, 맞습니다. 테스트 플레이 중 저장된 데이터는 플레이를 종료해도 사라지지 않고 유지됩니다. 이 데이터를 초기화하려면 **Setting - 만들기 - 데이터 스토리지 설정**에서 처리할 수 있습니다. [followup] | 이 데이터를 초기화할 수 있는 설정 경로(Setting - 만들기 - 데이터 스토리지 설정)가 어디인지 알려 주세요. [followup_answer] | 데이터 스토리지 초기화 설정 경로는 **Setting - 만들기 - 데이터 스토리지 설정**입니다. [scores] | [judge_reason] | [source_doc] | `GetAsync`는 데이터를 불러오기 위한 함수로 value 값 저장 시 함께 저장된 key 값을 통해 value 값을 가져옵니다. 이때 GetAsync도 SetAsync와 마찬가지로 key 값에 해당하는 value 값을 요청하게 되는데, 요청한 value 값을 함수 내에서 직접 리턴 받는 것이 아닌 GetAsync에 등록한 콜백 함수의 매개 변수로 key 값과 함께 들어옵니다. 이유는 GetAsync 역시 비동기식으로 동작을 하기 때문에 불러오기 요청을 보냈을 때 value 값을 언제 보내줄지는 보장되지 않기 때문입니다. 따라서

[task] | single_turn [pass] | ⏳ 미판정 [title] | Data DB 저장 및 불러오기 [question] | GetAsync의 콜백 함수 매개변수로 넘어오는 값 중 key와 value는 각각 어떤 용도로 사용되나요? [answer] | `GetAsync`의 콜백 함수에 매개변수로 넘어오는 `key`와 `value`의 용도는 다음과 같습니다. * **key**: 요청한 데이터의 키 값입니다. 저장할 때 사용했던 키 값과 동일하게 전달되며, 여러 개의 데이터를 동시에 요청하거나 키 값이 여러 개인 경우 어떤 데이터의 결과를 받은 것인지 식별하는 데 사용됩니다. * **value**: `key`에 해당하는 실제 데이터 값입니다. 이 값은 문자열(string) 형태로 전달되며, 필요한 경우 `tonumber` 등의 함수를 사용하여 숫자 등 다른 타입으로 변환하여 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | `GetAsync`는 데이터를 불러오기 위한 함수로 value 값 저장 시 함께 저장된 key 값을 통해 value 값을 가져옵니다. 이때 GetAsync도 SetAsync와 마찬가지로 key 값에 해당하는 value 값을 요청하게 되는데, 요청한 value 값을 함수 내에서 직접 리턴 받는 것이 아닌 GetAsync에 등록한 콜백 함수의 매개 변수로 key 값과 함께 들어옵니다. 이유는 GetAsync 역시 비동기식으로 동작을 하기 때문에 불러오기 요청을 보냈을 때 value 값을 언제 보내줄지는 보장되지 않기 때문입니다. 따라서

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 스킬 이펙트를 뿌려보자! [question] | Q, W, E, R 키 입력 시 로그 출력을 위한 HandleKeyDownEvent 코드만 출력하고, 설명은 주석으로 작성하세요. [answer] | ```lua Event Handler: [service: InputService] HandleKeyDownEvent(KeyDownEvent event) { -- 입력된 키를 변수에 저장합니다. local key = event.key -- Q, W, E, R 키가 눌렸을 때 각각의 키 이름이 콘솔에 로그로 출력되도록 처리합니다. if key == KeyboardKey.Q then log("Q") elseif key == KeyboardKey.W then log( [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 스킬 호출 기능에 앞서 간단하게 키 입력을 받는 기능을 먼저 만들어보겠습니다. 1. **Workspace**에서 새 컴포넌트를 추가하고, 이름으로 **NewSkill**을 입력합니다. 2. **NewSkill** 컴포넌트에 키 입력 이벤트를 처리할 핸들러를 추가합니다. **[+]** 버튼을 눌러 **KeyDownEvent**를 추가합니다. 3. **HandleKeyDownEvent**의 코드를 다음과 같이 작성해 줍니다. ```lua [service: InputService]

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 스킬 이펙트를 뿌려보자! [question] | KeyDownEvent 핸들러에 필요한 서비스 속성과 이벤트 이름, 그리고 파라미터 변수를 표로 정리해서 출력하세요. [answer] | KeyDownEvent 핸들러에 필요한 정보를 아래 표와 같이 정리했습니다. | 구분 | 내용 | | :--- | :--- | | **서비스 속성** | `[service: InputService]` | | **이벤트 이름** | `HandleKeyDownEvent` | | **파라미터 타입** | `KeyDownEvent` | | **파라미터 변수명** | `event` | | **접근 가능한 프로퍼티** | `event.key` (누른 키를 `KeyboardKey` 열거형으로 반환) | [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 스킬 호출 기능에 앞서 간단하게 키 입력을 받는 기능을 먼저 만들어보겠습니다. 1. **Workspace**에서 새 컴포넌트를 추가하고, 이름으로 **NewSkill**을 입력합니다. 2. **NewSkill** 컴포넌트에 키 입력 이벤트를 처리할 핸들러를 추가합니다. **[+]** 버튼을 눌러 **KeyDownEvent**를 추가합니다. 3. **HandleKeyDownEvent**의 코드를 다음과 같이 작성해 줍니다. ```lua [service: InputService]

[task] | single_turn [pass] | ⏳ 미판정 [title] | Data DB 저장 및 불러오기 [question] | DataStorageService를 통해 데이터를 불러올 때 SetAsync와 처리 방식이 다른 핵심적인 이유는 무엇인가요? [answer] | `GetAsync`가 `SetAsync`와 처리 방식이 다른 핵심적인 이유는 **비동기(Asynchronous) 동작** 때문입니다. `SetAsync`는 데이터를 저장하는 요청을 보내는 것이 주 목적이라, 저장 요청이 완료되었는지 확인하는 콜백만 간단히 등록하면 됩니다. 반면 `GetAsync`는 서버로부터 데이터를 **불러오는** 함수인데, 비동기 방식이기 때문에 요청을 보냈을 때 데이터(value)가 언제 도착하는지 보장되지 않습니다. 따라서 데이터를 즉시 받아서 사용할 수 없으므로, 데이터가 실제로 도착했을 때 그 값을 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | `GetAsync`는 데이터를 불러오기 위한 함수로 value 값 저장 시 함께 저장된 key 값을 통해 value 값을 가져옵니다. 이때 GetAsync도 SetAsync와 마찬가지로 key 값에 해당하는 value 값을 요청하게 되는데, 요청한 value 값을 함수 내에서 직접 리턴 받는 것이 아닌 GetAsync에 등록한 콜백 함수의 매개 변수로 key 값과 함께 들어옵니다. 이유는 GetAsync 역시 비동기식으로 동작을 하기 때문에 불러오기 요청을 보냈을 때 value 값을 언제 보내줄지는 보장되지 않기 때문입니다. 따라서

[task] | single_turn [pass] | ⏳ 미판정 [title] | Data DB 저장 및 불러오기 [question] | 데이터를 저장할 때 key 값을 프로퍼티 이름 대신 임의의 문자열로 지정해도 나중에 불러오기에 문제가 없나요? [answer] | 네, key 값을 프로퍼티 이름 대신 임의의 문자열로 지정해도 나중에 불러오기에 문제가 없습니다. 문서에서 key는 저장된 value 값을 다시 불러오기 위한 용도로 사용된다고 설명하고 있습니다. 프로퍼티 명을 key로 사용하는 것은 단순히 이해를 돕기 위한 권장 사항일 뿐, key 자체는 저장 시 설정한 문자열 그대로 유지됩니다. 데이터를 불러올 때(`GetAsync`)는 저장할 때 사용한 것과 동일한 key 값을 지정하면 됩니다. 예를 들어 저장할 때 key로 "MyCustomKey"를 사용했다면, 불러올 때도 반드시 "My [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 데이터의 저장은 GlobalDataStorage의 SetAsync를 활용해 할 수 있습니다. `SetAsync`는 매개 변수로 key와 value, 그리고 콜백 함수를 받는데, 저장할 데이터가 있으면 key와 value 매개 변수로 값을 넘겨 저장하게 됩니다. key는 매번 변경되어 저장되는 value 값을 불러오기 위한 용도로 사용됩니다. 따라서 key 값으로는 프로퍼티 명이나 혹은 저장된 value 값이 의미하는 것으로 입력해 주는 것이 좋습니다. 예를 들어 power라는 프로퍼티(또는 스탯)의 값을 저장한다면 key에는 "Po

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 스킬 이펙트를 뿌려보자! [question] | Workspace에서 컴포넌트를 추가부터 테스트까지의 단계를 단계별 번호 목록으로 정리하세요. [answer] | Workspace에서 컴포넌트를 추가부터 테스트까지의 단계는 다음과 같습니다. 1. **Workspace**에서 새 컴포넌트를 추가하고, 이름을 **NewSkill**로 입력합니다. 2. **NewSkill** 컴포넌트에 키 입력 이벤트를 처리할 핸들러를 추가합니다. **[+]** 버튼을 눌러 **KeyDownEvent**를 추가합니다. 3. **HandleKeyDownEvent**의 코드를 작성합니다. (예: Q, W, E, R 키 입력 시 로그 출력) 4. **Workspace - DefaultPlayer**의 프로퍼티 에디터 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 스킬 호출 기능에 앞서 간단하게 키 입력을 받는 기능을 먼저 만들어보겠습니다. 1. **Workspace**에서 새 컴포넌트를 추가하고, 이름으로 **NewSkill**을 입력합니다. 2. **NewSkill** 컴포넌트에 키 입력 이벤트를 처리할 핸들러를 추가합니다. **[+]** 버튼을 눌러 **KeyDownEvent**를 추가합니다. 3. **HandleKeyDownEvent**의 코드를 다음과 같이 작성해 줍니다. ```lua [service: InputService]

[task] | code [pass] | ⏳ 미판정 [title] | 맵 생성과 관리 [question] | HandleTouchEvent(TouchEvent event) 이벤트 핸들러를 이용해 포탈에 터치 시 TargetPortal 참조된 포탈의 Entity 경로 이름을 local 변수로 받아 self:MyMethod() 형태로 정의한 커스텀 메서드에서 log() 로 출력하는 스크립트를 작성해줘 [answer] | 제시된 참고 문서와 mLua 규칙에 기반하여 요청하신 스크립트를 작성했습니다. 참고 문서에서 확인 가능한 포탈 관련 프로퍼티는 `TargetPortal`이며, 이는 다른 포탈을 참조(Reference)하는 형식입니다. `HandleTouchEvent`는 `[self]` 블록에서 처리하며, 커스텀 메서드 호출 시 `self:Method()` 형식을 따릅니다. **주의사항:** 1. `TargetPortal`이 `Entity` 타입인지, `string`(경로) 타입인지, 또는 특수한 Reference 타입인지는 제공된 문서에 명시된 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 1. 연결하려는 맵에 포탈을 설치합니다. 2. 포탈의 프로퍼티 에디터에서 **TargetPortal**의 **[◉]** 버튼을 클릭합니다. 이후 **Reference** 팝업 창에서 이동할 포탈을 선택합니다. 3. **[시작]** 버튼을 클릭한 뒤, 출발 포탈에서 도착 포탈로 잘 이동하는지 확인합니다. # 마무리 좋은 맵의 크기와 개수는 정해진 답이 없습니다. 크리에이터의 기획에 맞게 여러 개의 맵을 만들거나, 하나의 커다란 맵을 만들어도 좋습니다. 그러나 맵이 너무 거대하거나 배치된 오브젝트가 많으면 로딩 및 플

[task] | two_turn [pass] | ⏳ 미판정 [title] | Data DB 저장 및 불러오기 [question] | 데이터 스토리지에서 값을 불러올 때 key에 해당하는 value가 없으면 어떤 값이 반환되나요? [answer] | key 값에 해당하는 value가 저장되어 있지 않은 상태에서 `GetAsync`를 호출하면, 콜백 함수의 `value` 매개변수로 **`nil`**이 전달됩니다. 따라서 데이터를 불러오는 콜백 함수 내에서 `value`가 `nil`인지를 확인하여, 저장된 값이 없을 경우의 기본값 처리를 해야 합니다. ```lua Property: [Sync] number Power = 0 Method: [server only] void OnBeginPlay() { local data = _DataStorageService:Get [followup] | nil 값 검출 후 기본값을 설정하는 로직이 포함된 OnBeginPlay 메서드 코드를 보여 주세요. [followup_answer] | `GetAsync`의 콜백 함수에서 `value`가 `nil`인 경우를 검출하여 기본값으로 처리하는 `OnBeginPlay` 메서드 코드는 다음과 같습니다. ```lua Property: [Sync] number Power = 0 Method: [server only] void OnBeginPlay() { local data = _DataStorageService:GetGlobalDataStorage("Data") local callBack = function(errorcode, key, value) [scores] | [judge_reason] | [source_doc] | `GetAsync`는 데이터를 불러오기 위한 함수로 value 값 저장 시 함께 저장된 key 값을 통해 value 값을 가져옵니다. 이때 GetAsync도 SetAsync와 마찬가지로 key 값에 해당하는 value 값을 요청하게 되는데, 요청한 value 값을 함수 내에서 직접 리턴 받는 것이 아닌 GetAsync에 등록한 콜백 함수의 매개 변수로 key 값과 함께 들어옵니다. 이유는 GetAsync 역시 비동기식으로 동작을 하기 때문에 불러오기 요청을 보냈을 때 value 값을 언제 보내줄지는 보장되지 않기 때문입니다. 따라서

[task] | two_turn [pass] | ⏳ 미판정 [title] | 스킬 이펙트를 뿌려보자! [question] | Workspace의 NewSkill 컴포넌트에 KeyDownEvent 핸들러를 추가하여 Q, W, E, R 키 입력을 감지하는 기본 구조는 어떻게 작성하나요? [answer] | Workspace에서 **NewSkill** 컴포넌트를 생성한 후, **KeyDownEvent** 핸들러를 추가하고 아래 코드와 같이 작성하면 Q, W, E, R 키 입력을 감지할 수 있습니다. ```lua Event Handler: [service: InputService] HandleKeyDownEvent(KeyDownEvent event) { -- Parameters local key = event.key ------------------------------------------------------ [followup] | HandleKeyDownEvent에서 event.key 값을 확인하여 특정 키(예: KeyboardKey.Q)가 눌렸을 때 실행되는 if-elseif 조건문 코드를 전체로 작성해 주세요. [followup_answer] | `HandleKeyDownEvent`에서 `event.key` 값을 확인하여 Q, W, E, R 키 입력을 감지하는 전체 코드는 다음과 같습니다. ```lua Event Handler: [service: InputService] HandleKeyDownEvent(KeyDownEvent event) { -- Parameters local key = event.key -------------------------------------------------------- if key == KeyboardKe [scores] | [judge_reason] | [source_doc] | 스킬 호출 기능에 앞서 간단하게 키 입력을 받는 기능을 먼저 만들어보겠습니다. 1. **Workspace**에서 새 컴포넌트를 추가하고, 이름으로 **NewSkill**을 입력합니다. 2. **NewSkill** 컴포넌트에 키 입력 이벤트를 처리할 핸들러를 추가합니다. **[+]** 버튼을 눌러 **KeyDownEvent**를 추가합니다. 3. **HandleKeyDownEvent**의 코드를 다음과 같이 작성해 줍니다. ```lua [service: InputService]

[task] | single_turn [pass] | ⏳ 미판정 [title] | 아이템 생성 및 삭제 [question] | ItemDelete 스크립트에서 local items = inventory:GetItemList() 로 가져온 리스트를 for index, item in pairs(items) 로 순회하며 삭제하는데, 이 과정에서 런타임 오류나 예상치 못한 동작이 발생할 수 있는 원인은 무엇인가요? [answer] | 제공된 참고 문서에 `for index, item in pairs(items)` 순회 중 런타임 오류나 예상치 못한 동작이 발생하는 구체적인 원인이나 경고 사항에 대한 설명은 포함되어 있지 않습니다. 문서에는 해당 코드가 동작하는 예시만 제시되어 있을 뿐, `_ItemService:RemoveItem(item)` 호출 시 리스트가 수정되어 발생하는 문제(예: 반복 중 요소 삭제에 따른 스킵이나 오류)에 대한 기술적 분석은 찾을 수 없습니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | **Preset List**에서 임의의 엔티티를 배치합니다. 그리고 **ItemDelete**라는 이름의 스크립트 컴포넌트를 추가합니다. **ItemDelete** 스크립트를 열고, **TriggerEnterEvent**를 추가합니다. 그리고 아래와 같이 내용을 작성합니다. ```lua [self] HandleTriggerEnterEvent(TriggerEnterEvent event) { --Parameters local TriggerBodyEntity = event.TriggerBodyEntity

[task] | two_turn [pass] | ⏳ 미판정 [title] | 아이템 생성 및 삭제 [question] | 맵에 놓인 아이템을 상호작용했을 때 인벤토리에 랜덤한 아이템을 생성하는 로직은 어떻게 구현하는가? [answer] | 맵에 놓인 아이템과 상호작용하여 인벤토리에 랜덤한 아이템을 생성하는 로직은 `_ItemService:CreateItem()` 메서드를 사용하여 구현합니다. 구현 시 주의할 점과 단계는 다음과 같습니다. 1. **ItemType 정의**: 먼저 생성할 아이템의 유형(ItemType)을 정의해야 합니다. (예: `Potion`) 2. **인벤토리 접근**: 상호작용 대상 엔티티의 스크립트에서 `self.Entity.InventoryComponent`를 통해 인벤토리에 접근합니다. 3. **랜덤 아이템 선택**: 인벤토리에 추가 [followup] | 특정 아이템 ID가 아닌 `UserItemDataSet`에 정의된 모든 아이템 중 하나를 무작위로 선택하여 `_EntityService`나 인벤토리 시스템에 추가하는 코드 예시를 보여줘. [followup_answer] | 제공된 참고 문서에는 `UserItemDataSet`의 모든 행을 조회하거나, DataSet에서 무작위로 아이템을 선택하는 API(예: `GetAllRows()`, `GetRandomItem()` 등)가 명시되어 있지 않습니다. 문서에 따르면, `_ItemService:CreateItem()`을 호출할 때 **ItemType**(예: `Potion`, `Sword` 등)을 직접 지정하여 생성하는 방식만 예시로 제시되어 있습니다. 또한, `UserItemDataSet`은 아이템의 데이터(이름, 아이콘, 스탯 등)를 저장하는 테이블이 [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 이번 과정에서는 아이템 생성과 삭제 기능을 알아봅니다. 제작할 예제는 다음과 같습니다. * 맵에 놓인 아이템을 먹을 때마다 인벤토리에 랜덤한 아이템이 생성 * 아이템을 먹으면, 5초 뒤 아이템이 놓여있던 자리에 다시 생성 * 맵에 놓인 다른 아이템을 먹을 때마다 인벤토리에 있는 모든 아이템 삭제 # 아이템 테이블 만들기 먼저 개별 아이템을 만들어 봅시다. 개별 아이템은 아이템 테이블에서 정의할 수 있습니다. 아이템 테이블은 **DataSet**으로 만듭니다. **Workspace - MyDesk**에서 콘

[task] | single_turn [pass] | ⏳ 미판정 [title] | Data DB 저장 및 불러오기 [question] | SetAsync의 콜백 함수에서 받은 errorcode와 key 매개변수를 활용해 저장 실패 여부를 어떻게 판단할 수 있나요? [answer] | 제공된 참고 문서에는 `SetAsync` 콜백 함수의 매개변수 `errorcode`와 `key`에 대한 **구체적인 값(예: 성공/실패를 나타내는 특정 숫자나 상수)과 그 의미에 대한 설명이 없습니다.** 문서에서는 다음과 같은 사실만 확인됩니다: 1. `SetAsync`의 콜백 함수는 데이터가 **저장되었을 때** 호출됩니다. 2. 콜백 함수는 `errorcode`와 `key` 두 개의 매개변수를 받습니다. 3. 예제 코드에서는 `errorcode` 값이 `0`인지 `1`인지 등 구체적인 비교 없이 단순히 `log(key. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 데이터의 저장은 GlobalDataStorage의 SetAsync를 활용해 할 수 있습니다. `SetAsync`는 매개 변수로 key와 value, 그리고 콜백 함수를 받는데, 저장할 데이터가 있으면 key와 value 매개 변수로 값을 넘겨 저장하게 됩니다. key는 매번 변경되어 저장되는 value 값을 불러오기 위한 용도로 사용됩니다. 따라서 key 값으로는 프로퍼티 명이나 혹은 저장된 value 값이 의미하는 것으로 입력해 주는 것이 좋습니다. 예를 들어 power라는 프로퍼티(또는 스탯)의 값을 저장한다면 key에는 "Po

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 스킬 이펙트를 뿌려보자! [question] | 예제에서 특정 키 입력 시 스킬 이펙트를 노출하는 흐름을 단계별 번호 목록으로 [answer] | 예제에서 특정 키 입력 시 스킬 이펙트를 노출하는 흐름은 다음과 같습니다. 1. `InputService`의 `KeyDownEvent` 이벤트 핸들러가 활성화됩니다. 2. 이벤트에서 전달된 `KeyDownEvent` 객체의 `key` 속성을 통해 현재 눌린 키를 확인합니다. 3. 눌린 키가 `KeyboardKey.LeftControl`인지 조건 분기를 통해 검사합니다. 4. 조건이 충족되면 `_SoundService`의 `PlaySound` 함수를 호출하여 지정된 RUID의 사운드를 재생합니다. 5. `_EffectSer [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 메이플스토리에서 사용되었던 수많은 이펙트 리소스들을 제공하고 있습니다. 그리고 우리는 이러한 이펙트들을 적절한 시점과 위치에 호출해 줌으로써 한층 더 멋진 연출을 구사할 수 있습니다. 이번 과정에서는 특정 키를 누를 때마다 스킬 이펙트가 노출되는 예제를 진행해봄으로써 스크립트를 통해 이펙트를 호출하는 방법에 대해 알아보도록 합니다. 다음 가이드를 먼저 학습하면 이번 과정을 진행하는 데 많은 도움이 될 것입니다. [스크립트 에디터 오리엔테이션](https://mod-developers.

[task] | single_turn [pass] | ⏳ 미판정 [title] | Data DB 저장 및 불러오기 [question] | 비동기 저장인 SetAsync 특성상 호출 직후 값을 읽으면 저장 전 값이 나올 수 있는데, 이를 방지하기 위해 권장되는 처리 방식은 무엇인가요? [answer] | `SetAsync`는 비동기 방식으로 동작하기 때문에, 함수 호출이 반환된 시점에는 데이터가 실제로 저장되지 않았을 수 있습니다. 따라서 `SetAsync` 호출 직후 바로 값을 읽으면 저장 전 값이 반환될 수 있습니다. 이 문제를 방지하기 위해 권장되는 처리 방식은 **콜백 함수(callback)를 활용하여 데이터가 실제로 저장된 시점에 후속 처리를 실행하는 것**입니다. `SetAsync`의 세 번째 매개변수로 콜백 함수를 전달하면, DB에서 저장 작업이 완료된 시점에 해당 함수가 호출되며 `errorCode`와 `key` 값 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 데이터의 저장은 GlobalDataStorage의 SetAsync를 활용해 할 수 있습니다. `SetAsync`는 매개 변수로 key와 value, 그리고 콜백 함수를 받는데, 저장할 데이터가 있으면 key와 value 매개 변수로 값을 넘겨 저장하게 됩니다. key는 매번 변경되어 저장되는 value 값을 불러오기 위한 용도로 사용됩니다. 따라서 key 값으로는 프로퍼티 명이나 혹은 저장된 value 값이 의미하는 것으로 입력해 주는 것이 좋습니다. 예를 들어 power라는 프로퍼티(또는 스탯)의 값을 저장한다면 key에는 "Po

[task] | code [pass] | ⏳ 미판정 [title] | 아이템 생성 및 삭제 [question] | TriggerComponent 와 ItemDelete 컴포넌트가 장착된 엔티티에 캐릭터가 닿을 때 InventoryComponent:GetItemList() 반환 값의 모든 아이템을 _ItemService:RemoveItem() 으로 제거하는 로직을 구현하는 스크립트를 작성해줘 [answer] | 요청하신 로직은 `TriggerEnterEvent` 이벤트 핸들러를 사용하여 트리거 영역에 진입한 캐릭터(`TriggerBodyEntity`)의 인벤토리를 조회하고, 해당 인벤토리에 있는 모든 아이템을 삭제하는 방식으로 구현할 수 있습니다. 아래는 **ItemDelete** 스크립트 컴포넌트의 예시입니다. 이 컴포넌트를 `TriggerComponent`와 함께 배치할 엔티티에 추가하고, `TriggerComponent`의 트리거 영역이 캐릭터와 상호작용하도록 설정하면 됩니다. ```lua Event Handler: [self] [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | **Preset List**에서 임의의 엔티티를 배치합니다. 그리고 **ItemDelete**라는 이름의 스크립트 컴포넌트를 추가합니다. **ItemDelete** 스크립트를 열고, **TriggerEnterEvent**를 추가합니다. 그리고 아래와 같이 내용을 작성합니다. ```lua [self] HandleTriggerEnterEvent(TriggerEnterEvent event) { --Parameters local TriggerBodyEntity = event.TriggerBodyEntity

[task] | code [pass] | ⏳ 미판정 [title] | Data DB 저장 및 불러오기 [question] | 서버 공간에서 `_DataStorageService:GetGlobalDataStorage`를 통해 "PlayerStats"라는 이름의 GlobalDataStorage를 생성하고, 특정 유저의 "Score" 값을 100으로 저장하는 스크립트를 작성해줘. [answer] | 요청하신 기능은 `GlobalDataStorage`를 생성하여 서버 공간에서 데이터 저장을 수행하는 것입니다. `_DataStorageService:GetGlobalDataStorage`는 Server Only 함수이므로 메서드 실행 공간은 `[server only]`로 설정해야 합니다. 저장할 값인 "Score"는 숫자 타입이지만, `SetAsync` 메서드의 값 매개변수는 문자열을 받기 때문에 `tostring()` 함수를 사용하여 변환 후 저장해야 합니다. 또한 저장이 완료되었음을 확인하기 위해 콜백 함수를 전달합니다. ` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 게임 중 변경된 데이터 값을 GlobalDataStorage에 저장하고 불러오는 방법에 대해 알아봅니다. # Data 생성 및 불러오기 GlobalDataStorage는 데이터의 저장과 불러오기를 할 수 있는 "보관소"라 할 수 있습니다. 우리는 데이터베이스에서 데이터를 저장하거나 불러올 일이 있을 때 이 "보관소"를 이용하면 됩니다. GlobalDataStorage는 `_DataStorageService:GetGlobalDataStorage`를 통해 생성하거나 불러오기가 가능합니다. GetGlobalDat

[task] | single_turn [pass] | ⏳ 미판정 [title] | 아이템 생성 및 삭제 [question] | TriggerEnterEvent는 캐릭터가 트리거 영역에 처음 들어갈 때만 한 번만 발화되므로, 영역 안에 머물러 있는 동안에도 계속 아이템이 삭제되도록 하려면 어떤 다른 이벤트 핸들러나 로직을 사용해야 하나요? [answer] | 제공된 참고 문서에는 `TriggerEnterEvent`가 처음 들어갈 때만 발화되며, 영역 안에 머물러 있는 동안 반복적으로 발화되는 이벤트(예: `TriggerStayEvent` 또는 유사한 이름의 이벤트)나 `OnUpdate`를 활용한 수동 체크 로직에 대한 설명이 포함되어 있지 않습니다. 따라서 제공된 문서 범위 내에서는 "영역 안에 머물러 있는 동안 계속 아이템이 삭제되도록" 하는 방법을 설명할 수 없습니다. 문서에 명시된 내용은 캐릭터가 트리거 영역에 **처음 닿는 시점(TriggerEnterEvent)** 에 인벤토리 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | **Preset List**에서 임의의 엔티티를 배치합니다. 그리고 **ItemDelete**라는 이름의 스크립트 컴포넌트를 추가합니다. **ItemDelete** 스크립트를 열고, **TriggerEnterEvent**를 추가합니다. 그리고 아래와 같이 내용을 작성합니다. ```lua [self] HandleTriggerEnterEvent(TriggerEnterEvent event) { --Parameters local TriggerBodyEntity = event.TriggerBodyEntity

← → 방향키로 페이지 이동 · 숫자 입력 후 Enter로 점프