← 목록

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

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

[task] | single_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | SpriteAnimPlayerChangeFrameEvent 를 구독한 뒤 애니메이션을 변경하면 왜 무한 루프가 발생하며, 이를 방지하기 위해 반드시 해야 할 처리는 무엇인가요? [answer] | `SpriteAnimPlayerChangeFrameEvent`를 구독한 상태에서 `ActionStateChangedEvent`를 보내어 애니메이션을 변경하면, 새로 재생되는 애니메이션의 프레임이 변경될 때마다 해당 이벤트가 다시 발생합니다. 구체적인 흐름은 다음과 같습니다. 1. `SpriteAnimPlayerChangeFrameEvent`가 발생하여 특정 프레임(예: 2번째 프레임)에 도달합니다. 2. 이벤트 핸들러에서 `ActionStateChangedEvent`를 보내어 다른 애니메이션(예: `swingOF`)으로 변경합니다 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 다음의 예제 코드를 보면서 **FrameEvent**의 사용법을 알아봅시다. 1. 어떤 아바타 애니메이션의 2번째 프레임이 재생될 때 다른 애니메이션으로 변경하고 싶다고 가정합니다. 그렇다면 **SpriteAnimPlayerChangeFrameEvent**를 활용할 수 있을 것입니다. `OnBeginPlay` 함수를 추가하고, 위에서 설명한 대로 이벤트를 **Body**와 연결합니다. 구독 취소를 대비해 연결한 이벤트의 핸들러는 프로퍼티로 가지고 있도록 합니다. ```lua Property: [None]

[task] | single_turn [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 메이플스토리 월드에서 전역 변수 대신 프로퍼티를 사용하라고 권장하는 이유는 무엇인가요? [answer] | 메이플스토리 월드에서는 전역 변수 사용을 권장하지 않습니다. 그 이유는 전역 변수처럼 사용해야 할 값이 있다면, 스크립트 컴포넌트의 **Property(프로퍼티)**를 사용하는 것이 더 적절하기 때문입니다. 프로퍼티는 스크립트 전체 범위에서 참조할 수 있는 변수로, 컴포넌트 구조에 명시적으로 정의되어 있어 관리가 용이합니다. 반면 전역 변수는 아무 선언 없이 어디서나 접근 가능하지만, 코드 관리와 유지보수에 문제가 생길 수 있으므로 메이플스토리 월드의 스크립팅 방식에서는 프로퍼티를 통해 상태 값을 다루는 것을 권장합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 **루아**라는 언어를 사용하여 스크립트를 작성합니다. 이번 시간에는 **루아**의 기본 사용법과 메이플스토리 월드에서 사용하는 예제를 함께 살펴보겠습니다. # 변수 변수란 데이터를 저장하는 메모리 공간, 값을 담아두는 그릇입니다. ## 변수의 범위 루아에서 사용하는 변수는 아래의 두 가지로 나뉩니다. | 변수 | 설명 | | --- | --- | | 전역(global) 변수 | 어느 곳이든 접근 가능한 변수로 아무 선언 없이 사용하면 전역 변수입니다. **단, 메이플스토리

[task] | two_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | CardBoard 컴포넌트에서 RemainingTime을 UI 텍스트에 반영하는 UpdateText 함수의 작성 방법은 무엇인가? [answer] | `CardBoard` 컴포넌트에서 `RemainingTime`을 UI 텍스트에 반영하기 위해 `UpdateText` 함수를 작성하는 방법은 다음과 같습니다. 1. **CardBoard** 컴포넌트에 타이머 텍스트를 표시할 `Entity` 타입의 프로퍼티 `TimeText`를 추가하고, 해당 UI 경로(예: `/ui/CardPairGameUI/UI_Board/Background/Title/Timer_Background/UI_Time/UI_Time_Text`)를 설정합니다. 2. `UpdateText()` 메서드를 작성하여 `Ca [followup] | math.floor(remainingTime)을 사용하는데, 만약 소수점 이하의 시간(예: 5.8초)을 '5.8'처럼 한 자리 소수까지 표시하고 싶다면 코드를 어떻게 수정해야 하는가? [followup_answer] | 참고 문서에는 `math.floor`를 사용하여 정수 형태로 시간을 표시하는 방법만 나와 있으며, 소수점 이하 한 자리까지 표시하는 구체적인 코드나 API에 대한 설명은 포함되어 있지 않습니다. 다만, mLua는 Lua 5.3 기반이므로 표준 Lua 문자열 포맷팅 함수인 `string.format`을 사용하여 소수점 이하 한 자리까지 표시할 수 있습니다. `UpdateText` 함수를 다음과 같이 수정하면 됩니다. ```lua Method: [client only] void UpdateText() { local remai [scores] | [judge_reason] | [source_doc] | # 타이머 만들기 게임을 시작하면 1초씩 감소하는 타이머를 만들어봅시다. 1. **CardPairGameLogic** 로직에 게임 제한 시간으로 사용할 **PlayTime** 프로퍼티와 시간을 줄이기 위해 사용할 **RemainingTime** 프로퍼티를 추가합니다. PlayTime 초깃값은 **60**으로 설정합니다. ```lua Property: [None] number PlayTime = 60 [None] number RemainingTime = 0 ``` > **

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 루아에서 배열의 첫 번째 인덱스 값을 0으로 시작한다고 잘못 알고 있을 때, 올바른 접근 방식을 코드 블록으로만 제시하고 설명은 주석으로 작성하세요. [answer] | ```lua -- 루아(Lua)의 배열은 0이 아닌 1부터 시작합니다. -- 첫 번째 요소에 접근하려면 인덱스 [1]을 사용해야 합니다. local testArray = {"A string", 1.234, true} -- 잘못된 접근: testArray[0] 은 nil 을 반환합니다 (첫 번째 값이 아님). -- 올바른 접근: testArray[1] 이 배열의 첫 번째 값입니다. log(testArray[1]) -- A string ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 루아의 변수는 내부적으로 유형이 존재하기는 하지만 변수를 생성할 때 그 유형을 명시하지는 않습니다. 변수에 들어가는 값에 따라 그 유형이 정해집니다. | 변수 유형 | 설명 | | --- | --- | | nil | 값이 없음을 뜻합니다. 논리 연산에서 nil은 거짓(false)이고 전역 변수 및 테이블 키에서의 nil은 버려집니다. | | boolean | true와 false 값만 갖습니다. 0, 1의 수치로 변환되지 않습니다. | | number | 64비트 실수입니다. | | integer | 64비트 정수입니다. |

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 산술 연산자 중 몫과 나머지를 구하는 연산자 2개를 2문장 이내로 설명하세요. [answer] | `//` 연산자는 두 수를 나눈 후 몫만 취하며, `%` 연산자는 나눈 후 나머지만 취합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 산술 연산을 할 때 사용하는 연산자입니다. | 연산자 | 설명 | | --- | --- | | `+` | 더하기 | | `-` | 빼기 | | `*` | 곱하기 | | `/` | 나누기 | | `//` | 나눈 후 몫만 취함 | | `%` | 나눈 후 나머지만 취함 | | `^` | 지수 | 예를 들어 아래와 같이 입력하고 **log**를 출력하면 주석의 값이 출력됩니다. ```lua log(1 + 1) -- 2 log(1 - 1) -- 0 log(5 * 5) -- 25 log(13 / 5) -- 2.6 log(13 // 5)

[task] | single_turn [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 지역 변수와 프로퍼티의 가장 큰 차이점은 스크립트 실행 범위에서 어디까지 값을 유지할 수 있는지에 있나요? [answer] | 네, 맞습니다. 지역 변수와 프로퍼티의 가장 큰 차이점은 **값이 유지되는 범위(스펙트럼)** 입니다. **프로퍼티(Property)** 는 스크립트 컴포넌트 전체에서 참조할 수 있는 값입니다. 특정 함수나 구문의 실행이 끝나도 사라지지 않으며, 스크립트 내 다른 메서드나 이벤트 핸들러에서도 `self.프로퍼티명`을 통해 접근할 수 있습니다. 반면, **지역 변수(Local variable)** 는 해당 변수가 정의된 함수 또는 구문(예: `if` 문, `for` 문 등) 내에서만 유효합니다. 해당 범위의 실행이 끝나면 변수는 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 **루아**라는 언어를 사용하여 스크립트를 작성합니다. 이번 시간에는 **루아**의 기본 사용법과 메이플스토리 월드에서 사용하는 예제를 함께 살펴보겠습니다. # 변수 변수란 데이터를 저장하는 메모리 공간, 값을 담아두는 그릇입니다. ## 변수의 범위 루아에서 사용하는 변수는 아래의 두 가지로 나뉩니다. | 변수 | 설명 | | --- | --- | | 전역(global) 변수 | 어느 곳이든 접근 가능한 변수로 아무 선언 없이 사용하면 전역 변수입니다. **단, 메이플스토리

[task] | two_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | `IsEmpty` 함수가 카드 스포팅 루트 내 카드의 가시성을 어떻게 검사하는지 알려 주세요 [answer] | `IsEmpty` 함수는 `self.CardSpawnRoot.Children` 배열을 순회하며 각 카드의 `Visible` 프로퍼티를 검사합니다. 구체적인 동작은 다음과 같습니다. 1. `self.CardSpawnRoot.Children`을 통해 카드 스포팅 루트의 모든 자식 객체(카드)를 `cards` 테이블에 저장합니다. 2. `1`부터 `#cards` (카운트)까지 반복문을 실행합니다. 3. 반복문 내에서 `cards[i].Visible` 값을 확인합니다. * 만약 `Visible`이 `true`인 카드가 [followup] | `cards[i].Visible`이 `false`인 카드들이 존재할 때 `return false`를 먼저 반환하는 로직이 맞는지 확인해 주세요. [followup_answer] | 아니요, `cards[i].Visible`이 `false`인 카드가 존재한다고 해서 `return false`를 반환하는 로직은 아닙니다. 참고 문서의 `IsEmpty` 함수 코드를 보면, **`cards[i].Visible`이 `true`일 때** `return false`를 반환하도록 작성되어 있습니다. ```lua for i = 1, #cards do if cards[i].Visible then -- 보이는 카드가 있을 때 return false -- "비어있지 않다"고 즉시 반환 [scores] | [judge_reason] | [source_doc] | [client only] void DeselectCard() { self.SelectedCard:CardOff() self.SelectedCard = nil } [client only] boolean IsEmpty () { local cards = self.CardSpawnRoot.Children for i = 1, #cards do if cards[i].Visible then return false end end

[task] | single_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | cardboard.SelectedCard가 nil이 아닌 상태에서 새로운 카드를 클릭했을 때 DeselectCard()만 호출되고 선택이 유지되지 않는 원인은 무엇인가요? [answer] | 제공된 문서의 `OnCardClicked` 로직을 분석하면, `cardboard.SelectedCard`가 `nil`이 아닌 상태에서 새로운 카드를 클릭했을 때 `DeselectCard()`만 호출되고 선택이 유지되지 않는 원인은 **새로운 카드(`newCard`)가 기존에 선택된 카드(`oldCard`)의 쌍(Pair)이 아닐 때**입니다. 문서에 명시된 코드 흐름은 다음과 같습니다. ```lua local oldCard = cardboard.SelectedCard local newCard = card if oldCard = [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | #### CardPairGameLogic 로직 ```lua Property: [None] Entity CardPairGameUI = /ui/CardPairGameUI [None] number PlayTime = 60 [None] number RemainingTime = 0 Method: [client only] void OnBeginPlay() { self:StartGame() } [client only] void StartGame() { self.CardPairGameUI.Enable = true

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | `type()` 함수가 반환할 수 있는 기본 데이터 유형 6가지를 표 형태로 정리하되, 헤더는 '유형'과 '설명' 두 칸만 사용하세요. [answer] | | 유형 | 설명 | | --- | --- | | nil | 값이 없음을 뜻합니다. 논리 연산에서 nil은 거짓(false)이고 전역 변수 및 테이블 키에서의 nil은 버려집니다. | | boolean | true와 false 값만 갖습니다. 0, 1의 수치로 변환되지 않습니다. | | number | 64비트 실수입니다. | | integer | 64비트 정수입니다. | | string | 문자열입니다. 큰따옴표(") 또는 작은따옴표(')로 감싸서 사용합니다. | | table | 복합 자료형입니다. 배열(Array) 형태와 사전 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 루아의 변수는 내부적으로 유형이 존재하기는 하지만 변수를 생성할 때 그 유형을 명시하지는 않습니다. 변수에 들어가는 값에 따라 그 유형이 정해집니다. | 변수 유형 | 설명 | | --- | --- | | nil | 값이 없음을 뜻합니다. 논리 연산에서 nil은 거짓(false)이고 전역 변수 및 테이블 키에서의 nil은 버려집니다. | | boolean | true와 false 값만 갖습니다. 0, 1의 수치로 변환되지 않습니다. | | number | 64비트 실수입니다. | | integer | 64비트 정수입니다. |

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 테이블 참조 시 원본 테이블 수정이 참조 변수에도 반영되는 원리를 Lua 코드만 출력하고 설명은 주석으로 작성하세요. [answer] | ```lua -- 루아에서 테이블은 객체(참조형 타입)입니다. -- 변수에 테이블을 대입하면 테이블 자체의 복사가 아니라, 그 테이블을 가리키는 주소(참조)가 복사됩니다. -- 따라서 원본 변수와 참조 변수는 동일한 메모리 영역(실제 테이블 데이터)을 공유하게 됩니다. local original = {10, 100, 1000} -- 'original'이 가리키는 테이블의 참조를 'reference'에 대입합니다. -- 이 시점에서 original과 reference는 같은 테이블을 가리킵니다. local reference = o [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 배열에서 값을 제거할 때는 `table.remove()` 함수를 사용합니다. ```lua local array = {11, 22, 33, 44, 55} -- 1번 인덱스를 제거 table.remove(array, 1) log(array[1]) -- 22 ``` > **더 알아보기** > 스크립트 에디터에서 테이블에서 활용할 수 있는 다양한 함수들을 확인할 수 있습니다. > ## 사전(Dictionary) 사전은 **key - value** 형태의 테이블입니다. 자료 구조에서 데이터를 빠르게 검색하기 위해 주로 사용합니다.

[task] | two_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | 카드 짝 맞추기 게임에서 매초 감소하는 타이머를 구현하려면 어떤 프로퍼티와 메서드를 설정해야 하나? [answer] | 카드 짝 맞추기 게임에서 매초 감소하는 타이머를 구현하기 위해 설정해야 하는 프로퍼티와 메서드는 다음과 같습니다. **1. 프로퍼티 설정** `CardPairGameLogic` 로직에 게임 제한 시간을 나타내는 `PlayTime`과 현재 남은 시간을 나타내는 `RemainingTime` 프로퍼티를 추가합니다. `PlayTime`의 초깃값은 60으로 설정하며, `RemainingTime`은 0으로 초기화합니다. ```lua Property: [None] number PlayTime = 60 [None] number Remainin [followup] | OnUpdate에서 RemainingTime을 delta만큼 차감할 때, 시간이 0 이하가 되면 게임을 즉시 종료하거나 패배 처리하는 로직은 어떻게 추가해야 하나? [followup_answer] | 제공된 참고 문서에는 `RemainingTime`이 0 이하가 되었을 때 게임을 종료하거나 패배 처리하는 로직에 대한 설명이 포함되어 있지 않습니다. 문서에는 `OnUpdate`에서 `RemainingTime`을 `delta`만큼 차감하고, 이를 UI에 반영하는 방법만 다루며, 시간이 0이 되었을 때의 처리(게임 종료, 패배 판정 등)에 관한 API나 코드 예제는 찾을 수 없습니다. 따라서 해당 로직을 어떻게 추가해야 하는지 문서 근거로 답변드리기 어렵습니다. [scores] | [judge_reason] | [source_doc] | # 타이머 만들기 게임을 시작하면 1초씩 감소하는 타이머를 만들어봅시다. 1. **CardPairGameLogic** 로직에 게임 제한 시간으로 사용할 **PlayTime** 프로퍼티와 시간을 줄이기 위해 사용할 **RemainingTime** 프로퍼티를 추가합니다. PlayTime 초깃값은 **60**으로 설정합니다. ```lua Property: [None] number PlayTime = 60 [None] number RemainingTime = 0 ``` > **

[task] | single_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | 아바타의 Body 엔티티를 가져와서 이벤트를 연결할 때, 왜 self.Entity.AvatarRendererComponent:GetBodyEntity() 를 직접 호출하는지 그리고 이 메서드가 반환하는 객체의 정체는 무엇인가요? [answer] | 참고 문서에 제시된 예제 코드를 분석하면, `self.Entity.AvatarRendererComponent:GetBodyEntity()`를 호출하는 이유와 반환 객체의 정의를 다음과 같이 설명할 수 있습니다. ### 1. `self.Entity.AvatarRendererComponent:GetBodyEntity()` 호출 이유 아바타 애니메이션 제어 및 관련 이벤트(`SpriteAnimPlayerChangeFrameEvent`, `ActionStateChangedEvent` 등)는 아바타의 **Body(몸통) 엔티티**를 대상 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 다음의 예제 코드를 보면서 **FrameEvent**의 사용법을 알아봅시다. 1. 어떤 아바타 애니메이션의 2번째 프레임이 재생될 때 다른 애니메이션으로 변경하고 싶다고 가정합니다. 그렇다면 **SpriteAnimPlayerChangeFrameEvent**를 활용할 수 있을 것입니다. `OnBeginPlay` 함수를 추가하고, 위에서 설명한 대로 이벤트를 **Body**와 연결합니다. 구독 취소를 대비해 연결한 이벤트의 핸들러는 프로퍼티로 가지고 있도록 합니다. ```lua Property: [None]

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 관계 연산자 7개를 연산자 기호와 설명이 담긴 표로 정리하세요. [answer] | 관계 연산자는 관계를 판단할 때 사용하며, 결과는 `boolean` 타입입니다. 7개의 연산자와 그 설명은 다음과 같습니다. | 연산자 | 설명 | | :--- | :--- | | `=` | 선언 | | `==` | 같다 | | `~=` | 다르다 | | `>` | 크다 | | `<` | 작다 | | `>=` | 크거나 같다 | | `<=` | 작거나 같다 | [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 산술 연산을 할 때 사용하는 연산자입니다. | 연산자 | 설명 | | --- | --- | | `+` | 더하기 | | `-` | 빼기 | | `*` | 곱하기 | | `/` | 나누기 | | `//` | 나눈 후 몫만 취함 | | `%` | 나눈 후 나머지만 취함 | | `^` | 지수 | 예를 들어 아래와 같이 입력하고 **log**를 출력하면 주석의 값이 출력됩니다. ```lua log(1 + 1) -- 2 log(1 - 1) -- 0 log(5 * 5) -- 25 log(13 / 5) -- 2.6 log(13 // 5)

[task] | single_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | OnUpdate에서 RemainingTime이 0 이하가 될 때만 EndGame()이 실행되는 조건이 왜 if문으로 처리되는지 설명해 주세요. [answer] | `OnUpdate`에서 `RemainingTime`이 0 이하가 될 때만 `EndGame()`이 실행되는 조건이 `if`문으로 처리되는 이유는 **매 프레임마다 발생하는 `OnUpdate` 이벤트에서 특정 조건이 충족된 시점에만 한 번의 동작(게임 종료)을 수행해야 하기 때문**입니다. 구체적인 동작 흐름은 다음과 같습니다. 1. **매 프레임 실행**: `OnUpdate`는 게임 루프가 돌 때마다(매 프레임) 호출됩니다. 2. **시간 감소**: 호출될 때마다 `self.RemainingTime`에서 `delta`(경과 시 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | #### CardPairGameLogic 로직 ```lua Property: [None] Entity CardPairGameUI = /ui/CardPairGameUI [None] number PlayTime = 60 [None] number RemainingTime = 0 Method: [client only] void OnBeginPlay() { self:StartGame() } [client only] void StartGame() { self.CardPairGameUI.Enable = true

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 점수 만들기 [question] | PlayerStats 컴포넌트의 Score 프로퍼티 선언 및 AddScore 메서드 코드를 코드 블록 하나로만 출력하세요. [answer] | ```lua Property: [None] number Score = 0 Method: void AddScore (number add) { self.Score = self.Score + add } ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 점수 만들기 카드 짝 맞출 때마다 일정한 점수가 증가하게 만들어봅시다. 1. **PlayerStats** 컴포넌트를 **DefalutPlayer**에 추가합니다. **PlayerStats** 컴포넌트는 점수 증가를 담당합니다. 2. **PlayerStats** 컴포넌트에 number 타입 프로퍼티를 아래와 같이 추가합니다. ```lua Property: [None] number Score = 0 ``` 3. 초깃값이 0인 **Score** 프로퍼티에 점수가 더해질 수 있도록 `A

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 문서 예제에 있는 논리 연산자 and, or, not 각각에 대한 동작 방식을 단계별 번호 목록으로 나열하세요. [answer] | 참고 문서에 따르면, 논리 연산자의 동작 방식은 다음과 같습니다. * 공통 전제: 인수가 거짓(false)이 아니면, 그리고 0이 아니면 참(true)으로 반환합니다. **and** 1. A and B 형식으로 사용합니다. 2. A와 B가 모두 true이어야 true를 반환합니다. **or** 1. A or B 형식으로 사용합니다. 2. A 또는 B 중 하나라도 true이어야 true를 반환합니다. **not** 1. 입력값이 true이면 false를 반환합니다. 2. 입력값이 false이면 true를 반환합니 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 산술 연산을 할 때 사용하는 연산자입니다. | 연산자 | 설명 | | --- | --- | | `+` | 더하기 | | `-` | 빼기 | | `*` | 곱하기 | | `/` | 나누기 | | `//` | 나눈 후 몫만 취함 | | `%` | 나눈 후 나머지만 취함 | | `^` | 지수 | 예를 들어 아래와 같이 입력하고 **log**를 출력하면 주석의 값이 출력됩니다. ```lua log(1 + 1) -- 2 log(1 - 1) -- 0 log(5 * 5) -- 25 log(13 / 5) -- 2.6 log(13 // 5)

[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | SpriteAnimPlayerChangeFrameEvent의 FrameIndex가 2일 때만 동작하도록 조건문을 설정하고, 이벤트 발생 시 Body에 ActionStateChangedEvent를 전송한 뒤 self.handler를 통해 이벤트 연결을 해제하는 로직을 포함하는 스크립트를 작성해줘. [answer] | SpriteAnimPlayerChangeFrameEvent의 FrameIndex가 2일 때만 동작하도록 조건문을 설정하고, 이벤트 발생 시 Body에 ActionStateChangedEvent를 전송한 뒤 self.handler를 통해 이벤트 연결을 해제하는 로직을 포함하는 스크립트는 다음과 같습니다. ```lua Property: [None] any handler = nil Method: [client only] void OnBeginPlay() { local body = self.Entity.AvatarRenderer [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 다음의 예제 코드를 보면서 **FrameEvent**의 사용법을 알아봅시다. 1. 어떤 아바타 애니메이션의 2번째 프레임이 재생될 때 다른 애니메이션으로 변경하고 싶다고 가정합니다. 그렇다면 **SpriteAnimPlayerChangeFrameEvent**를 활용할 수 있을 것입니다. `OnBeginPlay` 함수를 추가하고, 위에서 설명한 대로 이벤트를 **Body**와 연결합니다. 구독 취소를 대비해 연결한 이벤트의 핸들러는 프로퍼티로 가지고 있도록 합니다. ```lua Property: [None]

[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | self.Entity.AvatarRendererComponent:GetBodyEntity()를 통해 Body를 가져와서 ActionStateChangedEvent("swingOF", "swingOF", 0.5, SpriteAnimClipPlayType.Loop, 2, 3)를 보내는 ChangeFrameEvent 메서드를 구현하고, OnBeginPlay에서 이벤트 핸들러를 프로퍼티로 저장하여 연결하는 스크립트를 작성해줘. [answer] | 요청하신 기능을 구현한 mLua 스크립트입니다. `OnBeginPlay`에서 Body 엔티티를 가져와 `SpriteAnimPlayerChangeFrameEvent`를 연결하고, 핸들러를 프로퍼티에 저장합니다. `ChangeFrameEvent`에서 프레임 인덱스가 2일 때 `ActionStateChangedEvent`를 보내어 `swingOF` 애니메이션을 재생 속도와 반복 범위를 지정하여 실행합니다. ```lua Property: [None] any handler = nil Method: [client only] void OnB [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 다음의 예제 코드를 보면서 **FrameEvent**의 사용법을 알아봅시다. 1. 어떤 아바타 애니메이션의 2번째 프레임이 재생될 때 다른 애니메이션으로 변경하고 싶다고 가정합니다. 그렇다면 **SpriteAnimPlayerChangeFrameEvent**를 활용할 수 있을 것입니다. `OnBeginPlay` 함수를 추가하고, 위에서 설명한 대로 이벤트를 **Body**와 연결합니다. 구독 취소를 대비해 연결한 이벤트의 핸들러는 프로퍼티로 가지고 있도록 합니다. ```lua Property: [None]

[task] | single_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | ClearCardEntities 에서 self.CardSpawnRoot.Children 을 순회하며 Destroy() 를 호출할 때, 자식 개수가 0인 경우나 이미 파괴된 엔티티가 목록에 남아있을 경우 예외 처리가 필요한가요? [answer] | 제시된 참고 문서에는 `ClearCardEntities` 메서드에서 자식 개수가 0인 경우나 이미 파괴된 엔티티가 목록에 남아 있을 경우를 위한 명시적인 예외 처리 코드나 관련 설명이 포함되어 있지 않습니다. 문서에 제시된 `ClearCardEntities` 메서드의 구현은 다음과 같습니다: ```lua [client Only] void ClearCardEntities () { local cardEntities = self.CardSpawnRoot.Children for i = 1, #cardEn [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | ```lua Property: [None] Entity CardSpawnRoot = /ui/CardPairGameUI/UI_Board/UI_Blocks/UI_Block_Group [None] Card SelectedCard = nil [None] Entity TimeText = /ui/CardPairGameUI/UI_Board/Background/Title/Timer_Background/UI_Time/UI_Time_Text Method: [client only] void OnUpdate (number delta) { sel

[task] | single_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | OnUpdate 에서 매 프레임 UpdateText 를 호출하여 RemainingTime 값을 화면에 반영하는 방식이 있는데, 이를 이벤트 기반으로 변경하거나 성능을 최적화할 수 있는 방법이 있을까요? [answer] | 제공된 참고 문서에는 `OnUpdate` 루프를 사용하는 외에 타이머 업데이트를 위한 다른 이벤트 기반 API나 최적화 메서드에 대한 정보가 포함되어 있지 않습니다. 문서에는 `_CardPairGameLogic` 객체의 `RemainingTime` 프로퍼티를 읽고, `OnUpdate`에서 이를 화면(`TimeText.TextComponent.Text`)에 반영하는 코드가 제시되어 있을 뿐, `_TimerService`를 활용한 타이머 이벤트 핸들러 등록 방법이나 `RemainingTime` 값 변경 시 발동되는 특정 이벤트(예: [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | ```lua Property: [None] Entity CardSpawnRoot = /ui/CardPairGameUI/UI_Board/UI_Blocks/UI_Block_Group [None] Card SelectedCard = nil [None] Entity TimeText = /ui/CardPairGameUI/UI_Board/Background/Title/Timer_Background/UI_Time/UI_Time_Text Method: [client only] void OnUpdate (number delta) { sel

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 점수 만들기 [question] | AddScore 호출 시점과 UI 업데이트 로직을 단계별 번호 목록으로 3줄 이내로 요약하세요. [answer] | 1. `CardPairGameLogic`의 `OnCardClicked`에서 카드가 소멸된 직후 `me.PlayerStats:AddScore(10)`을 호출하여 점수를 증가시킵니다. 2. `CardBoard`의 `UpdateText()` 함수에서 `_UserService.LocalPlayer`의 `PlayerStats.Score` 값을 가져와 `math.floor`로 정수화합니다. 3. 정수화된 점수를 `self.ScoreText.TextComponent.Text`에 문자열로 할당하여 UI에 반영합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 점수 만들기 카드 짝 맞출 때마다 일정한 점수가 증가하게 만들어봅시다. 1. **PlayerStats** 컴포넌트를 **DefalutPlayer**에 추가합니다. **PlayerStats** 컴포넌트는 점수 증가를 담당합니다. 2. **PlayerStats** 컴포넌트에 number 타입 프로퍼티를 아래와 같이 추가합니다. ```lua Property: [None] number Score = 0 ``` 3. 초깃값이 0인 **Score** 프로퍼티에 점수가 더해질 수 있도록 `A

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 점수 만들기 [question] | CardBoard 컴포넌트의 ScoreText 프로퍼티 경로와 UpdateText 내 점수 표시 코드를 표로 정리해서 출력하세요. [answer] | CardBoard 컴포넌트의 ScoreText 프로퍼티 경로와 UpdateText 함수 내 점수 표시 코드는 다음과 같습니다. | 항목 | 내용 | | :--- | :--- | | **ScoreText 프로퍼티 경로** | `/ui/CardPairGameUI/UI_Board/Background/Title/Score_Backgrond/UI_Score/UI_Score_Text` | | **UpdateText 내 점수 표시 코드** | `local me = _UserService.LocalPlayer`<br>`self.ScoreText [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 점수 만들기 카드 짝 맞출 때마다 일정한 점수가 증가하게 만들어봅시다. 1. **PlayerStats** 컴포넌트를 **DefalutPlayer**에 추가합니다. **PlayerStats** 컴포넌트는 점수 증가를 담당합니다. 2. **PlayerStats** 컴포넌트에 number 타입 프로퍼티를 아래와 같이 추가합니다. ```lua Property: [None] number Score = 0 ``` 3. 초깃값이 0인 **Score** 프로퍼티에 점수가 더해질 수 있도록 `A

[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | OnBeginPlay에서 self.Entity.AvatarRendererComponent:GetBodyEntity()로 Body를 참조하여 SpriteAnimPlayerChangeFrameEvent를 구독하고, ChangeFrameEvent 핸들러에서 2번째 프레임 감지 시 swingOF 애니메이션을 0.5속도로 2~3프레임 반복 재생하며 구독을 취소하는 [client] 실행 공간의 스크립트를 작성해줘. [answer] | 사용자가 요청한 기능을 구현하기 위해, 이벤트 구독을 위한 프로퍼티를 선언하고, `OnBeginPlay`에서 Body 엔티티를 참조하여 이벤트를 연결합니다. 이후 `ChangeFrameEvent` 핸들러에서 조건(2번째 프레임)이 충족되면 `ActionStateChangedEvent`를 보내 애니메이션을 변경하고, 무한 루프를 방지하기 위해 즉시 구독을 취소하는 로직을 포함합니다. ```lua Property: [None] any handler = nil Method: [client only] void OnBeginPlay() [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 다음의 예제 코드를 보면서 **FrameEvent**의 사용법을 알아봅시다. 1. 어떤 아바타 애니메이션의 2번째 프레임이 재생될 때 다른 애니메이션으로 변경하고 싶다고 가정합니다. 그렇다면 **SpriteAnimPlayerChangeFrameEvent**를 활용할 수 있을 것입니다. `OnBeginPlay` 함수를 추가하고, 위에서 설명한 대로 이벤트를 **Body**와 연결합니다. 구독 취소를 대비해 연결한 이벤트의 핸들러는 프로퍼티로 가지고 있도록 합니다. ```lua Property: [None]

[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | 아바타의 Body 엔티티에 SpriteAnimPlayerChangeFrameEvent를 연결하여 2번째 프레임에서 swingOF 애니메이션을 0.5배속으로 2~3프레임 루프 재생하고, 즉시 이벤트 구독을 취소하는 [client only] 스크립트를 작성해줘. [answer] | 사용자가 요청한 기능(2번째 프레임 감지 후 `swingOF` 애니메이션 재생 및 즉시 구독 취소)을 구현한 스크립트입니다. 참고 문서에 따르면 `SpriteAnimPlayerChangeFrameEvent`는 아바타의 Body 엔티티에 연결하며, 이벤트 핸들러 참조는 프로퍼티로 저장해야 합니다. 요청사항에 따라 이벤트가 발생한 즉시(`ChangeFrameEvent` 내부에서) 구독을 취소하는 로직을 포함했습니다. ```lua Property: [None] any handler = nil Method: [client only] [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 다음의 예제 코드를 보면서 **FrameEvent**의 사용법을 알아봅시다. 1. 어떤 아바타 애니메이션의 2번째 프레임이 재생될 때 다른 애니메이션으로 변경하고 싶다고 가정합니다. 그렇다면 **SpriteAnimPlayerChangeFrameEvent**를 활용할 수 있을 것입니다. `OnBeginPlay` 함수를 추가하고, 위에서 설명한 대로 이벤트를 **Body**와 연결합니다. 구독 취소를 대비해 연결한 이벤트의 핸들러는 프로퍼티로 가지고 있도록 합니다. ```lua Property: [None]

[task] | code [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | `_DataService`에서 "CardSet" 행 개수를 조회하고 `_UtilLogic`으로 난수 섞기를 수행해 `_SpawnService`로 카드를 생성하는 SetCards 메서드를 구현하는 스크립트를 작성해줘. [answer] | `_DataService:GetRowCount`으로 "CardSet" 시트의 행 개수를 가져오고, `_UtilLogic:RandomIntegerRange`으로 두 번의 셔플(덱 순서 섞기, 최종 카드 배열 섞기)을 수행하여 `_SpawnService:SpawnByModelId`로 카드 엔티티를 생성하는 `SetCards` 메서드를 포함하는 스크립트입니다. 참고 문서에 있는 `CreateCardEntities`, `ClearCardEntities` 메서드도 카드 생성에 필수적이므로 함께 포함했습니다. ```lua Property: [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | ```lua Property: [None] Entity CardSpawnRoot = /ui/CardPairGameUI/UI_Board/UI_Blocks/UI_Block_Group [None] Card SelectedCard = nil [None] Entity TimeText = /ui/CardPairGameUI/UI_Board/Background/Title/Timer_Background/UI_Time/UI_Time_Text Method: [client only] void OnUpdate (number delta) { sel

[task] | single_turn [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 테이블을 다른 변수에 대입했을 때 원본을 수정하면 참조 변수도 함께 변하는데, 이걸 복사본으로 만들려면 어떻게 해야 하나요? [answer] | 주어진 참고 문서에는 테이블 참조(Reference)의 개념, 즉 변수가 원본 테이블을 가리키기 때문에 원본을 수정하면 참조 변수도 함께 변경된다는 사실만 설명하고 있습니다. 하지만 **복사본(Copy)을 만드는 구체적인 방법이나 관련 함수**에 대한 설명은 문서에 포함되어 있지 않습니다. 따라서 제공된 문서만으로는 복사본을 만드는 방법을 답변드릴 수 없습니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 배열에서 값을 제거할 때는 `table.remove()` 함수를 사용합니다. ```lua local array = {11, 22, 33, 44, 55} -- 1번 인덱스를 제거 table.remove(array, 1) log(array[1]) -- 22 ``` > **더 알아보기** > 스크립트 에디터에서 테이블에서 활용할 수 있는 다양한 함수들을 확인할 수 있습니다. > ## 사전(Dictionary) 사전은 **key - value** 형태의 테이블입니다. 자료 구조에서 데이터를 빠르게 검색하기 위해 주로 사용합니다.

[task] | single_turn [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | OnBeginPlay 함수 내부에서 정의한 지역 변수를 다른 메서드에서 호출했을 때 값이 nil로 나오는 이유는 무엇인가요? [answer] | 메이플스토리 월드의 스크립트 언어 mLua는 Lua 5.3 기반이며, 지역 변수(`local`)는 해당 변수가 선언된 함수 또는 구문(scope) 내부에서만 유효합니다. `OnBeginPlay` 함수 내부에서 정의한 지역 변수는 `OnBeginPlay` 함수의 실행이 종료되면 메모리에서 파괴됩니다. 따라서 다른 메서드(예: `testFunction`)에서 해당 변수에 접근하려고 하면, 그 변수가 더 이상 존재하지 않기 때문에 `nil` 값이 반환됩니다. 반면, 스크립트 전체에서 참조할 수 있는 값이 필요할 경우 지역 변수가 아닌 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 **루아**라는 언어를 사용하여 스크립트를 작성합니다. 이번 시간에는 **루아**의 기본 사용법과 메이플스토리 월드에서 사용하는 예제를 함께 살펴보겠습니다. # 변수 변수란 데이터를 저장하는 메모리 공간, 값을 담아두는 그릇입니다. ## 변수의 범위 루아에서 사용하는 변수는 아래의 두 가지로 나뉩니다. | 변수 | 설명 | | --- | --- | | 전역(global) 변수 | 어느 곳이든 접근 가능한 변수로 아무 선언 없이 사용하면 전역 변수입니다. **단, 메이플스토리

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | `table.insert()` 함수를 사용하여 배열 중간에 값을 삽입하는 과정과 `#array+1` 문법을 사용한 추가 과정을 비교하는 코드를 출력하되, 각 행의 결과는 반드시 주석으로 명시하세요. [answer] | `table.insert()` 함수는 배열의 특정 위치(인덱스)에 값을 삽입하거나, 두 번째 인수를 생략하면 배열의 끝에 값을 추가하는 역할을 합니다. 반면, `#array+1` 문법은 현재 배열의 길이(`#array`)에 1을 더한 새로운 인덱스 위치에 값을 직접 대입하여 배열의 끝에 값을 추가하는 방법입니다. 두 가지 방법으로 값을 추가하는 과정과 그 결과를 비교한 코드는 다음과 같습니다. ```lua Method: [server only] void OnBeginPlay() { -- 초기 배열 생성 local [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 루아의 변수는 내부적으로 유형이 존재하기는 하지만 변수를 생성할 때 그 유형을 명시하지는 않습니다. 변수에 들어가는 값에 따라 그 유형이 정해집니다. | 변수 유형 | 설명 | | --- | --- | | nil | 값이 없음을 뜻합니다. 논리 연산에서 nil은 거짓(false)이고 전역 변수 및 테이블 키에서의 nil은 버려집니다. | | boolean | true와 false 값만 갖습니다. 0, 1의 수치로 변환되지 않습니다. | | number | 64비트 실수입니다. | | integer | 64비트 정수입니다. |

[task] | single_turn [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 사전에서 값을 읽을 때 myDictionary.key 와 myDictionary["key"] 방식 중 어떤 것이 더 권장되는지, 혹은 차이가 있는지 알고 싶어요. [answer] | 제공된 문서에는 `myDictionary.key`와 `myDictionary["key"]` 방식의 차이점이나 특정 방식이 더 권장되는지에 대한 명시적인 내용이 없습니다. 문서에는 두 가지 방식 모두 값을 읽을 때 사용할 수 있는 유효한 문법으로만 소개되어 있습니다. ```lua local myDictionary = {a = "myNumber", myNumber = 5, myString = "TTT", myBoolean = true} log(myDictionary.myNumber) -- 5 log(myDictionary.mySt [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 배열에서 값을 제거할 때는 `table.remove()` 함수를 사용합니다. ```lua local array = {11, 22, 33, 44, 55} -- 1번 인덱스를 제거 table.remove(array, 1) log(array[1]) -- 22 ``` > **더 알아보기** > 스크립트 에디터에서 테이블에서 활용할 수 있는 다양한 함수들을 확인할 수 있습니다. > ## 사전(Dictionary) 사전은 **key - value** 형태의 테이블입니다. 자료 구조에서 데이터를 빠르게 검색하기 위해 주로 사용합니다.

[task] | single_turn [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 배열의 길이를 구할 때 사용하는 `#` 연산자가 정확히 어떤 값을 반환하는지 알고 싶습니다. [answer] | `#` 연산자는 배열의 길이를 구할 때 사용하며, 배열에 저장된 요소의 개수를 반환합니다. 예를 들어 아래 코드에서 `a`는 두 개의 문자열을 가진 배열입니다. `#a`를 사용하면 배열의 길이인 `2`가 반환됩니다. ```lua local a = {"HELLO", "MapleStory Worlds"} log(#a) -- 2 ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 산술 연산을 할 때 사용하는 연산자입니다. | 연산자 | 설명 | | --- | --- | | `+` | 더하기 | | `-` | 빼기 | | `*` | 곱하기 | | `/` | 나누기 | | `//` | 나눈 후 몫만 취함 | | `%` | 나눈 후 나머지만 취함 | | `^` | 지수 | 예를 들어 아래와 같이 입력하고 **log**를 출력하면 주석의 값이 출력됩니다. ```lua log(1 + 1) -- 2 log(1 - 1) -- 0 log(5 * 5) -- 25 log(13 / 5) -- 2.6 log(13 // 5)

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