[task] | single_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | StateComponent를 이용해 아바타 상태를 변경할 때, 미리 정의된 상태 변경 조건으로 인해 원하는 애니메이션이 출력되기 전에 상태가 바뀌어 버리는 현상은 어떻게 발생하는 건가요? [answer] | StateComponent를 통해 아바타의 상태를 변경할 때, 미리 정의된 기본 상태 변경 조건이나 사용자 정의 상태 변경 조건이 존재하면 해당 조건이 충족되는 즉시 시스템이 자동으로 상태를 변경합니다. 이는 개발자가 `ChangeState`를 호출해 특정 애니메이션(예: 공격, 점프 등)을 재생하려는 시점과 무관하게, 아바타의 현재 물리적 상태나 입력 조건 등이 다른 상태(예: 이동 중, 착지 등)의 진입 조건을 만족하면 그 조건에 따라 상태가 우선적으로 덮어씌워지기 때문에 발생합니다. 결과적으로, 개발자가 의도했던 애니메이션 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 이미 정의된, 혹은 새로 정의할 아바타의 상태가 바뀔 때마다 매번 이벤트를 보내서 애니메이션을 변경하는 것도 번거로울 수 있습니다. 이벤트를 보내지 않고도 아바타 상태가 바뀔 때마다 애니메이션도 함께 변경되면 매우 편리할 것입니다. [AvatarStateAnimationComponent](/apiReference/Components/AvatarStateAnimationComponent)의 **ActionSheet**에 아바타 상태와 연결될 애니메이션을 설정하고 [StateComponent](/apiReference/Component
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | `EndGame` 함수의 코드만 출력하고 설명은 주석으로 작성하세요. [answer] | ```lua [client only] void EndGame () { -- 게임 종료 시 카드 짝 맞추기 UI를 비활성화하여 화면을 끕니다. self.CardPairGameUI.Enable = false } ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 타이머를 완성했지만 이번에도 한 가지 추가하면 좋겠습니다 타이머가 0초가 된 이후에 수가 음수로 계속해서 감소하고 있습니다. 일반적으로 수가 줄어드는 모습을 보면, 0초가 되었을 때 게임이 종료될 거라 기대합니다. 그러나 지금은 0초 이후 수가 음수로 줄어들고 있습니다. 0초가 되면 ui가 꺼지게 만들어 봅시다. 1. **CardPairGameLogic** 로직의 `EndGame` 함수에 아래와 같이 작성합니다. ```lua [client only] void EndGame () {
[task] | single_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | 몸통과 파츠의 애니메이션을 독립적으로 조절하고 싶다면 ActionStateChangedEvent 와 BodyActionStateChangeEvent 중 어떤 것을 선택해야 하는지, 그 이유와 함께 설명해 주세요. [answer] | 몸통과 파츠의 애니메이션을 독립적으로 조절하고 싶다면 `ActionStateChangedEvent`를 선택해야 합니다. 그 이유는 `ActionStateChangedEvent`는 몸통과 파츠 애니메이션을 각각 다르게 조절할 수 있는 장점이 있기 때문입니다. 반면, `BodyActionStateChangeEvent`는 몸통과 파츠 애니메이션을 각각 다르게 조절할 수 없는 단점이 있습니다. 추가적으로 `ActionStateChangedEvent`를 사용하면 재생 속도, 재생 타입, 애니메이션 시작/종료 프레임을 세밀하게 설정할 수 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 애니메이션 변경 과정을 정리하면 다음과 같습니다. 위에서 알아본 3가지 아바타 애니메이션 제어 방법의 장단점을 정리하면 아래 표와 같습니다. 각 방법은 장단점이 명확하므로 크리에이터의 의도에 맞는 방법을 적절히 선택하면 됩니다. | 아바타 애니메이션 제어 방법 | 장점 | 단점 | | :---: | --- | --- | | ActionStateChangedEvent | <ul> <li>몸통과 파츠 애니메이션을 각각 다르게 조절할 수 있습니다.</li> <li>재생 속도, 재생 타입, 애니메이션 시작/종료 프레임을 세밀하게 설
[task] | single_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | ActionSheet와 StateComponent를 조합해 애니메이션을 제어할 때, 애니메이션 시작과 끝 프레임을 직접 지정할 수 없거나 상태가 자동으로 변경되어 의도하지 않은 동작이 발생하는 원인은 무엇인가요? [answer] | ActionSheet와 StateComponent를 조합해 애니메이션을 제어할 때 발생하는 두 가지 문제의 원인은 다음과 같습니다. **1. 애니메이션 시작과 끝 프레임을 직접 지정할 수 없는 원인** ActionSheet는 아바타 상태(Key)와 `MapleAvatarBodyActionState` 값(Value)을 매핑하는 구조를 사용합니다. `MapleAvatarBodyActionState`에는 이미 재생할 몸통 및 파츠 애니메이션이 정의되어 있으며, 이 방식에서는 애니메이션의 시작/끝 프레임과 같은 세부 재생 범위를 직접 제 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 이미 정의된, 혹은 새로 정의할 아바타의 상태가 바뀔 때마다 매번 이벤트를 보내서 애니메이션을 변경하는 것도 번거로울 수 있습니다. 이벤트를 보내지 않고도 아바타 상태가 바뀔 때마다 애니메이션도 함께 변경되면 매우 편리할 것입니다. [AvatarStateAnimationComponent](/apiReference/Components/AvatarStateAnimationComponent)의 **ActionSheet**에 아바타 상태와 연결될 애니메이션을 설정하고 [StateComponent](/apiReference/Component
[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | ActionStateChangedEvent 이벤트 핸들러에서 CoreActionName 프로퍼티를 확인하여 "Jump" 액션이 실행될 때 아바타의 재생 속도(PlayRate)를 1.5배로 설정하는 스크립트를 작성해줘. [answer] | ActionStateChangedEvent 이벤트 핸들러에서 CoreActionName 프로퍼티를 확인하여 "Jump" 액션이 실행될 때 아바타의 재생 속도(PlayRate)를 1.5배로 설정하는 스크립트는 다음과 같습니다. 참고로, mLua API 문서에 따르면 `ActionStateChangedEvent`는 이벤트 핸들러를 통해 수신되는 이벤트이며, 이 이벤트의 프로퍼티(`CoreActionName`, `PlayRate` 등)는 읽기 전용으로 제공되어 이벤트 핸들러 내부에서 직접 수정하여 애니메이션의 재생 속도를 변경하는 기능 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 아바타 애니메이션을 제어하는 3가지 방법을 살펴봅니다. 본 과정을 통해 크리에이터가 원하는 기능에 맞게 아바타 애니메이션을 제어해 봅시다. # ActionStateChangedEvent로 제어 아바타는 **AvatarRoot**에 **Body**와 **Face**로 나뉘어 있습니다. **Body**는 말 그대로 아바타의 몸통이며 **Face**는 아바타의 얼굴을 뜻합니다. 아바타의 **Body**와 **Face**에 어떤 애니메이션을 재생할지는 [ActionStateChangedEvent](/apiRefer
[task] | single_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | 아바타 애니메이션을 클라이언트에서 제어해야 하는 구체적인 이유는 무엇인가요? [answer] | 아바타 애니메이션은 클라이언트에서 재생되므로, 이를 제어하기 위해서는 반드시 클라이언트 공간에서 스크립트를 실행해야 합니다. 서버에서 애니메이션 재생 상태를 변경하려고 해도 클라이언트 화면에 반영되지 않기 때문입니다. 따라서 아바타의 애니메이션을 바꾸거나 프레임 이벤트를 구독할 때는 `[client]` 실행 공간의 메서드나 이벤트 핸들러를 사용해야 합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 3. 아까 저장한 **handler**를 통해 **SpriteAnimPlayerChangeFrameEvent** 구독을 취소합니다. `ChangeFrameEvent` 함수를 수정해 봅시다. ```lua [client] void ChangeFrameEvent(any event) { if event.FrameIndex == 2 then local body = self.Entity.AvatarRendererComponent:GetBodyEntity()
[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | ActionStateChangedEvent의 StartFrameIndex와 EndFrameIndex 프로퍼티를 활용하여, 특정 액션 실행 시 애니메이션이 지정된 시작 프레임부터 종료 프레임까지만 재생되도록 PlayType을 설정하는 스크립트를 작성해줘. [answer] | `ActionStateChangedEvent`의 `PlayType` 파라미터에 `SpriteAnimClipPlayType.PlayOnce`를 설정하면, `StartFrameIndex`와 `EndFrameIndex`가 지정된 범위 내에서 애니메이션이 한 번만 재생됩니다. 아바타의 Body 엔티티에 해당 이벤트를 전송하는 방법을 활용한 스크립트 예시는 다음과 같습니다. ```lua Method: [client only] void OnBeginPlay() { -- B키를 누르면 특정 프레임 범위로 애니메이션 재생하는 액션 실행 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 아바타 애니메이션을 제어하는 3가지 방법을 살펴봅니다. 본 과정을 통해 크리에이터가 원하는 기능에 맞게 아바타 애니메이션을 제어해 봅시다. # ActionStateChangedEvent로 제어 아바타는 **AvatarRoot**에 **Body**와 **Face**로 나뉘어 있습니다. **Body**는 말 그대로 아바타의 몸통이며 **Face**는 아바타의 얼굴을 뜻합니다. 아바타의 **Body**와 **Face**에 어떤 애니메이션을 재생할지는 [ActionStateChangedEvent](/apiRefer
[task] | single_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | StateComponent 로 상태를 변경했는데 의도한 애니메이션이 나오지 않고 다른 애니메이션이 재생되는 현상은 어떤 원인으로 발생하나요? [answer] | StateComponent를 통해 상태를 변경했을 때 의도한 애니메이션 대신 다른 애니메이션이 재생되는 주된 원인은 **다른 상태 변경 조건에 의해 상태가 자동으로 변경되었기 때문**입니다. StateComponent 방식의 주요 단점 중 하나로, 다른 조건(예: 다른 이벤트 처리, 다른 스크립트의 상태 변경 등)이 우선적으로 실행되어 현재 상태가 변경되면, 그 상태에 대응하는 애니메이션으로 전환됩니다. 따라서 단순히 StateComponent의 State만 변경했다고 해서 항상 원하는 애니메이션이 출력된다는 보장은 없으며, 다른 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 애니메이션 변경 과정을 정리하면 다음과 같습니다. 위에서 알아본 3가지 아바타 애니메이션 제어 방법의 장단점을 정리하면 아래 표와 같습니다. 각 방법은 장단점이 명확하므로 크리에이터의 의도에 맞는 방법을 적절히 선택하면 됩니다. | 아바타 애니메이션 제어 방법 | 장점 | 단점 | | :---: | --- | --- | | ActionStateChangedEvent | <ul> <li>몸통과 파츠 애니메이션을 각각 다르게 조절할 수 있습니다.</li> <li>재생 속도, 재생 타입, 애니메이션 시작/종료 프레임을 세밀하게 설
[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | 아바타가 터치 입력을 받으면 MapleAvatarBodyActionState.Crouch 상태로 변경하고 2초 후 다시 MapleAvatarBodyActionState.Stand 상태로 복귀하는 스크립트를 작성해줘 [answer] | 사용자가 요청한 기능은 아바타의 터치 입력을 감지하여 `Crouch` 상태로 전환한 뒤, 2초 후 `Stand` 상태로 복귀하는 것입니다. 이를 구현하기 위해 `HandleTouchEvent` 이벤트 핸들러와 `_TimerService`를 사용합니다. 아바타의 몸통 액션 상태를 변경하려면 `self.Entity`에 `BodyActionStateChangeEvent`를 전송해야 합니다. 제공된 문서의 예제와 실제 mLua 예제에 따라 이벤트 객체를 생성하고 필요한 프로퍼티(`ActionState`, `needResetAction`, [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | [BodyActionStateChangeEvent](/apiReference/Events/BodyActionStateChangeEvent)는 이름 그대로 아바타의 bodyActionState를 변경하는 이벤트입니다. 이 이벤트는 무기 타입에 따른 애니메이션을 별도로 지정할 필요가 없어 편리합니다. **BodyActionStateChangeEvent**는 **MapleAvatarBodyActionState**로 애니메이션을 제어합니다. **MapleAvatarBodyActionState**에는 각 상태별로 어떤 몸통 액션과 파츠 액
[task] | single_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | ActionSheet와 StateComponent를 사용하면 왜 특정 프레임부터 시작하는 애니메이션을 지정할 수 없나요? [answer] | ActionSheet와 StateComponent 방식은 아바타의 **상태(State)** 를 변경하는 것을 통해 애니메이션을 간접적으로 제어합니다. 이 방식의 핵심은 `StateComponent`의 `ChangeState` 메서드를 호출하여 특정 상태 이름(예: "HIT", "IDLE" 등)으로 전환하는 것입니다. 참고 문서에 따르면, ActionSheet와 StateComponent 방식의 주요 단점 중 하나로 **"애니메이션 시작/종료 프레임을 설정할 수 없습니다"**라고 명시되어 있습니다. 이는 이 방식이 애니메이션의 재생 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 애니메이션 변경 과정을 정리하면 다음과 같습니다. 위에서 알아본 3가지 아바타 애니메이션 제어 방법의 장단점을 정리하면 아래 표와 같습니다. 각 방법은 장단점이 명확하므로 크리에이터의 의도에 맞는 방법을 적절히 선택하면 됩니다. | 아바타 애니메이션 제어 방법 | 장점 | 단점 | | :---: | --- | --- | | ActionStateChangedEvent | <ul> <li>몸통과 파츠 애니메이션을 각각 다르게 조절할 수 있습니다.</li> <li>재생 속도, 재생 타입, 애니메이션 시작/종료 프레임을 세밀하게 설
[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | 아바타의 Body에 연결된 SpriteAnimPlayerChangeFrameEvent를 처리하여 이벤트의 TotalFrameCount가 0보다 클 때 현재 FrameIndex를 log로 출력하는 스크립트를 작성해줘 [answer] | ```lua Event Handler: [self] HandleSpriteAnimPlayerChangeFrameEvent(SpriteAnimPlayerChangeFrameEvent event) { if event.TotalFrameCount > 0 then log(event.FrameIndex) end } ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 애니메이션 변경 과정을 정리하면 다음과 같습니다. 위에서 알아본 3가지 아바타 애니메이션 제어 방법의 장단점을 정리하면 아래 표와 같습니다. 각 방법은 장단점이 명확하므로 크리에이터의 의도에 맞는 방법을 적절히 선택하면 됩니다. | 아바타 애니메이션 제어 방법 | 장점 | 단점 | | :---: | --- | --- | | ActionStateChangedEvent | <ul> <li>몸통과 파츠 애니메이션을 각각 다르게 조절할 수 있습니다.</li> <li>재생 속도, 재생 타입, 애니메이션 시작/종료 프레임을 세밀하게 설
[task] | code [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | self.CardSpawnRoot.Children의 Visible 속성을 순회하여 카드가 남아있는지 확인하는 IsEmpty 메서드를 구현하는 스크립트를 작성해줘 [answer] | `CardSpawnRoot`의 자식 목록(`Children`)을 순회하며 `Visible` 속성이 `true`인 카드가 있는지 확인하는 `IsEmpty` 메서드를 포함하는 스크립트입니다. ```lua Property: [None] Entity CardSpawnRoot Method: [client only] boolean IsEmpty() { local cards = self.CardSpawnRoot.Children for i = 1, #cards do if cards[i].Visible th [followup] | [followup_answer] | [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] | two_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | 아바타 애니메이션의 특정 프레임에서 다른 애니메이션으로 전환하는 원리와 FrameEvent의 역할이 궁금합니다 [answer] | 아바타 애니메이션의 특정 프레임에서 다른 애니메이션으로 전환하는 원리는 **SpriteAnimPlayerChangeFrameEvent**를 활용하는 것입니다. 이 이벤트는 현재 재생 중인 애니메이션의 프레임이 변경될 때마다 발생하며, 이를 통해 특정 프레임(예: 2번째 프레임)에 도달했는지 확인하고 조건에 따라 새로운 애니메이션을 트리거할 수 있습니다. FrameEvent의 역할은 다음과 같습니다: 1. **모니터링**: `AvatarRendererComponent:GetBodyEntity()`를 통해 아바타의 Body 엔티티를 [followup] | SpriteAnimPlayerChangeFrameEvent를 구독하지 않고 해제하면 전환이 무한 반복되는 문제를 어떻게 해결해야 하는지, 그리고 구독 취소 시 주의할 점이 무엇인지 알려주세요. [followup_answer] | 참고 문서에 따르면, `SpriteAnimPlayerChangeFrameEvent`를 구독한 상태로 애니메이션 전환을 수행하면 **무한 루프** 문제가 발생합니다. ### 무한 반복 문제의 원리 및 해결 방법 1. **문제 원인**: * `SpriteAnimPlayerChangeFrameEvent`는 애니메이션 프레임이 변경될 때마다 발생하도록 구독(Connect)되어 있습니다. * 특정 프레임(예: 2번째)에서 `ActionStateChangedEvent`를 보내어 다른 애니메이션으로 전환하더라도, 여전 [scores] | [judge_reason] | [source_doc] | 다음의 예제 코드를 보면서 **FrameEvent**의 사용법을 알아봅시다. 1. 어떤 아바타 애니메이션의 2번째 프레임이 재생될 때 다른 애니메이션으로 변경하고 싶다고 가정합니다. 그렇다면 **SpriteAnimPlayerChangeFrameEvent**를 활용할 수 있을 것입니다. `OnBeginPlay` 함수를 추가하고, 위에서 설명한 대로 이벤트를 **Body**와 연결합니다. 구독 취소를 대비해 연결한 이벤트의 핸들러는 프로퍼티로 가지고 있도록 합니다. ```lua Property: [None]
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | OnUpdate 함수에서 RemainingTime을 감소시키는 로직과 UI 반영용 UpdateText 함수를 포함하는 전체 메서드 블록을 표로 정리해서 작성하세요. [answer] | 요청하신 `OnUpdate` 함수와 `UpdateText` 함수를 포함한 전체 메서드 블록을 아래 표에 정리했습니다. | 구분 | 코드 블록 | | :--- | :--- | | **타이머 로직 (CardPairGameLogic)** | ```lua<br>Method:<br>[client only]<br>void OnUpdate (number delta)<br>{<br> self.RemainingTime = self.RemainingTime - delta<br> log(self.RemainingTime)<br>}<br>` [followup] | [followup_answer] | [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] | 0초 이후 타이머가 음수로 감소하는 현상을 방지하고, 0초가 되면 UI를 비활성화하는 로직 변경 사항은 다음과 같습니다. 1. `CardPairGameLogic` 컴포넌트에 `[client only]` 속성을 가진 `EndGame()` 메서드를 추가하여, 게임 종료 시 `CardPairGameUI`의 `Enable` 프로퍼티를 `false`로 설정하도록 구현합니다. ```lua [client only] void EndGame () { self.CardPairGameUI.Enable = false [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 타이머를 완성했지만 이번에도 한 가지 추가하면 좋겠습니다 타이머가 0초가 된 이후에 수가 음수로 계속해서 감소하고 있습니다. 일반적으로 수가 줄어드는 모습을 보면, 0초가 되었을 때 게임이 종료될 거라 기대합니다. 그러나 지금은 0초 이후 수가 음수로 줄어들고 있습니다. 0초가 되면 ui가 꺼지게 만들어 봅시다. 1. **CardPairGameLogic** 로직의 `EndGame` 함수에 아래와 같이 작성합니다. ```lua [client only] void EndGame () {
[task] | two_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | 스프라이트 애니메이션의 재생 중 특정 프레임이 도달했을 때 다른 애니메이션으로 전환하는 로직을 구현하고 싶다 [answer] | 스프라이트 애니메이션이 재생되는 동안 특정 프레임에 도달했을 때 다른 애니메이션으로 전환하려면, `SpriteAnimPlayerChangeFrameEvent` 이벤트를 처리하는 핸들러를 구현하면 됩니다. 이벤트는 프레임 번호(`FrameIndex`)를 전달하므로, 이 값을 비교하여 원하는 프레임이 되면 `BodyActionStateChangeEvent`를 보내어 애니메이션을 변경할 수 있습니다. 아래는 해당 로직을 구현한 mLua 스크립트 예제입니다. ```lua Event Handler: [self] HandleSpriteA [followup] | SpriteAnimPlayerChangeFrameEvent를 ConnectEvent로 연결하여 FrameIndex가 특정 값일 때 애니메이션을 변경하는 mLua 코드 예시를 보여줘 [followup_answer] | 참고 문서에 따르면, `SpriteAnimPlayerChangeFrameEvent`는 `ConnectEvent`를 사용하여 아바타의 **Body** 또는 **Face**에 연결해야 제대로 사용할 수 있습니다. `FrameIndex`가 특정 값일 때 애니메이션을 변경하는 로직은 `StateComponent`의 `ChangeState` 메서드를 호출하는 방식으로 구현할 수 있습니다. 아래는 `InitStateComponentEventHandler` 메서드 내에서 이벤트를 연결하고, 특정 프레임 도달 시 상태를 변경하는 mLua 코드 [scores] | [judge_reason] | [source_doc] | 애니메이션 변경 과정을 정리하면 다음과 같습니다. 위에서 알아본 3가지 아바타 애니메이션 제어 방법의 장단점을 정리하면 아래 표와 같습니다. 각 방법은 장단점이 명확하므로 크리에이터의 의도에 맞는 방법을 적절히 선택하면 됩니다. | 아바타 애니메이션 제어 방법 | 장점 | 단점 | | :---: | --- | --- | | ActionStateChangedEvent | <ul> <li>몸통과 파츠 애니메이션을 각각 다르게 조절할 수 있습니다.</li> <li>재생 속도, 재생 타입, 애니메이션 시작/종료 프레임을 세밀하게 설
[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | ActionStateChangedEvent가 발생했을 때, Body와 Face의 액션 이름을 각각 변수에 저장하고, CoreActionName이 비어있지 않은 경우에만 Body 액션을 재생하도록 조건 분기를 처리하는 스크립트를 작성해줘. [answer] | ActionStateChangedEvent는 아바타의 Body와 Face 애니메이션을 제어하는 데 사용되며, 이벤트 객체를 통해 CoreActionName(몸통 액션 이름)과 PartsActionName(파츠/얼굴 액션 이름)을 접근할 수 있습니다. 요청하신 조건에 맞춰 Body와 Face의 액션 이름을 변수에 저장하고, CoreActionName이 비어있지 않을 때만 Body 액션을 재생하는 스크립트는 다음과 같습니다. ```lua Event Handler: [self] HandleActionStateChangedEvent(Ac [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 아바타 애니메이션을 제어하는 3가지 방법을 살펴봅니다. 본 과정을 통해 크리에이터가 원하는 기능에 맞게 아바타 애니메이션을 제어해 봅시다. # ActionStateChangedEvent로 제어 아바타는 **AvatarRoot**에 **Body**와 **Face**로 나뉘어 있습니다. **Body**는 말 그대로 아바타의 몸통이며 **Face**는 아바타의 얼굴을 뜻합니다. 아바타의 **Body**와 **Face**에 어떤 애니메이션을 재생할지는 [ActionStateChangedEvent](/apiRefer
[task] | single_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | 애니메이션 프레임 인덱스가 2일 때 swingOF 애니메이션으로 전환되는 로직에서 Loop 타입을 지정하는 파라미터 값은 어떻게 정하나요? [answer] | `ActionStateChangedEvent`를 생성할 때 4번째 파라미터에 애니메이션 재생 타입을 지정합니다. `swingOF` 애니메이션을 반복(Loop) 재생하려면 해당 파라미터에 `SpriteAnimClipPlayType.Loop`를 사용합니다. 참고 문서에 제시된 `ChangeFrameEvent` 함수의 예제를 보면, 프레임 인덱스가 2일 때 `swingOF` 애니메이션으로 전환하는 로직은 다음과 같습니다. ```lua [client] void ChangeFrameEvent(any event) { if event [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 3. 아까 저장한 **handler**를 통해 **SpriteAnimPlayerChangeFrameEvent** 구독을 취소합니다. `ChangeFrameEvent` 함수를 수정해 봅시다. ```lua [client] void ChangeFrameEvent(any event) { if event.FrameIndex == 2 then local body = self.Entity.AvatarRendererComponent:GetBodyEntity()
[task] | single_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | 제작 중 빠르게 게임 종료 여부를 확인하기 위해 추천되는 PlayTime 설정 팁은 무엇인가요? [answer] | 제작 중에는 게임이 빠르게 종료되도록 **PlayTime**의 초깃값을 60 대신 작은 수로 설정하는 것이 좋습니다. 이렇게 하면 타이머가 빠르게 감소하는지, 그리고 게임이 정상적으로 종료되는지 빠르게 확인할 수 있습니다. [followup] | [followup_answer] | [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] | 타이머가 60초가 아닌 다른 시간으로 시작하게 하려면 어떤 프로퍼티 값을 수정해야 하나요? [answer] | 게임 제한 시간을 변경하려면 **CardPairGameLogic** 로직의 **PlayTime** 프로퍼티 값을 수정하면 됩니다. 기본값은 60초로 설정되어 있지만, 원하는 시간(예: 30초)으로 바꾸려면 해당 숫자를 변경합니다. ```lua Property: [None] number PlayTime = 30 [None] number RemainingTime = 0 ``` 이 값은 게임 시작 시 `StartGame()` 함수에서 `self.RemainingTime`에 대입되어 타이머의 초기 시간으로 사용됩니다. [followup] | [followup_answer] | [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] | 무기 변경에 따라 자동으로 애니메이션이 바뀌어야 하는 상황에서 BodyActionStateChangeEvent 를 사용할 때 MapleAvatarBodyActionState 에 없는 상태는 어떻게 처리해야 하나요? [answer] | 참고 문서에 따르면, `BodyActionStateChangeEvent`를 사용할 경우 `MapleAvatarBodyActionState`에서 정의되지 않은 상태로는 변경할 수 없습니다. 이는 해당 이벤트의 단점으로 명시되어 있습니다. 따라서 `MapleAvatarBodyActionState`에 없는 상태가 필요한 상황이라면, `BodyActionStateChangeEvent`는 사용할 수 없으며, 다른 제어 방법을 선택해야 합니다. 문서에 제시된 대안은 다음과 같습니다: 1. **`ActionStateChangedEvent` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 애니메이션 변경 과정을 정리하면 다음과 같습니다. 위에서 알아본 3가지 아바타 애니메이션 제어 방법의 장단점을 정리하면 아래 표와 같습니다. 각 방법은 장단점이 명확하므로 크리에이터의 의도에 맞는 방법을 적절히 선택하면 됩니다. | 아바타 애니메이션 제어 방법 | 장점 | 단점 | | :---: | --- | --- | | ActionStateChangedEvent | <ul> <li>몸통과 파츠 애니메이션을 각각 다르게 조절할 수 있습니다.</li> <li>재생 속도, 재생 타입, 애니메이션 시작/종료 프레임을 세밀하게 설
[task] | single_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | 크리에이터가 수동으로 새로운 상태를 추가하여 ActionSheet에 반영하는 과정은 어떻게 이루어지나요? [answer] | 크리에이터가 수동으로 새로운 상태를 추가하여 `ActionSheet`에 반영하는 과정은 다음과 같이 이루어집니다. 1. **새로운 상태 이름 정의**: 기존 기본 상태(IDLE, MOVE 등)와 구별되는 새로운 상태 이름을 정의합니다. 2. **ActionSheet 값 설정**: `AvatarStateAnimationComponent`의 `ActionSheet`에서 해당 새로운 상태 이름(Key)에 대해 재생하고자 하는 애니메이션 이름(Value)을 설정합니다. * **Key**: 새로 추가할 상태 이름 (예: `C [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 이미 정의된, 혹은 새로 정의할 아바타의 상태가 바뀔 때마다 매번 이벤트를 보내서 애니메이션을 변경하는 것도 번거로울 수 있습니다. 이벤트를 보내지 않고도 아바타 상태가 바뀔 때마다 애니메이션도 함께 변경되면 매우 편리할 것입니다. [AvatarStateAnimationComponent](/apiReference/Components/AvatarStateAnimationComponent)의 **ActionSheet**에 아바타 상태와 연결될 애니메이션을 설정하고 [StateComponent](/apiReference/Component
[task] | single_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | ActionSheet에서 Key와 Value가 각각 무엇을 의미하며, StateComponent로 상태를 바꾸면 애니메이션이 어떻게 연동되는지 설명해 주세요. [answer] | ActionSheet는 아바타의 상태(State)와 재생할 몸통 애니메이션(MapleAvatarBodyActionState)을 매핑하는 테이블입니다. **1. Key와 Value의 의미** * **Key**: 아바타의 **State**를 의미합니다. (예: `IDLE`, `MOVE`, `ATTACK`, `HIT`, `CROUCH`, `FALL`, `JUMP`, `CLIMB`, `LADDER`, `DEAD`, `SIT`) * **Value**: 해당 Key가 적용될 때 재생될 **MapleAvatarBodyActionStat [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 이미 정의된, 혹은 새로 정의할 아바타의 상태가 바뀔 때마다 매번 이벤트를 보내서 애니메이션을 변경하는 것도 번거로울 수 있습니다. 이벤트를 보내지 않고도 아바타 상태가 바뀔 때마다 애니메이션도 함께 변경되면 매우 편리할 것입니다. [AvatarStateAnimationComponent](/apiReference/Components/AvatarStateAnimationComponent)의 **ActionSheet**에 아바타 상태와 연결될 애니메이션을 설정하고 [StateComponent](/apiReference/Component
[task] | instruction_following [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | DeselectCard 메서드에서 self.SelectedCard:CardOff() 호출 후 nil 할당하는 순서가 중요한 이유를 3문장 이내로 설명하세요. [answer] | `CardOff()` 호출 시에는 여전히 유효한 참조가 존재해야 하므로, 그 전에 `nil`로 초기화하면 메서드 호출이 불가능해집니다. 따라서 시각적 상태 변경이 완료된 후 참조를 해제해야 런타임 오류를 방지할 수 있습니다. [followup] | [followup_answer] | [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] | SpriteAnimPlayerChangeFrameEvent 를 처리하기 위해 ConnectEvent 를 호출할 때 아바타의 Body 나 Face 중 어디에 연결해야 이벤트가 정상적으로 발생하나요? [answer] | SpriteAnimPlayerChangeFrameEvent는 스프라이트 애니메이션의 프레임이 바뀔 때 발생하는 이벤트입니다. 이 이벤트를 정상적으로 수신하기 위해서는 아바타의 **Body** 또는 **Face**에 `ConnectEvent`를 통해 연결해야 합니다. 참고 문서에는 Body와 Face 중 특정 한 곳만 지정해야 한다는 제한은 명시되어 있지 않으며, "아바타의 **Body** 또는 **Face**에 연결해야 제대로 사용할 수 있습니다"라고 안내하고 있습니다. 따라서 스프라이트 렌더러가 적용된 컴포넌트(Body 또는 F [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 애니메이션 변경 과정을 정리하면 다음과 같습니다. 위에서 알아본 3가지 아바타 애니메이션 제어 방법의 장단점을 정리하면 아래 표와 같습니다. 각 방법은 장단점이 명확하므로 크리에이터의 의도에 맞는 방법을 적절히 선택하면 됩니다. | 아바타 애니메이션 제어 방법 | 장점 | 단점 | | :---: | --- | --- | | ActionStateChangedEvent | <ul> <li>몸통과 파츠 애니메이션을 각각 다르게 조절할 수 있습니다.</li> <li>재생 속도, 재생 타입, 애니메이션 시작/종료 프레임을 세밀하게 설
[task] | code [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | `CardPairGameLogic` 컴포넌트에서 `RemainingTime` 프로퍼티가 0 이하가 되면 `CardPairGameUI` 컴포넌트의 `Enable` 프로퍼티를 `false`로 설정하여 UI를 비활성화하는 로직을 `OnUpdate` 생명주기 메서드 내에 구현하는 스크립트를 작성해줘 [answer] | 타이머가 0초가 되는 순간 게임이 종료되도록 하려면, `OnUpdate`에서 `RemainingTime`이 0 이하인지 확인하고 해당 조건이 충족되면 `CardPairGameUI`의 `Enable` 프로퍼티를 `false`로 설정해야 합니다. 이를 위해 `EndGame` 메서드를 별도로 정의하여 UI 비활성화 로직을 분리하고, `OnUpdate`에서 이 메서드를 호출하는 구조로 스크립트를 작성할 수 있습니다. 아래는 `CardPairGameLogic` 컴포넌트의 전체 스크립트입니다. ```lua Property: [None] E [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 타이머를 완성했지만 이번에도 한 가지 추가하면 좋겠습니다 타이머가 0초가 된 이후에 수가 음수로 계속해서 감소하고 있습니다. 일반적으로 수가 줄어드는 모습을 보면, 0초가 되었을 때 게임이 종료될 거라 기대합니다. 그러나 지금은 0초 이후 수가 음수로 줄어들고 있습니다. 0초가 되면 ui가 꺼지게 만들어 봅시다. 1. **CardPairGameLogic** 로직의 `EndGame` 함수에 아래와 같이 작성합니다. ```lua [client only] void EndGame () {
[task] | two_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | 타이머가 0초가 되었을 때 UI를 자동으로 꺼지게 하는 로직을 어떻게 구현하나요? [answer] | 타이머가 0초가 되었을 때 UI를 자동으로 끄기 위해, `CardPairGameLogic` 스크립트에 `EndGame` 메서드를 추가하고 `OnUpdate`에서 `RemainingTime`을 확인하여 해당 메서드를 호출하는 방식으로 구현합니다. 구체적인 구현 방법은 다음과 같습니다. 1. **`EndGame` 메서드 추가**: `CardPairGameLogic` 스크립트에 UI를 비활성화하는 `EndGame` 함수를 정의합니다. 이 함수는 `self.CardPairGameUI.Enable` 속성을 `false`로 설정하여 UI [followup] | OnUpdate에서 RemainingTime이 0 이하가 될 때 EndGame()을 호출하여 CardPairGameUI의 Enable 속성을 false로 설정하는 코드를 어떻게 작성하나요? [followup_answer] | `OnUpdate`에서 `RemainingTime`이 0 이하가 될 때 `EndGame()`을 호출하고, `EndGame` 함수에서 `CardPairGameUI`의 `Enable` 속성을 `false`로 설정하는 코드는 다음과 같이 작성합니다. ```lua Property: [None] Entity CardPairGameUI = /ui/CardPairGameUI number RemainingTime = 0 Method: [client only] void OnUpdate(number delta) { if self.Remai [scores] | [judge_reason] | [source_doc] | 타이머를 완성했지만 이번에도 한 가지 추가하면 좋겠습니다 타이머가 0초가 된 이후에 수가 음수로 계속해서 감소하고 있습니다. 일반적으로 수가 줄어드는 모습을 보면, 0초가 되었을 때 게임이 종료될 거라 기대합니다. 그러나 지금은 0초 이후 수가 음수로 줄어들고 있습니다. 0초가 되면 ui가 꺼지게 만들어 봅시다. 1. **CardPairGameLogic** 로직의 `EndGame` 함수에 아래와 같이 작성합니다. ```lua [client only] void EndGame () {
[task] | single_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | 타이머 시간이 UI에 소수점 없이 정수로 나타나도록 하기 위해 어떤 함수와 메서드를 조합해서 사용해야 하나요? [answer] | 타이머 시간을 UI에 소수점 없이 정수로 표시하려면 `math.floor` 함수와 `tostring` 함수를 조합하여 사용합니다. 구체적인 조합 방식은 다음과 같습니다: 1. `math.floor(remainingTime)`: 실수(소수점 포함)인 남은 시간을 정수로 반내림합니다. 2. `tostring(...)`: `math.floor`로 변환된 정수 값을 텍스트 컴포넌트에 입력할 수 있는 문자열(string) 타입으로 변환합니다. 참고 문서의 `UpdateText` 함수 예제에서 이러한 조합을 확인할 수 있습니다. ```l [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 타이머 만들기 게임을 시작하면 1초씩 감소하는 타이머를 만들어봅시다. 1. **CardPairGameLogic** 로직에 게임 제한 시간으로 사용할 **PlayTime** 프로퍼티와 시간을 줄이기 위해 사용할 **RemainingTime** 프로퍼티를 추가합니다. PlayTime 초깃값은 **60**으로 설정합니다. ```lua Property: [None] number PlayTime = 60 [None] number RemainingTime = 0 ``` > **
[task] | two_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | ActionSheet와 StateComponent를 활용한 애니메이션 제어 방식에서 발생할 수 있는 단점, 특히 애니메이션 프레임 선택 불가와 자동 상태 변경 조건에 의한 간섭 문제는 어떻게 발생하나요? [answer] | ActionSheet와 StateComponent를 활용한 방식은 상태 변경 시 애니메이션을 자동으로 매칭시켜 주는 편리함이 있지만, 아래 두 가지 측면에서 제한이 있습니다. **1. 애니메이션 프레임 선택 불가** 이 방식에서는 `ActionSheet`의 Key(상태)에 해당하는 Value(`MapleAvatarBodyActionState`)가 정의된 대로 애니메이션이 재생됩니다. 즉, 크리에이터가 특정 애니메이션의 **시작 프레임**이나 **끝 프레임**을 임의로 지정하거나 잘라서 재생하는 것이 불가능합니다. 애니메이션은 항상 [followup] | 정의된 기본 상태 변경 조건이 활성화되어 있어 원하는 애니메이션이 출력되기 전에 상태가 바뀌는 상황을 방지하거나, 애니메이션 시작/끝 프레임을 제어해야 하는 경우를 대안으로 설명해 주세요. [followup_answer] | 참고 문서에 따르면, `ActionSheet`와 `StateComponent` 방식은 애니메이션의 시작과 끝 프레임을 선택할 수 없으며, 정의된 기본 또는 사용자 상태 변경 조건에 의해 상태가 자동으로 변경되어 원하는 애니메이션이 출력되기 전에 바뀌는 문제가 발생할 수 있습니다. 하지만 해당 문서에는 이러한 단점을 방지하거나 프레임 제어를 위한 **구체적인 대안 API나 코드 예제**가 명시되어 있지 않습니다. 문서에서는 이러한 한계를 인지하고 있을 때, 이벤트 기반으로 매번 애니메이션을 직접 제어하는 번거로운 방식을 언급하고 있 [scores] | [judge_reason] | [source_doc] | 이미 정의된, 혹은 새로 정의할 아바타의 상태가 바뀔 때마다 매번 이벤트를 보내서 애니메이션을 변경하는 것도 번거로울 수 있습니다. 이벤트를 보내지 않고도 아바타 상태가 바뀔 때마다 애니메이션도 함께 변경되면 매우 편리할 것입니다. [AvatarStateAnimationComponent](/apiReference/Components/AvatarStateAnimationComponent)의 **ActionSheet**에 아바타 상태와 연결될 애니메이션을 설정하고 [StateComponent](/apiReference/Component
[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | ActionStateChangedEvent를 통해 Body에 적용된 PartsActionName이 "Weapon_Swing"으로 변경될 때 log 함수를 사용하여 해당 액션 이름을 출력하고, Face에는 기본 표정으로 재설정하는 스크립트를 작성해줘. [answer] | 참고 문서에 따르면 `ActionStateChangedEvent`는 `CoreActionName`과 `PartsActionName`을 포함한 프로퍼티를 가지며, `AvatarRoot`의 `Body`와 `Face` 엔티티에 해당 이벤트를 보내어 애니메이션을 제어할 수 있습니다. 요청하신 기능은 서버 또는 클라이언트에서 특정 액션이 트리거되었을 때(예: 플레이어 액션 이벤트 수신 또는 직접 호출) `Body`에 `PartsActionName`이 `"Weapon_Swing"`인 `ActionStateChangedEvent`를 전송하고, [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 아바타 애니메이션을 제어하는 3가지 방법을 살펴봅니다. 본 과정을 통해 크리에이터가 원하는 기능에 맞게 아바타 애니메이션을 제어해 봅시다. # ActionStateChangedEvent로 제어 아바타는 **AvatarRoot**에 **Body**와 **Face**로 나뉘어 있습니다. **Body**는 말 그대로 아바타의 몸통이며 **Face**는 아바타의 얼굴을 뜻합니다. 아바타의 **Body**와 **Face**에 어떤 애니메이션을 재생할지는 [ActionStateChangedEvent](/apiRefer