msw-ai-tf/maplestory-worlds-creator-docs huggingface dataset:
아바타 상품 만들기

# 학습 과정 소개

메이플스토리 월드에서 크리에이터는 직접 제작한 아바타 아이템을 판매할 수 있습니다. 이번 가이드에서는 제작한 아바타 아이템 판매 방법을 알아봅니다. 판매하기 전에 아바타 아이템을 제작하고 등록하는 방법은 아래 가이드를 참고해 봅시다.

##### 참고 가이드

  * [아바타 아이템 제작](/docs/?postId=582)



> 더 알아보기 아이템 제작, 판매할 때는 을 준수하기 바랍니다.

# 아바타 상품 만들기

아바타 아이템을 판매하려면 먼저 아바타 아이템을 제작한 후 등록해야 합니다. [아바타 아이템 등록하기](/docs/?postId=590) 가이드를 참고하여 제작한 아이템을 먼저 등록한 뒤 아래 과정을 진행합니다.

  1. 아이템을 등록한 후 에 들어가 [아바타 상품 만들기] 메뉴를 클릭합니다. [png](1669007328991a5c617b7ca474648a05cb21e632762ff)   

  2. 아바타 아이템 목록에서 내가 등록한 아이템을 확인한 후, [+ 상품등록] 버튼을 클릭합니다. [png](16690073628804fdcf39b19d14594b6e5ff259b91e819)   

  3. 아바타 상품 만들기 페이지에서 상품 이름, 가격, 판매 기간, 출시 여부를 설정합니다. 상품 설명은 선택 입력 사항입니다. [png](166900757567106f1cba685c745408c2d2c8a946d6c15)   

  4. 이용약관에 동의한 후 [등록] 버튼을 클릭합니다.   

  5. 등록비를 결제하면 상품에 상점에 등록됩니다. [png](16690087351190c5842cc74524e81beec924fc4a8c332) [png](1669008749635e118c8be5b0148119d5f080e6cb66915)   

  6. 아바타 상품 목록에 정상적으로 등록된 것을 확인합니다. [png](1669008790305183b1d518e594964b3d31ec8e4a7fc24)   

  7. 클라이언트에서도 정상적으로 판매되는 것을 확인합니다.



# 아바타 상품 수정하기

이미 등록한 아바타 상품 정보를 수정할 수 있습니다.

  1. 아바타 상품 목록에서 원하는 상품의 [수정] 버튼을 클릭합니다. [png](166900912623816ad7427f92844bbba84178f28746f04)   

  2. 상품 가격, 판매 기간, 출시 여부 및 상품 설명을 수정할 수 있습니다. 원하는 정보를 수정 후 [수정] 버튼을 클릭합니다. [png](16690091362509ff950272fb949cb9ec05fe3b6e55afd)



# 아바타 상품 판매 상태

아바타 상품은 출시 여부, 등록비 결제 여부, 판매 기간, 제재 등에 따라 판매 상태가 달라집니다. 판매 상태는 다음과 같이 구분됩니다.

[{"판매 상태":"미출시","설명":"출시 여부를 '미출시'로 설정한 상태이며, 판매 기간이 되어도 상점에 노출되지 않고 판매도 불가합니다. 플레이어가 이미 보유하고 있는 상품도 확인 불가합니다."},{"판매 상태":"결제 대기","설명":"상품 등록 후 등록비를 결제하기 전 단계입니다."},{"판매 상태":"판매 대기","설명":"판매 시작일 이전에 등록이 완료된 상태로 상품의 판매 시작일에 맞춰 판매 중 상태로 변경됩니다."},{"판매 상태":"판매 중","설명":"판매가 시작된 상태로 판매 종료일이 설정된 경우 해당 기간까지 상품을 판매합니다."},{"판매 상태":"판매 종료","설명":"판매 종료일이 지난 상태로 상점에서 상품을 판매하지 않습니다."},{"판매 상태":"제재 중","설명":"해당 상품이 제재 처리된 상태입니다. 상점에서 노출되지 않으며 유저에게 판매할 수 없습니다."}]

상품은 판매 종료 상태가 되어도 플레이어가 이미 구매한 상품은 계속 소유할 수 있습니다.
global

# Functions

[{"index":"any assert(any v, string message = \"assertion failed!\") (Static)","0":"v의 값이 false 또는 nil이면 error를 호출합니다. 그렇지 않다면 인수 전체를 반환합니다. 오류의 경우 message가 오류 객체가 되며 인수가 없으면 \"assertion failed!\"을 사용합니다"}]

[{"index":"void error(string message, integer level = 1) (Static)","0":"함수를 종료하고 에러 메시지를 반환합니다."}]

[{"index":"any collectgarbage(string opt = \"collect\", any arg = nil) (Static)","0":"garbage collector의 포괄적 인터페이스입니다. opt에 따라서 다양한 기능을 수행합니다."}]

[{"index":"any getmetatable(any object) (Static)","0":"object에 메타테이블이 없으면 nil을 반환합니다. 메타테이블에 __metatable 필드가 있으면 연계된 값을 반환합니다. 그 외에는 object의 메타테이블을 반환합니다."}]

[{"index":"func, any, integer ipairs(any t) (Static)","0":"반복자 함수, t, 숫자 0을 반환합니다. 반복문에서 사용할 때 숫자 인덱스와 요소를 반복할 수 있습니다."}]

[{"index":"any, any next(table table, any index = nil) (Static)","0":"테이블의 다음 키와 요소를 반환합니다. Index가 지정된 경우 index를 기반으로 다음 키와 요소를 반환합니다. 숫자 인덱스의 경우에도 인덱스가 나오는 순서는 알 수 없습니다."}]

[{"index":"func, any, any pairs(any t) (Static)","0":"반복자 함수, t, nil을 반환합니다. 반복문에서 사용할 때 t의 키와 요소를 반복할 수 있습니다."}]

[{"index":"boolean, any... pcall(func f, any... args) (Static)","0":"주어진 인수들을 가지고 함수 f를 보호 모드로 호출합니다. f 안에서 오류가 발생하더라도 외부로 전달되지 않습니다. 대신 pcall이 오류를 잡아서 상태 코드를 반환합니다. 첫 번째 결과는 오류가 없으면 true를 반환하고, 두 번째 결과는 함수의 결괏값을 반환합니다. 오류 발생 시 false와 오류 메시지를 반환합니다."}]

[{"index":"void print(any... args) (Static)","0":"임의 개수의 인수를 받아 tostring 함수로 각 인수를 문자열로 변환한 값을 출력합니다."}]

[{"index":"boolean rawequal(any v1, any v2) (Static)","0":"__eq 메타메소드 호출 없이 v1이 v2와 같은지 확인합니다."}]

[{"index":"any rawget(table table, any index) (Static)","0":"__index 메타메소드 호출 없이 t[index]의 진짜 값을 얻습니다."}]

[{"index":"integer rawlen(any v) (Static)","0":"__len 메타메소드 호출 없이 v의 길이를 반환합니다."}]

[{"index":"table rawset(table table, any index, any value) (Static)","0":"__newindex 메타메소드 호출 없이 t[index]의 값을 value로 설정하고 테이블을 반환합니다."}]

[{"index":"any... select(any index, any... args) (Static)","0":"index가 수라면 index번째 뒤의 인수들을 반환합니다. 음수는 인덱스를 끝에서부터 거꾸로 셉니다. index가 수가 아니라면 문자열 \"#\"이어야 하고 나머지 인수들의 총개수를 반환합니다."}]

[{"index":"table setmetatable(table table, table metatable) (Static)","0":"t의 메타테이블을 설정하고 t를 반환합니다."}]

[{"index":"number tonumber(any e, integer base = 10) (Static)","0":"e를 number로 변환하고 반환합니다. 변환이 불가능하면 nil을 반환합니다. base로 진법을 지정할 수 있습니다."}]

[{"index":"string tostring(any v) (Static)","0":"v를 문자열로 변환합니다. v의 메타테이블에 __tostring 필드가 있으면 v를 매개 변수로 호출하고 결과를 반환합니다."}]

[{"index":"string type(any v) (Static)","0":"v의 타입을 문자열 형태로 반환합니다."}]

[{"index":"boolean, any... xpcall(func f, func msgh, any... args) (Static)","0":"pcall 함수와 동일하게 사용합니다. 다만, 새 메시지 핸들러 msgh를 설정할 수 있습니다."}]

[{"index":"table enum(table table) (Static)","0":"지정된 테이블의 키와 값을 교환 후 테이블을 반환합니다."}]

[{"index":"void wait(number seconds) (Static)","0":"seconds 동안 현재 스크립트의 실행을 중단합니다."}]

[{"index":"boolean isvalid(any object) (Static)","0":"객체 내부의 상태가 유효한지 확인합니다. nil 여부와 Entity, Component의 삭제 여부를 확인할 수 있습니다."}]

[{"index":"void log(any... args) (Static)","0":"tostring 함수로 각 인수를 문자열로 변환한 값을 정보 로그로 출력합니다."}]

[{"index":"void log_warning(any... args) (Static)","0":"tostring 함수로 각 인수를 문자열로 변환한 값을 경고 로그로 출력합니다."}]

[{"index":"void log_error(any... args) (Static)","0":"tostring 함수로 각 인수를 문자열로 변환한 값을 오류 로그로 출력합니다."}]
SkeletonGUIRendererComponent

Spine으로 제작된 스켈레톤 리소스를 UI에 그리고 제어할 수 있는 기능을 제공합니다. Spine 4.1로 제작된 리소스만 사용할 수 있습니다.

# Properties

[{"index":"SyncList AnimationNames","0":"1번 트랙에 애니메이션을 설정합니다. 애니메이션은 인덱스 순서대로 재생됩니다. 프로퍼티에 값을 추가하거나 제거하면 애니메이션이 처음부터 다시 재생됩니다."}]

[{"index":"Color Color","0":"색상을 설정합니다."}]

[{"index":"boolean FlipX","0":"X축을 기준으로 반전 여부를 결정합니다."}]

[{"index":"boolean FlipY","0":"Y축을 기준으로 반전 여부를 결정합니다."}]

[{"index":"boolean Loop","0":"애니메이션 반복 재생 여부를 설정합니다."}]

[{"index":"float PlayRate","0":"애니메이션 재생 속도를 설정합니다."}]

[{"index":"PreserveSpriteType PreserveMode","0":"스켈레톤 리소스의 비율, 피봇, 크기 등이 유지되는 방식을 설정합니다."}]

[{"index":"boolean RaycastTarget","0":"true로 설정할 경우 화면 터치 또는 마우스 클릭 대상이 되며, 뒤에 가려진 UI는 화면 터치와 마우스 클릭 입력을 받지 못합니다."}]

[{"index":"string SkeletonRUID","0":"스켈레톤 리소스의 RUID를 설정합니다."}]

[{"index":"SyncList SkinNames","0":"스킨을 설정합니다."}]

##### inherited from Component:

[{"index":"boolean Enable (Sync)","0":"컴포넌트 활성화 여부를 확인합니다."}]

[{"index":"boolean EnableInHierarchy (ReadOnly) (HideFromInspector)","0":"계층 구조상에서 이 컴포넌트가 Enable 상태인지를 반환합니다. Enable이 true일지라도 엔티티의 Enable이 false라면 false를 반환합니다."}]

[{"index":"Entity Entity (ReadOnly)","0":"이 컴포넌트를 소유한 엔티티입니다."}]

# Methods

[{"index":"void AddAnimation(SkeletonAnimationClip animationClip) (ClientOnly)","0":"트랙에 애니메이션을 추가합니다. 1번 트랙은 사용할 수 없습니다. animationClip에는 트랙 번호, 애니메이션 이름, 기타 속성을 지정합니다. 애니메이션이 처음부터 다시 재생됩니다."}]

[{"index":"void AddEmptyAnimation(SkeletonAnimationClip animationClip) (ClientOnly)","0":"트랙에 빈 애니메이션을 추가합니다. 1번 트랙은 사용할 수 없습니다. animationClip에는 트랙 번호, 기타 속성을 설정합니다.애니메이션이 처음부터 다시 재생됩니다."}]

[{"index":"void ClearTrack(int32 trackIndex) (ClientOnly)","0":"트랙을 비웁니다. 1번 트랙은 사용할 수 없습니다."}]

[{"index":"SkeletonAnimationClip GetCurrentAnimation(int32 trackIndex) (ClientOnly)","0":"현재 재생 중인 애니메이션을 반환합니다."}]

[{"index":"void SetAnimation(SkeletonAnimationClip animationClip) (ClientOnly)","0":"트랙을 비우고 애니메이션을 추가합니다. animationClip에는 트랙 번호, 애니메이션 이름, 기타 속성을 지정합니다. 1번 트랙은 사용할 수 없습니다."}]

[{"index":"void SetAttachment(string slotName, string attachmentName) (ClientOnly)","0":"슬롯에 어태치먼트를 붙입니다. attachmentName이 nil이면 슬롯에서 어태치먼트를 제거합니다."}]

[{"index":"void SetEmptyAnimation(SkeletonAnimationClip animationClip) (ClientOnly)","0":"트랙을 비우고 빈 애니메이션을 추가합니다. animationClip에는 트랙 번호, 기타 속성을 지정합니다. 1번 트랙은 사용할 수 없습니다."}]

##### inherited from Component:

[{"index":"boolean IsClient()","0":"현재 실행 환경이 클라이언트인지 아닌지의 여부를 반환합니다."}]

[{"index":"boolean IsServer()","0":"현재 실행 환경이 서버인지 아닌지의 여부를 반환합니다."}]

# Events

[{"index":"SkeletonAnimationCompleteEvent","0":"스켈레톤 애니메이션의 재생이 완료되었을 때 발생하는 이벤트입니다. 반복 재생되는 경우, 재생이 완료될 때마다 발생합니다."}]

[{"index":"SkeletonAnimationEndEvent","0":"스켈레톤 애니메이션이 전환될 때, 종료되는 애니메이션에서 발생하는 이벤트입니다."}]

[{"index":"SkeletonAnimationStartEvent","0":"스켈레톤 애니메이션이 전환될 때, 새롭게 재생되는 애니메이션에서 발생하는 이벤트입니다."}]

[{"index":"SkeletonAnimationTimelineEvent","0":"스켈레톤 애니메이션이 재생 중일 때, 애니메이션 타임라인에 등록된 이벤트가 감지되면 발생하는 이벤트입니다."}]
자동 번역

# 학습 과정 소개

메이플스토리 월드에서는 크리에이터가 지원하지 않은 언어의 자동 번역 기능을 지원합니다. 이 기능을 통해 크리에이터는 번역 부담을 덜고, 다양한 언어 사용자들은 보다 편하게 월드를 즐길 수 있습니다. 이번 과정에서는 자동 번역 기능 작동 방식과 설정 방법을 알아봅시다.

##### 참고 가이드

[WorldConfig](/docs?postId=1101) [로컬라이징의 이해](/docs/?postId=951) [포맷에 맞게 로컬라이징하기](/docs/?postId=968)

##### 참고 API Reference

[TextComponent](/apiReference/Components/TextComponent) [TextInputComponent](/apiReference/Components/TextInputComponent) [TextRendererComponent](/apiReference/Components/TextRendererComponent%7B%22target%22:%22_blank%22%7D) [ChatBalloonComponent](/apiReference/Components/ChatBalloonComponent)

# 자동 번역 개념 소개

자동 번역은 크리에이터가 정식으로 지원하지 않는 언어의 번역을 기계 번역을 통해 제공하는 것을 의미합니다.

예를 들어 모어가 영어이며, 이중언어 구사자는 아닌 크리에이터가 월드를 제작해 출시했다고 생각해 봅시다. 이 크리에이터는 혼자 월드를 제작하고 있으므로, 월드에서 사용한 모든 단어와 문장을 다개국어로 번역해 제공하는 것은 시간 여건상 쉽지 않습니다. 이때 크리에이터는 자동 번역을 사용할 수 있습니다. 모어로 자동 번역 기준이 되는 원문만 작성하고, 지원 언어 또한 자신의 모어인 영어로만 설정해 월드를 출시합니다.

이 월드에 한국어만 구사하는 플레이어가 월드 언어 설정을 한국어로 변경하면 월드를 한국어로 즐길 수 있게 됩니다. 월드 설정에서 언어(자동 번역)로 표시되는 언어 중 번역하고자 하는 언어인 한국어를 선택하면 월드의 언어가 번역됩니다.

> 더 알아보기
> 
>   * 자동 번역 옵션의 설정 정보는 기기별로 저장됩니다.
>   * 번역할 내용이 5,000자 이상이면 번역되지 않으므로 주의해야 합니다.
> 


# 자동 번역 설정

플레이어가 언어 설정 변경을 통해 자동 번역을 사용하기 위해서 크리에이터는 AllowAutomaticTranslation을 활성화해야 합니다. 이 프로퍼티는 `TextComponent, TextInputComponent, TextRendererComponent, ChatBalloonComponent`에 있습니다. 예제를 통해 자동 번역 설정 방법을 살펴봅시다.

  1. 자동 번역할 텍스트 엔티티의 `TextComponent, TextInputComponent, TextRendererComponent, ChatBalloonComponent`에서 AllowAutomaticTranslation를 활성화합니다. [png](16983007897332bb3b13efdb14c27baa6ce77d2fd6f42)
  2. 월드 출시 시 크리에이터가 정한 원문 언어와 직접 번역을 제공하는 언어를 지원 언어로 설정합니다. 출시 시 지원 언어로 설정하지 않은 언어는 자동 번역으로 제공됩니다. 출시한 월드에서 플레이어가 월드 언어에서 자동 번역 대상 언어로 설정할 경우, AllowAutomaticTranslation가 활성화된 모든 엔티티는 자동으로 번역됩니다.



[png](1698300827862477f0eab1ddc424e9f1a44c2658b117e)

> Tip. 크리에이터가 번역 기준으로 삼은 원문 언어는 Workspace - WorldConfig - SourceLanguage에서 설정할 수 있습니다. [png](1698826078961925a793678514dc0821fb980cf8072ee)

> 더 알아보기 설정한 SourceLanguage와 다른 언어를 크리에이터가 월드에 임의로 입력한 경우 자동 번역이 정상적으로 동작하지 않을 수 있습니다. 자동 번역 시 작성된 언어와 상관없이 SourceLanguage로 설정한 언어로 가정하고 번역하기 때문입니다. 

# 자동 번역 작동 방식

출시한 월드에 접속한 플레이어는 월드 언어 설정 창에서 해당 월드를 어떤 언어로 플레이할지 설정할 수 있습니다. 해당 월드의 미지원 언어는 월드 언어 목록에서 자동 번역으로 표시됩니다. 플레이어가 월드 언어에서 자동 번역 대상 언어를 설정할 경우, AllowAutomaticTranslation 프로퍼티가 활성화된 모든 엔티티는 자동 번역됩니다.

[png](1739775149202fb0268e2a9b344eaa392cc8c110b9514)
화면 전환 효과 재생하기

# 학습 과정 소개

맵 이동할 때 부드러운 화면 전환 연출 기능을 제공하는 ScreenTransitionService에 대해 알아봅시다. 한 맵에서 다른 맵으로 이동할 때 전환 효과를 사용하면 플레이어가 명확하게 맵이 달라졌음을 인지할 수 있게 됩니다.

### Fade In, Fade Out

Fade In과 Fade Out은 맵 이동 시에 사용하는 연출입니다. 두 효과는 화면의 투명도를 조절해 점점 어두워지거나 밝아지다가 새로운 장면이 나타납니다. Fade In/Out 효과 재생과 재생 중단 시점에는 시작, 종료 이벤트가 발생합니다. 그러나 Fade In 효과 재생이 끝나기 전에 Fade Out이 시작된다면 `FadeInEndEvent`가 발생하지 않습니다.

  * Fade In: 맵 이동 시 화면이 점점 밝아지다가 전환 효과가 사라집니다. 맵 이동 시 사용할지를 결정해야 합니다. [gif](1768372730766154d87c428f54500affbe0da58b75c9d)
  * Fade Out: 맵 이동 시 화면이 점점 어두워지다가 전환 효과가 사라집니다. 맵 이동 시 사용할지를 결정해야 합니다. [gif](1768445001703af162a3065e34b3a980ff6f739c63892)



#### 주의 사항

  * Fade 효과 재생 시간은 최대 3초입니다.
  * Fade 효과 재생 중에는 UI를 조작할 수 없습니다.
  * Fade 재생 중 ScreenTransition의 `Set()` 계열 함수를 사용하면 Fade 재생이 완료된 뒤 값이 적용됩니다.
  * 룸과 월드 이동 시 FadeOut은 동작하지 않습니다.



### Dissolve

Dissolve란 이전 장면이 서서히 사라지면서 새로운 장면이 서서히 나타나는 효과입니다. 이 과정에서 중간 혼합 형태가 나타납니다. Dissolve를 사용할 때는 스크립트에서 이 연출을 어떻게 사용할지 크리에이터가 정해야 합니다. [gif](17683534723100d4c346e0f6148aa91583b39e0a0720c)

#### 주의 사항

  * Dissolve 시간은 최대 3초입니다.
  * 현재 화면 해상도에 맞춰 텍스처를 생성하므로 끊김 현상이 발생할 수 있습니다. 또한 메모리 사용량이 증가합니다. 모바일 환경에서 플레이가 가능한 월드의 경우 Dissolve 사용에 유의해야 합니다.



# 활용 예시

맵 2개와 이동할 수 있는 포탈을 만들어 봅시다. 두 맵을 이동할 때마다 전환 연출이 재생되도록 만들어봅시다.

#### FadeIn/Out 사용하기

맵 이동 시 Fade In과 Fade Out이 동작하도록 `SetFadeInOutEnable()`, `SetFadeInTime()`, `SetFadeOutTime()` 함수를 사용해봅시다.

  1. 새로운 ScreenTransitionLogic을 생성합니다.

  2. `OnBeginPlay()`를 추가하고 맵 이동 시 전환 효과가 재생될 수 있도록 아래와 같이 작성합니다. `SetFadeInTime()`, `SetFadeOutTime()`은 각각 1.5초로 설정합니다.
         
         @Component
         script ScreenFadeConfigurator extends Component
         @ExecSpace("ClientOnly")
         method void OnBeginPlay()
         _ScreenTransitionService:SetFadeInOutEnable(true)
         _ScreenTransitionService:SetFadeInTime(1.5)
         _ScreenTransitionService:SetFadeOutTime(1.5)
         end
         end
         



    
    
    4. 포탈을 통해 맵을 이동해보며 Fade Out과 Fade In 효과가 동작하는지 확인합니다.
    
    #### Dissolve 사용하기
    **Y** 키를 눌렀을 때 Dissolve 효과가 나타나도록 만들어 봅시다.
    
    

@Component script InputTransitionHandler extends Component @EventSender("Service", "InputService") handler HandleKeyDownEvent(KeyDownEvent event) \--------------- Native Event Sender Info ---------------- \-- Sender: InputService \-- Space: Client \---------------------------------------------------------
    
    
    -- Parameters
    local key = event.key
    ---------------------------------------------------------
    
    if key == KeyboardKey.Y then
    	_ScreenTransitionService:DissolveScreen(3, true, false)
    end
    end
    

end
    
    
    #### Dissolve와 Fade In/Out 중첩
    맵을 이동해 Fade In 혹은 Fade Out 효과가 재생되고 있는 중에 Dissolve 실행이 중첩된다면, Fade Out 시작부터 Fade In 시작하기 전에는 Dissolve를 실행할 수 없습니다. 
    반대로 Dissolve 실행 중 맵을 이동해 Fade In/Out 실행이 중첩된다면, Fade In/Out은 실행되고, Dissolve 실행은 중지됩니다.
    
    만약 Dissolve 효과를 최우선 순위로 재생하고, Fade In/Out 효과를 차단하고 싶다면 `DissolveScreen()`의 매개 변수 `isHighPriorityThanFadeInOut`를 **true**로 설정해야 합니다.
    
    

@Component script InitialScreenDissolve extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() _ScreenTransitionService:DissolveScreen(3, true, true) end end
데이터 편집

# 학습 과정 소개

데이터 셋을 이용해 데이터를 추가하거나 수정할 수 있습니다. 이번 가이드에서는 데이터의 생성 및 편집 방법, 스크립트로 데이터를 불러오는 방법에 대해 알아봅니다.

# 데이터 셋 생성 및 데이터 에디터 열기

  1. Workspace - MyDesk의 콘텍스트 메뉴에서 Create DataSet을 클릭합니다.

  2. 생성된 데이터를 더블클릭하여 데이터 에디터를 엽니다. [png](16354715533571c67244b3c0e4ba688af580c8c34a7dc)




# 데이터 에디터

   


[{"번호":"[jpg](1634541272181b5c1a55fcf3d49b19734d25913c38583)","설명":"컬럼 셀각 열의 데이터명, 즉 컬럼 명을 정의합니다.각 열의 데이터를 가져올 때 컬럼 명을 통해 가져올 수 있습니다."},{"번호":"[jpg](1634541300837cb541c2f44e046a79bb1901a885aa8ac)","설명":"셀각 셀은 인풋 텍스트 필드로 각 열의 정의에 적합한 데이터 값을 입력합니다.입력한 데이터 값은 모두 스트링으로 저장됩니다."},{"번호":"[jpg](163454131465069e090278448490f965207e9a4a10348)","설명":"행\/열 추가 버튼버튼을 누르면 행\/열 끝에 새로운 행이나 열을 추가합니다."},{"번호":"[jpg](1634541326353d8628c1473944497bf376acb7a65ca45)","설명":"행\/열 삽입 및 삭제 핸들러선택한 행\/열을 기준으로 상하\/좌우에 새로운 행\/열을 추가하거나 선택한 행\/열을 삭제할 수 있습니다.핸들러는 각 머리 행 또는 머리 열을 선택하면 노출됩니다."},{"번호":"[jpg](1634541338689678f574f21e54a6ca533737924124d7e)","설명":"웹에서 데이터 가져오기GoogleSpreadSheet의 데이터를 가져올 수 있습니다.GoogleSpreadSheet에서 데이터를 작성한 후 해당 데이터의 URL을 팝업창에 넣어주면현재 열려있는 데이터에 GoogleSpreadSheet의 데이터를 덮어씌웁니다.단, GoogleSpreadSheet의 URL은 웹에 게시한 URL만 사용할 수 있습니다. [png](1656660216362c29ce81d29e6400caa25bc648b91058a)"},{"번호":"[jpg](163454135201207284554a25b498380fff224cd767f6b)","설명":"CSV 파일 불러오기컴퓨터에 저장된 CSV 파일을 가져와 현재 데이터에 덮어씌울 수 있습니다.utf-8로 저장된 CSV 파일만 정상적으로 가져올 수 있습니다.CSV 파일 내보내기메이커의 DataSet을 CSV 파일로 내보내어 컴퓨터에 저장할 수 있습니다."}]

  
# 작성한 데이터 스크립트에서 불러오기 

  1. 먼저 위에 생성한 NewDataSet에 다음과 같이 데이터를 작성합니다. [png](16596783003508b1add63e564405d9f00a099a8496934)   

  2. 데이터를 저장하고 새 스크립트 컴포넌트 DataSet을 추가합니다. [png](16878457449028bebb7ed9b9141288f93dd176baca7c5)   

  3. DataSet 컴포넌트를 열고, `OnBeginPlay()` 함수를 추가합니다. [png](16354715733367404d00c99aa45de86f5cc5cdfe101ec)   

  4. 다음과 같이 작성합니다. 
         
         @Component
         script FixedCellDataReader extends Component
         @ExecSpace("ServerOnly")
         method void OnBeginPlay()
         --위에 생성한 데이터의 이름으로 데이터 테이블을 가져옵니다.
         local dataSet = _DataService:GetTable("NewDataSet")    
         --가져오려는 셀 데이터의 행, 열 번호를 매개 변수로 입력해 줍니다.
         local cellValue = dataSet:GetCell(3,2)               
         --셀 값을 콘솔창에 출력합니다.
         log("cellValue : "..tostring(cellValue))             
         end
         end
         



    
    
          
    
    5. **Hierarchy - map01**의 콘텍스트 메뉴에서 **Add Component**를 클릭합니다.
          
    
    6. **DataSet**을 검색하여 **DataSet** 컴포넌트를 추가합니다.
        [png](1637219296068e486bb5b29b4418b9ef31c1647ad3323)
    
        >**더 알아보기**
        >**_DataService:GetTable(string name)**
        > 데이터의 이름으로 데이터 테이블을 리턴하는 함수입니다.
        > 매개 변수로 데이터 이름을 넘겨줍니다.
        >   
    
        > **UserDataSet:GetCell(int row_1based, int col_based)**
        > 데이터에서 특정 셀의 값을 문자열 타입으로 리턴합니다.
        > 매개 변수로는 셀이 위치한 행, 열 번호를 입력해 줍니다.
        > 행과 열은 1부터 시작합니다.
          
            
    7. 플레이를 눌러 콘솔 창을 확인합니다.
    [png](165967905703060d30eec2560433d9a4922fefc9ed0db)
배지 관리하기

# 학습 과정 소개

배지 뷰어와 활용 방법, 배지 상태별 기능 제한에 대해 알아봅시다.

# Badge Viewer

메이커에서 배지를 등록하고, 관리할 수 있는 창입니다. 등록한 배지는 배지 등급에 따라 각각의 폴더에 자동으로 분류됩니다. 주요 콘텍스트 메뉴는 아래와 같습니다.

[png](1664444765338bb3429f3b420435394c759bd538122c7)

[{"메뉴 이름":"Copy Badge ID","설명":"등록한 배지의 ID를 복사합니다."},{"메뉴 이름":"Copy Badge Thumbnail RUID","설명":"등록한 배지의 섬네일 RUID를 복사합니다."},{"메뉴 이름":"Create New Badge","설명":"새로운 배지를 생성합니다."},{"메뉴 이름":"Edit Badge","설명":"등록한 배지를 수정합니다."},{"메뉴 이름":"Open Badge List(Web)","설명":"생성한 배지들의 상태를 확인할 수 있는 외부 브라우저 창을 엽니다."},{"메뉴 이름":"Refresh Viewer","설명":"배지 목록을 새로고침 합니다."}]

등록한 배지에 마우스를 올려 배지 정보를 확인할 수 있습니다. [png](16681333983706a072184cfb147a29d035c8591a8b10c)

# 배지 상태별 기능 제한

배지 상태에 따라 기능이 제한됩니다. 아래의 표를 참고하세요. 전체 배지를 검색할 때 획득 대기 상태인 배지를 노출하지 않으려면, 해당 배지를 미출시 상태로 변경하여 조회되지 않도록 할 수 있습니다.

[{"상태":"미출시","월드에서 정보 조회":"불가","월드에서 배지 노출":"노출 안 됨","실제 획득":"불가","테스트 획득":"가능","메이커\/웹 정보 수정":"가능","공식 홈페이지 배지 노출":"노출 안 됨"},{"상태":"획득 대기","월드에서 정보 조회":"가능","월드에서 배지 노출":"노출","실제 획득":"불가","테스트 획득":"가능","메이커\/웹 정보 수정":"가능","공식 홈페이지 배지 노출":"노출"},{"상태":"획득 가능","월드에서 정보 조회":"가능","월드에서 배지 노출":"노출","실제 획득":"가능","테스트 획득":"가능","메이커\/웹 정보 수정":"가능","공식 홈페이지 배지 노출":"노출"},{"상태":"획득 불가","월드에서 정보 조회":"가능","월드에서 배지 노출":"노출","실제 획득":"불가","테스트 획득":"가능","메이커\/웹 정보 수정":"가능","공식 홈페이지 배지 노출":"노출"},{"상태":"제재 중","월드에서 정보 조회":"가능","월드에서 배지 노출":"노출","실제 획득":"가능: 획득 시 제재 중 표시","테스트 획득":"가능: 획득 시 제재 중 표시","메이커\/웹 정보 수정":"가능","공식 홈페이지 배지 노출":"노출 안 됨"}]

#### 배지 제재 안내

크리에이터가 제작한 배지는 메이플스토리 월드의 에 따라 제재받을 수 있습니다. 제재받은 배지 이름은 월드 유저에게는 운영정책 위반 명칭으로 변경되어 보이게 됩니다. 더불어 배지 섬네일이 변경됩니다. 배지의 제재 내용은 Badge Viewer의 툴팁에서 확인할 수 있습니다.

제재 상품 관련 문의가 있다면 를 이용해 주세요.

# 메이커와 월드에서 차이

배지를 얻는 환경이 어디인지에 따라 아래와 같은 차이점이 있습니다.

[{"항목":"배지 획득 정보","메이커":"테스트 플레이 시작 시에는 항상 배지가 없는 것으로 체크됩니다. 테스트 플레이를 종료하면 획득한 배지 정보를 제거합니다.","출시된 월드":"한번 획득한 배지의 정보는 변경할 수 없습니다."},{"항목":"배지 조회","메이커":"미출시, 획득 대기, 획득 가능, 획득 불가 상태에서 모두 조회할 수 있습니다.","출시된 월드":"획득 대기, 획득 가능, 획득 불가 상태에서 조회할 수 있습니다."},{"항목":"획득 가능 상태","메이커":"미출시, 획득 대기, 획득 가능, 획득 불가 상태에서 모두 획득할 수 있습니다.","출시된 월드":"획득 가능 상태에서 획득할 수 있습니다."}]

##### 참고 가이드

  * [배지 등록하기](/docs/?postId=656)
  * [배지 서비스 활용하기](/docs/?postId=664)
SkeletonRendererComponent

Spine으로 제작된 스켈레톤 리소스를 그리고 제어할 수 있는 기능을 제공합니다. Spine 4.1로 제작된 리소스만 사용할 수 있습니다.

# Properties

[{"index":"SyncList AnimationNames (Sync)","0":"1번 트랙에 애니메이션을 설정합니다. 애니메이션은 인덱스 순서대로 재생됩니다. 프로퍼티에 값을 추가하거나 제거하면 애니메이션이 처음부터 다시 재생됩니다."}]

[{"index":"Color Color (Sync)","0":"색상을 설정합니다."}]

[{"index":"boolean FlipX (Sync)","0":"X축을 기준으로 반전 여부를 결정합니다."}]

[{"index":"boolean FlipY (Sync)","0":"Y축을 기준으로 반전 여부를 결정합니다."}]

[{"index":"boolean IgnoreMapLayerCheck (Sync)","0":"SortingLayer에 맵 레이어 이름을 지정했을 때 자동으로 치환되지 않습니다."}]

[{"index":"boolean Loop (Sync)","0":"애니메이션 반복 재생 여부를 설정합니다."}]

[{"index":"int32 OrderInLayer (Sync)","0":"같은 Layer 내의 우선순위를 결정합니다. 수가 클수록 앞에 보입니다."}]

[{"index":"float PlayRate (Sync)","0":"애니메이션 재생 속도를 설정합니다."}]

[{"index":"string SkeletonRUID (Sync)","0":"스켈레톤 리소스의 RUID를 설정합니다."}]

[{"index":"SyncList SkinNames (Sync)","0":"스킨을 설정합니다."}]

[{"index":"string SortingLayer (Sync)","0":"2개 이상의 엔티티가 겹쳤을 때 Sorting Layer에 따라 보이는 우선순위가 결정됩니다."}]

##### inherited from Component:

[{"index":"boolean Enable (Sync)","0":"컴포넌트 활성화 여부를 확인합니다."}]

[{"index":"boolean EnableInHierarchy (ReadOnly) (HideFromInspector)","0":"계층 구조상에서 이 컴포넌트가 Enable 상태인지를 반환합니다. Enable이 true일지라도 엔티티의 Enable이 false라면 false를 반환합니다."}]

[{"index":"Entity Entity (ReadOnly)","0":"이 컴포넌트를 소유한 엔티티입니다."}]

# Methods

[{"index":"void AddAnimation(SkeletonAnimationClip animationClip)","0":"트랙에 애니메이션을 추가합니다. 1번 트랙은 사용할 수 없습니다. animationClip에는 트랙 번호, 애니메이션 이름, 기타 속성을 지정합니다. 애니메이션이 처음부터 다시 재생됩니다."}]

[{"index":"void AddEmptyAnimation(SkeletonAnimationClip animationClip)","0":"트랙에 빈 애니메이션을 추가합니다. 1번 트랙은 사용할 수 없습니다. animationClip에는 트랙 번호, 기타 속성을 설정합니다.애니메이션이 처음부터 다시 재생됩니다."}]

[{"index":"void ClearTrack(int32 trackIndex)","0":"트랙을 비웁니다. 1번 트랙은 사용할 수 없습니다."}]

[{"index":"SkeletonAnimationClip GetCurrentAnimation(int32 trackIndex) (ClientOnly)","0":"현재 재생 중인 애니메이션을 반환합니다."}]

[{"index":"void SetAnimation(SkeletonAnimationClip animationClip)","0":"트랙을 비우고 애니메이션을 추가합니다. animationClip에는 트랙 번호, 애니메이션 이름, 기타 속성을 지정합니다. 1번 트랙은 사용할 수 없습니다."}]

[{"index":"void SetAttachment(string slotName, string attachmentName)","0":"슬롯에 어태치먼트를 붙입니다. attachmentName이 nil이면 슬롯에서 어태치먼트를 제거합니다."}]

[{"index":"void SetEmptyAnimation(SkeletonAnimationClip animationClip)","0":"트랙을 비우고 빈 애니메이션을 추가합니다. animationClip에는 트랙 번호, 기타 속성을 지정합니다. 1번 트랙은 사용할 수 없습니다."}]

##### inherited from Component:

[{"index":"boolean IsClient()","0":"현재 실행 환경이 클라이언트인지 아닌지의 여부를 반환합니다."}]

[{"index":"boolean IsServer()","0":"현재 실행 환경이 서버인지 아닌지의 여부를 반환합니다."}]

# Events

[{"index":"OrderInLayerChangedEvent","0":"Component의 OrderInLayer가 변경되었을 때 발생하는 이벤트입니다."}]

[{"index":"SkeletonAnimationCompleteEvent","0":"스켈레톤 애니메이션의 재생이 완료되었을 때 발생하는 이벤트입니다. 반복 재생되는 경우, 재생이 완료될 때마다 발생합니다."}]

[{"index":"SkeletonAnimationEndEvent","0":"스켈레톤 애니메이션이 전환될 때, 종료되는 애니메이션에서 발생하는 이벤트입니다."}]

[{"index":"SkeletonAnimationStartEvent","0":"스켈레톤 애니메이션이 전환될 때, 새롭게 재생되는 애니메이션에서 발생하는 이벤트입니다."}]

[{"index":"SkeletonAnimationTimelineEvent","0":"스켈레톤 애니메이션이 재생 중일 때, 애니메이션 타임라인에 등록된 이벤트가 감지되면 발생하는 이벤트입니다."}]

[{"index":"SortingLayerChangedEvent","0":"컴포넌트의 SortingLayer가 변경되었을 때 발생하는 이벤트입니다."}]