msw-ai-tf/maplestory-worlds-creator-docs huggingface dataset:
TimerService

함수를 일정 시간 뒤에 호출하거나 반복적으로 호출할 수 있는 타이머 기능을 제공합니다.

# Methods

[{"index":"void ClearTimer(integer id)","0":"타이머를 소멸시킵니다."}]

[{"index":"integer SetTimer(IScriptable scriptable, func callback, float intervalSeconds, boolean isRepeat, float startDelaySeconds = 0)","0":"callback으로 전달한 함수를 특정 시점에 호출하도록 타이머를 예약합니다. scriptable은 예약할 액션의 소유자를 넘겨줍니다. 액션의 소유자로는 로직, 컴포넌트를 사용할 수 있습니다. isRepeat가 false인 경우 intervalSeconds 후에 최초 호출됩니다. isRepeat가 true인 경우 startDelaySeconds 후에 최초 호출되고, intervalSeconds 마다 반복 호출됩니다. 타이머 예약 성공 시 타이머의 아이디를 반환하고, 예약 실패 시 0을 반환합니다."}]

[{"index":"integer SetTimerOnce(func callback, float delaySeconds)","0":"callback으로 전달한 함수를 delaySeconds 후에 호출합니다. 타이머 예약 성공 시 타이머의 아이디를 반환하고, 예약 실패 시 0을 반환합니다."}]

[{"index":"integer SetTimerRepeat(func callback, float intervalSeconds, float startDelaySeconds = 0)","0":"callback으로 전달한 함수를 startDelaySeconds 후에 intervalSeconds마다 한 번씩 반복해서 호출합니다. 타이머 예약 성공 시 타이머의 아이디를 반환하고, 예약 실패 시 0을 반환합니다."}]

##### inherited from Service:

[{"index":"EventHandlerBase ConnectEvent(string key, IScriptFunction eventHandler)","0":"이벤트를 연결합니다. 이 서비스에서 타입의 이름이 key인 이벤트가 발생하면, 핸들러로 통지받습니다. 핸들러는 event 매개 변수를 전달받습니다."}]

[{"index":"EventHandlerBase ConnectEvent(Type eventType, IScriptFunction eventHandler)","0":"이벤트를 연결합니다. 이 서비스에서 타입이 eventType인 이벤트가 발생하면, 핸들러로 통지받습니다. 핸들러는 event 매개 변수를 전달받습니다."}]

[{"index":"boolean DisconnectEvent(string key, EventHandlerBase eventHandler)","0":"타입의 이름이 key인 이벤트와 핸들러와의 이벤트 연결을 끊습니다."}]

[{"index":"boolean DisconnectEvent(Type eventType, EventHandlerBase eventHandler)","0":"타입이 eventType인 이벤트와 핸들러와의 연결을 끊습니다."}]

[{"index":"void SendEvent(EventType sendEvent)","0":"이벤트를 발생시킵니다."}]

# Examples

다음은 Entity를 회전시켜 시계의 초침을 구현하는 예제입니다. Entity를 회전시키는 함수를 1초마다 반복 실행하도록 설정합니다.
    
    
    @Component
    script ZAxisRotator extends Component
        property integer TimerId = 0
    
        @ExecSpace("ServerOnly")
        method void OnBeginPlay()
        local repeatFunc = function()
        	local transform = self.Entity.TransformComponent
        	local zRot = transform.ZRotation
    
        	transform.ZRotation = zRot - (360.0 / 60.0)
        end
    
        self.TimerId = _TimerService:SetTimerRepeat(repeatFunc,1.0)
        if self.TimerId == 0 then
        	log_error("Timer reservation failed.")
        end
        end
    
        @ExecSpace("ServerOnly")
        method void OnEndPlay()
        if self.TimerId > 0 then
        	_TimerService:ClearTimer(self.TimerId)
        end
        end
    end
    

# SeeAlso

  * TransformComponent
  * [액션을 예약하고 실행하는 TimerService](/docs?postId=47)
SpotTypeOverlayLightInfo

맵에 스폰할 Spot 타입의 광원 정보입니다.

# Properties

[{"index":"Color Color","0":"광원의 색상입니다."}]

[{"index":"float FalloffIntensity","0":"광원이 사라지는 곡선의 부드러움을 조절합니다. 값이 클수록 광원의 경계선이 흐릿하고 부드러워 보입니다. 값이 작을수록 광원의 경계선이 날카롭고 또렷하게 보입니다."}]

[{"index":"float InnerRadius","0":"광원이 Spot 타입일 때 최대 밝기를 갖는 내부 광원 영역의 반경입니다. OuterRadius보다 큰 값을 가질 수 없습니다."}]

[{"index":"Entity Instigator","0":"광원이 생성될 맵에 소속된 엔티티입니다."}]

[{"index":"float Intensity","0":"광원의 강도입니다."}]

[{"index":"float Lifetime","0":"광원이 표시될 시간입니다. 적혀있는 시간을 경과하면 생성되었던 광원이 자동으로 사라집니다. 단, 0 이하의 값을 입력할 경우에는 아무리 시간이 지나도 사라지지 않습니다."}]

[{"index":"int32 LightOrder","0":"광원이 라이트 텍스처에 렌더링되는 순서를 결정합니다. 낮은 수의 광원이 먼저 렌더링되고, 높은 수의 광원이 그 위에 렌더링됩니다. OverlapOperation이 AlphaBlend일 때 동작합니다. 예외적으로 Global 타입 광원은 LightOrder를 갖지 않습니다."}]

[{"index":"float OuterRadius","0":"Spot 타입 광원의 크기를 결정하는 외부 반경입니다. InnerRadius의 끝에서부터 빛이 감쇠되기 시작하여 이 반지름에 도달하면 빛의 강도가 0%가 됩니다."}]

[{"index":"OverlayLightOverlapOperation OverlapOperation","0":"광원의 연산 방식입니다. Global 타입 광원은 OverlapOperation을 갖지 않습니다."}]

[{"index":"float SpotInnerAngle","0":"Spot 타입 광원의 내부 각도입니다. 각도가 클수록 간격이 넓어집니다. 내부 각도에 있는 모든 픽셀은 빛의 강도가 100%로 적용됩니다. SpotOuterAngle보다 큰 값을 가질 수 없습니다."}]

[{"index":"float SpotOuterAngle","0":"Spot 타입 광원의 외부 각도입니다. 값이 클수록 각도가 넓어집니다. SpotInnerAngle의 끝에서부터 빛이 감쇠되기 시작하여 SpotOuterAngle에 도달하면 빛의 강도는 0%가 됩니다."}]

[{"index":"Vector3 WorldPosition","0":"광원이 위치할 월드 공간 상의 좌표입니다."}]

[{"index":"float WorldZRotation","0":"광원에 적용될 월드 공간 상의 Z축 기준 회전값입니다."}]

# Constructors

[{"index":"SpotTypeOverlayLightInfo(Entity instigator)","0":"지정한 값으로 SpotTypeOverlayLightInfo를 초기화합니다."}]

[{"index":"SpotTypeOverlayLightInfo(Entity instigator, float lifetime, Vector3 worldPosition, float worldZRotation, Color color, float intensity, OverlayLightOverlapOperation overlapOperation, int32 lightOrder, float innerRadius, float outerRadius, float spotInnerAngle, float spotOuterAngle, float falloffIntensity)","0":"지정한 값으로 SpotTypeOverlayLightInfo를 초기화합니다."}]
MapComponent

맵을 관리하고, 맵의 고유 속성들을 변경할 수 있습니다.

# Properties

[{"index":"float AirAccelerationXFactor","0":"맵 내에 RigidbodyComponent를 가진 엔티티의 공중에서의 속도를 보정합니다. 값이 증가할수록 공중에서의 속도가 빨라집니다."}]

[{"index":"float AirDecelerationXFactor","0":"맵 내에 RigidbodyComponent를 가진 엔티티가 공중에 있을 때, 입력이 없으면 X축 이동 속도가 얼마나 빠르게 멈추는지를 보정합니다."}]

[{"index":"float FallSpeedMaxXFactor","0":"맵 내에 RigidbodyComponent를 가진 엔티티들의 공중에서의 X축 최대 속도 제한값을 보정합니다."}]

[{"index":"float FallSpeedMaxYFactor","0":"맵 내에 RigidbodyComponent를 가진 엔티티의 공중에서의 Y축 최대 속도 제한값을 보정합니다."}]

[{"index":"float Gravity","0":"맵 내에 RigidbodyComponent를 가진 엔티티의 중력값을 보정합니다."}]

[{"index":"boolean IsDynamicMap (ReadOnly) (HideFromInspector)","0":"동적으로 생성된 맵인지를 나타냅니다."}]

[{"index":"boolean IsInstanceMap","0":"인스턴스 맵으로 사용할지 여부를 설정합니다."}]

[{"index":"Vector2 LeftBottom (Sync)","0":"맵 영역의 좌하단 값입니다."}]

[{"index":"Vector2 RightTop (Sync)","0":"맵 영역의 우상단 값입니다."}]

[{"index":"TileMapMode TileMapMode (ReadOnly)","0":"맵의 타일맵 모드를 확인합니다."}]

[{"index":"boolean UseCustomBound (Sync)","0":"맵 영역을 직접 정의해 사용할지 여부를 나타냅니다. LeftBottom, RightTop 프로퍼티를 사용해 정의할 수 있습니다. false일 시 맵의 형태를 기반으로 자동 생성한 영역이 맵 영역으로 사용됩니다. TileMapMode가 MapleTile일 때에만 작동합니다."}]

[{"index":"float WalkAccelerationFactor","0":"맵 내에 RigidbodyComponent를 가진 엔티티의 이동 속도의 Factor를 설정합니다. 최대 속도는 RigidbodyComponent의 WalkSpeed를 넘을 수 없으며, 최대 속도 도달까지의 속도를 제어합니다."}]

[{"index":"float WalkDrag","0":"맵 내에 RigidbodyComponent를 가진 Entity들의 타일 마찰력을 보정합니다. 값이 작을수록 타일에서 잘 미끄러집니다."}]

##### 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":"Vector2, Vector2 GetBound()","0":"LeftBottom, RightTop으로 구성된 맵 영역을 가져옵니다."}]

##### inherited from Component:

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

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

플레이어끼리 소통을 할 수 있는 채팅 기능을 지원해주는 컴포넌트입니다.

# Properties

[{"index":"float ChatEmotionDuration","0":"아바타 감정 표현 지속 시간을 설정합니다."}]

[{"index":"boolean EnableVoiceChat (MakerOnly)","0":"보이스 채팅 버튼의 표시 및 사용 여부를 설정합니다."}]

[{"index":"boolean Expand","0":"채팅창을 펼칠 수 있는 기능입니다."}]

[{"index":"boolean HideWorldChatButton (MakerOnly)","0":"월드 채팅 버튼을 숨기는 기능입니다."}]

[{"index":"boolean MessageAlignBottom (MakerOnly)","0":"월드 채팅 메세지를 하단을 기준으로 정렬하는 기능입니다."}]

[{"index":"boolean UseChatBalloon","0":"플레이어의 채팅 메세지를 말풍선으로 표현할 수 있는 기능입니다."}]

[{"index":"boolean UseChatEmotion","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

##### inherited from Component:

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

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

# Events

[{"index":"ChatEvent","0":"대화가 입력되었을 때 발생하는 이벤트입니다."}]

# Examples

`EmotionalType`의 텍스트 길이만큼 `ChatEmotionDuration`과 `ChatBalloonComponent`의 `ShowDuration`을 변경하는 예제입니다. `ChatEvent`를 통해 EmotionalType이 메시지에 포함되었는지 확인합니다.
    
    
    @Component
    script ChatEmotionActivator extends Component
        @EventSender("Self")
        handler HandleChatEvent(ChatEvent event)
        --------------- Native Event Sender Info ----------------
        -- Sender: ChatComponent
        -- Space: Client
        ---------------------------------------------------------
    
        -- Parameters
        local Message = event.Message
        local SenderName = event.SenderName
        local UserId = event.UserId
        ---------------------------------------------------------
    
        local localId = _UserService.LocalPlayer.OwnerId
        if string.compare(localId, UserId) == false then
        	return
        end
    
        local lowerMessage = string.lower(Message)
    
        local findEmotion = EmotionalType.Invalid
        local len = 23
        for i = 1, len do
        	local key = string.lower(tostring(EmotionalType.CastFrom(i)))
    
        	if lowerMessage:find(key, 1, true ) then
        		log("onChat Find : ", key)
        		findEmotion = EmotionalType.CastFrom(i)
        	end
        end
    
        if findEmotion == EmotionalType.Invalid then
        	return
        end
    
        local chatComponent = self.Entity.ChatComponent
        local duration = #tostring(findEmotion)
        if chatComponent then
        	chatComponent.UseChatEmotion = true
        	chatComponent.ChatEmotionDuration = duration
        end
    
        local balloonComponent = _UserService.LocalPlayer.ChatBalloonComponent
        if balloonComponent then
        	balloonComponent.ShowDuration = duration
        end
    
        log("OnChatEvent ", Message, " duration :", duration)
        end
    end
    

# SeeAlso

  * ChatBalloonComponent
  * EmotionalType
  * ChatEvent
  * UserService
UIBasicParticleComponent

UI에 사용하는 기본 파티클의 설정 및 제어 기능을 제공합니다.

# Properties

[{"index":"UIBasicParticleType ParticleType","0":"생성할 파티클의 타입을 설정합니다."}]

##### inherited from UIBaseParticleComponent:

[{"index":"boolean AutoRandomSeed","0":"파티클 입자 방출이 시작될 때마다 랜덤 시드를 새로 생성할지 여부를 설정합니다."}]

[{"index":"Color Color","0":"렌더링될 파티클의 색상을 보정합니다."}]

[{"index":"boolean IsEmitting (ReadOnly) (HideFromInspector)","0":"새 파티클을 방출하고 있는지를 나타냅니다."}]

[{"index":"Vector2 LocalScale","0":"파티클의 크기입니다."}]

[{"index":"boolean Loop","0":"파티클의 반복 재생 여부를 설정합니다."}]

[{"index":"float ParticleCount","0":"파티클 입자 개수를 설정합니다."}]

[{"index":"float ParticleLifeTime","0":"파티클 입자의 지속시간을 설정합니다."}]

[{"index":"float ParticleSize","0":"파티클 입자의 크기를 설정합니다."}]

[{"index":"float ParticleSpeed","0":"파티클 입자의 속도를 설정합니다."}]

[{"index":"boolean PlayOnEnable","0":"파티클 컴포넌트가 Enable일 때, 파티클을 재생할지 여부를 설정합니다."}]

[{"index":"float PlaySpeed","0":"파티클 재생 속도를 설정합니다."}]

[{"index":"boolean Prewarm","0":"값이 true일 경우 파티클이 처음 재생될 때 이미 재생되고 있었던 것과 같은 상태로 시작합니다."}]

[{"index":"integer RandomSeed","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

##### inherited from UIBaseParticleComponent:

[{"index":"void Play() (ClientOnly)","0":"파티클을 재생합니다."}]

[{"index":"void Stop() (ClientOnly)","0":"파티클 재생을 멈춥니다."}]

##### inherited from Component:

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

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

# Events

[{"index":"ParticleEmitEndEvent","0":"파티클의 방출이 종료되었을 때 BaseParticleComponent에서 발생하는 이벤트입니다."}]

[{"index":"ParticleEmitStartEvent","0":"파티클 입자 방출이 시작될 때 발생하는 이벤트입니다."}]

[{"index":"ParticleLoopEvent","0":"Loop 프로퍼티가 활성화 된 경우, 파티클의 방출 주기가 돌아와서 방출을 반복할 때 발생하는 이벤트입니다."}]
데이터 스토리지 관리 방법 알아보기

이 게시글은 기존 정보에 기반해 크리에이터에게 유용하도록 AI가 재구성한 내용입니다.

# 데이터 스토리지 관리 방법 알아보기

> 데이터 스토리지는 현대의 다양한 애플리케이션에서 필수적인 요소로, 데이터를 효율적으로 저장하고 관리하는 방법은 개발자와 크리에이터에게 매우 중요합니다. 이 아티클에서는 데이터 스토리지의 관리 방법과 이를 효과적으로 활용하는 법을 알아봅니다.

## 데이터 스토리지 서비스 사용법

데이터 스토리지는 주로 `DataStorageService`를 통해 관리됩니다. 이 서비스는 다양한 데이터 스토리지에 접근할 수 있는 함수를 제공하여 데이터를 저장, 삭제, 불러오기, 조회하는 등 여러 작업을 수행할 수 있습니다. 예를 들어, `GlobalDataStorage`, `UserDataStorage`, `CreatorDataStorage`, `SortableDataStorage` 등의 함수를 활용하여 데이터를 효율적으로 관리할 수 있습니다. 각 데이터 스토리지의 특성을 이해하고 적절한 함수를 선택하는 것이 중요합니다.

## 데이터 저장하기

데이터를 저장할 때는 데이터 스토리지의 타입을 명확히 구분해야 합니다. 이는 데이터 스토리지의 타입마다 저장할 수 있는 값의 타입이 다르기 때문입니다. 예를 들어, `Global`, `User`, `Creator` 데이터 스토리지는 문자열로 데이터를 저장할 수 있으며, `Sortable` 데이터 스토리지는 정수로만 저장할 수 있습니다. 따라서 데이터 저장 시에는 저장할 값의 타입과 스토리지의 타입을 일치시키는 것이 중요합니다.

## 데이터 저장 시 고려할 사항

데이터 스토리지 사용량에는 제한이 있으므로, 데이터를 자주 저장하면 `크레딧`이 부족해질 수 있습니다. 따라서 변경된 값만 저장하여 크레딧 소비를 줄이는 것이 좋습니다. 데이터를 저장하는 주요 시나리오로는 사용자 연결 해제 시, 정기적인 간격으로, 예외 상황 발생 시 등이 있습니다. 각 시나리오에 맞게 저장 전략을 수립하는 것이 중요합니다.

## 데이터 불러오기

저장된 데이터를 불러올 때는 `GetGlobalDataStorage`, `GetUserDataStorage`, `GetCreatorStorage`, `GetSortableDataStorage` 등의 함수를 사용합니다. 이러한 데이터 불러오기 함수는 서버 전용으로 설계되었으므로, 서버 공간에서 데이터를 로드하는 것이 권장됩니다.

## 에러 코드 처리

데이터 로드가 실패할 수 있는 다양한 상황을 대비하여 에러 코드를 처리하는 기능을 구현하는 것이 중요합니다. 예를 들어, 요청 시간이 초과되거나 호출 한도가 초과되는 경우를 처리할 수 있는 에러 코드 핸들링을 마련하는 것이 필요합니다.

## 결론 및 추가 자료

데이터 스토리지 관리 방법은 애플리케이션의 효율성과 안정성을 높이는 데 중요한 역할을 합니다. 데이터를 효율적으로 저장하고 불러오는 방법을 이해하고 활용하는 것은 크리에이터에게 필수적입니다.

추가로 학습할 수 있는 자료는 다음 링크를 참고하세요:

  * 
  *
SpriteRendererComponent의 이미지 크기 알아보기

이 게시글은 기존 정보에 기반해 크리에이터에게 유용하도록 AI가 재구성한 내용입니다.

# SpriteRendererComponent의 이미지 크기 알아보기

> SpriteRendererComponent를 활용하여 이미지의 크기를 확인하는 방법을 알아보고, 실제로 리소스를 로딩하여 스프라이트와 애니메이션의 크기를 측정하는 방법을 설명합니다.

## SpriteRendererComponent와 이미지 크기의 중요성

SpriteRendererComponent는 메이플스토리 월드에서 이미지를 표현하기 위한 중요한 요소입니다. 이 컴포넌트를 통해 스프라이트의 크기, 위치, 회전 등을 조정할 수 있습니다. 이미지의 크기를 정확히 파악하는 것은 UI 디자인, 게임 그래픽 최적화, 충돌 감지 등의 다양한 분야에서 필수적입니다.

## 스프라이트 및 애니메이션 리소스 로딩

스프라이트나 애니메이션 리소스를 로딩하기 위해 `_ResourceService:LoadSpriteAndWait`와 `_ResourceService:LoadAnimationClipAndWait` 메서드를 사용합니다. 리소스를 로딩할 때는 `IsLoadComplete` 플래그를 통해 로딩 상태를 확인하는 것이 중요합니다.

## 스프라이트 크기 확인 방법

스프라이트 리소스를 로딩한 후, 그 크기를 확인하려면 다음과 같은 방법을 사용합니다:
    
    
    Method:
    void OnBeginPlay()
    {
        local spriteRenderer = self.Entity.SpriteRendererComponent
        local spriteRUID = spriteRenderer.SpriteRUID
    
        local sprite = _ResourceService:LoadSpriteAndWait(spriteRUID)
    
        if sprite.IsLoadComplete then
            log("Sprite Height: "..sprite.Height..", Width: "..sprite.Width)
        else
            log("Sprite is not yet loaded.")
        end
    }
    

위 코드에서는 `Height`와 `Width` 프로퍼티를 사용하여 스프라이트의 크기를 출력합니다.

## 애니메이션 프레임 크기 분석

애니메이션 리소스를 로딩하고 각 프레임의 크기를 분석하는 방법은 다음과 같습니다:
    
    
    local spriteRenderer = self.Entity.SpriteRendererComponent
    local spriteRUID = spriteRenderer.SpriteRUID
    
    local animationClip = _ResourceService:LoadAnimationClipAndWait(spriteRUID)
    
    if animationClip.IsLoadComplete then
        local frames = animationClip.Frames
        for i, frame in ipairs(frames) do
            log("Frame index: "..i.. " Sprite Height: "..frame.FrameSprite.Height..", Width: "..frame.FrameSprite.Width.." OffSetX: "..frame.Offset.x.." OffSetY"..frame.Offset.y)
        end
    else
        log("AnimationClip is not yet loaded.")
    end
    

각 프레임의 크기와 오프셋을 출력하여 이미지 크기를 기준으로 활용할 수 있습니다.

## 잠재적 문제 및 해결책

리소스가 로드되지 않는 경우, `IsLoadComplete` 플래그를 사용하여 로딩 상태를 반복적으로 확인해야 합니다. 또한, 애니메이션의 경우 프레임마다 크기가 다를 수 있으므로 특정 프레임을 기준으로 크기를 설정해야 합니다.

## 결론 및 추가 자료

SpriteRendererComponent를 활용하여 이미지의 크기를 파악하는 방법을 설명했습니다. 이 정보를 기반으로 스프라이트와 애니메이션의 크기를 정확히 측정하고 응용할 수 있습니다. 추가적으로 관련된 자료는 아래 링크를 통해 확인할 수 있습니다:

  * 
  *
AttachedSpotTypeOverlayLightInfo

엔티티의 자식으로 스폰될 Spot 타입의 광원 정보입니다.

# Properties

[{"index":"Color Color","0":"광원의 색상입니다."}]

[{"index":"float FalloffIntensity","0":"광원이 사라지는 곡선의 부드러움을 조절합니다. 값이 클수록 광원의 경계선이 흐릿하고 부드러워 보입니다. 값이 작을수록 광원의 경계선이 날카롭고 또렷하게 보입니다."}]

[{"index":"float InnerRadius","0":"광원이 Spot 타입일 때 최대 밝기를 갖는 내부 광원 영역의 반경입니다. OuterRadius보다 큰 값을 가질 수 없습니다."}]

[{"index":"float Intensity","0":"광원의 강도입니다."}]

[{"index":"float Lifetime","0":"광원이 표시될 시간입니다. 적혀있는 시간을 경과하면 생성되었던 광원이 자동으로 사라집니다. 단, 0 이하의 값을 입력할 경우에는 아무리 시간이 지나도 사라지지 않습니다."}]

[{"index":"int32 LightOrder","0":"광원이 라이트 텍스처에 렌더링되는 순서를 결정합니다. 낮은 수의 광원이 먼저 렌더링되고, 높은 수의 광원이 그 위에 렌더링됩니다. OverlapOperation이 AlphaBlend일 때 동작합니다. 예외적으로 Global 타입 광원은 LightOrder를 갖지 않습니다."}]

[{"index":"Vector3 LocalPosition","0":"광원이 위치할 부모 엔티티 공간 상의 좌표입니다."}]

[{"index":"float LocalZRotation","0":"광원에 적용될 부모 엔티티 공간 상의 Z축 기준 회전값입니다."}]

[{"index":"float OuterRadius","0":"광원의 크기를 결정하는 외부 반경입니다. InnerRadius의 끝에서부터 빛이 감쇠되기 시작하여 이 반지름에 도달하면 빛의 강도가 0%가 됩니다."}]

[{"index":"OverlayLightOverlapOperation OverlapOperation","0":"광원의 연산 방식입니다. Global 타입 광원은 OverlapOperation을 갖지 않습니다."}]

[{"index":"Entity ParentEntity","0":"생성된 광원이 추가될 엔티티입니다."}]

[{"index":"float SpotInnerAngle","0":"Spot 타입 광원의 내부 각도입니다. 각도가 클수록 간격이 넓어집니다. 내부 각도에 있는 모든 픽셀은 빛의 강도가 100%로 적용됩니다. SpotOuterAngle보다 큰 값을 가질 수 없습니다."}]

[{"index":"float SpotOuterAngle","0":"Spot 타입 광원의 외부 각도입니다. 값이 클수록 각도가 넓어집니다. SpotInnerAngle의 끝에서부터 빛이 감쇠되기 시작하여 SpotOuterAngle에 도달하면 빛의 강도는 0%가 됩니다."}]

# Constructors

[{"index":"AttachedSpotTypeOverlayLightInfo(Entity parentEntity)","0":"지정한 값으로 AttachedSpotTypeOverlayLightInfo를 초기화합니다."}]

[{"index":"AttachedSpotTypeOverlayLightInfo(Entity parentEntity, float lifetime, Vector3 localPosition, float localZRotation, Color color, float intensity, OverlayLightOverlapOperation overlapOperation, int32 lightOrder, float innerRadius, float outerRadius, float spotInnerAngle, float spotOuterAngle, float falloffIntensity)","0":"지정한 값으로 AttachedSpotTypeOverlayLightInfo를 초기화합니다."}]
ResourceType

리소스 파일 헤더 포맷을 나타냅니다.

# Members

[{"이름":"nan","값":"0","설명":"미정의 상태입니다. 내용물을 알 수 없습니다."},{"이름":"Sprite","값":"1","설명":"Texture와 피봇 등의 메타 정보를 담은 2D에 특화된 그래픽 리소스 파일 타입입니다."},{"이름":"Atlas","값":"2","설명":"현재는 사용되지 않습니다."},{"이름":"AudioClip","값":"3","설명":"음원 정보를 담은 AudioClip 리소스 파일 타입입니다. OGG 파일 형식을 사용합니다."},{"이름":"Background","값":"4","설명":"MapleStory Worlds의 배경 메타 정보를 담은 리소스 파일 타입입니다. PresetList에서 사용합니다."},{"이름":"TileSet","값":"5","설명":"MapleStory Worlds의 타일셋 메타 정보를 담은 타일셋 리소스 파일 타입입니다. PresetList에서 사용합니다."},{"이름":"AnimationClip","값":"6","설명":"프레임 단위의 2D 그래픽스 애니메이션 메타 정보를 담은 파일 타입입니다. AnimationClip에서 사용합니다."},{"이름":"MapleMapObject","값":"7","설명":"MapleStory Worlds의 오브젝트의 메타 정보를 담은 리소스 파일 타입입니다."},{"이름":"MapleRope","값":"8","설명":"MapleStory Worlds의 사다리와 로프 메타 정보를 담은 리소스 파일 타입입니다."},{"이름":"Item","값":"9","설명":"MapleStory Worlds의 아이템 메타 정보를 담은 리소스 파일 타입입니다."},{"이름":"Monster","값":"10","설명":"MapleStory Worlds의 몬스터 메타 정보를 담은 리소스 파일 타입입니다."},{"이름":"Npc","값":"11","설명":"MapleStory Worlds의 NPC 메타 정보를 담은 리소스 파일 타입입니다. NPC의 기본 동작, 동작별 AnimationClip 테이블 확인이 가능합니다."},{"이름":"Trap","값":"12","설명":"MapleStory Worlds의 함정 메타 정보를 담은 리소스 파일 타입입니다."},{"이름":"ChatBalloon","값":"13","설명":"MapleStory Worlds의 말풍선 메타 정보를 담은 리소스 파일 타입입니다."},{"이름":"NameTag","값":"14","설명":"MapleStory Worlds의 이름표 메타 정보를 담은 리소스 파일 타입입니다."},{"이름":"AvatarItem","값":"15","설명":"아바타 아이템 메타 정보를 담은 리소스 파일 타입입니다."},{"이름":"DamageSkin","값":"16","설명":"MapleStory Worlds의 대미지 스킨 메타 정보를 담은 리소스 파일 타입입니다."},{"이름":"MapleMap","값":"17","설명":"MapleStory Worlds의 맵 메타 정보를 담은 리소스 파일 타입입니다. MapleStory Map을 불러올 때 사용합니다."},{"이름":"UserAtlas","값":"18","설명":"크리에이터가 생성한 아틀라스의 메타 정보를 담은 리소스 파일 타입입니다."},{"이름":"Skeleton","값":"19","설명":"Spine 스켈레톤 리소스 메타 정보를 담은 리소스 파일 타입입니다."},{"이름":"CustomFont","값":"21","설명":"폰트 메타 정보를 담은 리소스 파일 타입입니다."}]

# Methods

[{"index":"ResourceType CastFrom(number value) (Static)","0":"숫자를 해당 타입으로 변환합니다."}]

[{"index":"ResourceType CastFrom(string value) (Static)","0":"문자열을 해당 타입으로 변환합니다."}]
AI ToolKit

메이플스토리 월드에서 제공하는 AI ToolKit 기능을 활성화하면 간단한 명령을 통해 월드를 제작할 수 있습니다. AI ToolKit을 사용하기 위해서는 사전 준비 단계와 별도의 AI 에이전트 구독이 필요합니다.

## 로컬 워크스페이스

AI ToolKit을 사용하기 위해서는 반드시 로컬 워크스페이스와 ExtendedScriptFormat을 사용해야 합니다. 로컬 워크스페이스에 대한 내용은 [LocalWorkspace](docs/?postId=1165) 가이드를 참고하세요. AI ToolKit은 AI ToolKit Settings의 로컬 워크스페이스, MCP 서버, AI 스킬 셋 탭의 설정을 모두 마쳐야 정상적으로 동작합니다.

  1. 만들기 - AI와 함께 월드 만들기 혹은 만들기 - 새로 만들기 - AI 스타터 템플릿을 선택해 월드를 새로 만듭니다.

[{"index":"만들기 버튼","0":"[png](1779353818776a4e26c18fe634009b6bd3a55217be287)"},{"index":"AI 스타터 템플릿","0":"[png](1779360155464759176e069e043bca3fa9e92b8508d45)"}]

  2. AI 설정하기 버튼을 누르거나, AI Lab - AI ToolKit Settings을 선택합니다.

[{"index":"팝업 버튼","0":"[png](1779360182729fc2acf1c4c074f99bc8c4ed9bdb2b227)"},{"index":"AI Lab 메뉴","0":"[png](17793602054810da48bfe35224bd78d283600f24f95bb)"},{"index":"바로가기 버튼","0":"[png](1779777266102597ce420134c4be0bd81ea5c1685c9a6)"}]

  3. 로컬 워크스페이스 - 로컬 워크스페이스 사용을 선택하고, 월드를 저장할 위치를 선택합니다.

  4. ExtendedScriptFormat을 활성화합니다. [png](1779360408062d9f1bdac22ee407bbd9aec2d2b9127a6)




## MCP 서버

MCP 연결 방법과 API Key 발급 방법은 [MSW MCP](docs/?postId=1368)를 참고합니다.

[png](17793538693200c3c7c3841554cd7bc055b4ba8016b3e)

  1. MCP 서버 탭에서 MSW Maker MCP 사용을 활성화합니다.
  2. 크리에이터가 사용할 AI 에이전트의 [연결] 버튼을 누릅니다.



## AI 스킬 셋

[AI 스킬 셋](/docs?postId=1373%7B%22target%22:%22_blank%22%7D) 탭에서 월드 파일 작성·수정에 사용할 AI 도구를 선택하고 연결합니다. 원하는 항목의 [연결] 버튼을 누르면 자동으로 설치됩니다. 자세한 내용은 위 가이드를 참고하세요.

[png](1779353961022eea460b339094bacb87673bcea67a3cb)

> Tip. AI 에이전트의 업데이트가 필요한 경우 업데이트 버튼이 활성화됩니다. 

## AI 시작하기

AI 시작하기 탭에서 연결한 AI 에이전트를 열 수 있습니다. [png](17793539806115b82f93f24274604b3e41e788e7cf514)

> Tip Claude Code CLI는 연결이 완료되면 메이커 오른쪽 상단의 바로가기 버튼을 통해 쉽게 시작할 수 있습니다. [png](177935399435730396d6c7abf497fb1ff7cb5f9451248)
ItemService

아이템 관련 기능을 제공합니다.

# Methods

[{"index":"void ChangeOwner(Item item, InventoryComponent owner) (ServerOnly)","0":"아이템의 소유권을 해당 InventoryComponent로 이전합니다."}]

[{"index":"void ChangeOwner(string itemGUID, InventoryComponent owner) (ServerOnly)","0":"아이템의 소유권을 해당 InventoryComponent로 이전합니다."}]

[{"index":"Item CreateItem(Type itemType, string itemDataTableName, InventoryComponent ownerInventoryComponent = nil) (ServerOnly)","0":"해당하는 itemType의 아이템을 생성합니다. tableDataName을 입력해 미리 준비된 DataSets\/DataSet\/UserItemDataSet의 데이터 중 Name과 일치하는 데이터를 불러올 수 있습니다. UserItemDataSet에는 Name, IconRUID, Description 열을 기본으로 작성해야 하며, 편의에 따라 열을 추가해 사용할 수 있습니다."}]

[{"index":"Item GetItemByGUID(string guid) (ServerOnly)","0":"아이템 GUID를 사용하여 서버에 캐시된 아이템을 가져옵니다."}]

[{"index":"table GetMODItemsByOwner(InventoryComponent owner)","0":"InventoryComponent가 소유한 아이템을 가져옵니다."}]

[{"index":"void RemoveItem(Item item) (ServerOnly)","0":"아이템을 삭제합니다."}]

##### inherited from Service:

[{"index":"EventHandlerBase ConnectEvent(string key, IScriptFunction eventHandler)","0":"이벤트를 연결합니다. 이 서비스에서 타입의 이름이 key인 이벤트가 발생하면, 핸들러로 통지받습니다. 핸들러는 event 매개 변수를 전달받습니다."}]

[{"index":"EventHandlerBase ConnectEvent(Type eventType, IScriptFunction eventHandler)","0":"이벤트를 연결합니다. 이 서비스에서 타입이 eventType인 이벤트가 발생하면, 핸들러로 통지받습니다. 핸들러는 event 매개 변수를 전달받습니다."}]

[{"index":"boolean DisconnectEvent(string key, EventHandlerBase eventHandler)","0":"타입의 이름이 key인 이벤트와 핸들러와의 이벤트 연결을 끊습니다."}]

[{"index":"boolean DisconnectEvent(Type eventType, EventHandlerBase eventHandler)","0":"타입이 eventType인 이벤트와 핸들러와의 연결을 끊습니다."}]

[{"index":"void SendEvent(EventType sendEvent)","0":"이벤트를 발생시킵니다."}]

# Examples

플레이어의 인벤토리에 아이템을 추가하고, 개수를 변경하고, 제거하는 예제입니다.

이름이 `Get Item`인 오브젝트에 충돌하면 아이템을 3개 획득합니다.  
이름이 `Give Item`인 오브젝트에 충돌하면 아이템 개수가 1 감소합니다. 아이템 개수가 0이 되면 제거합니다.  
이름이 `Trash Can`인 오브젝트에 충돌하면 아이템을 제거합니다.
    
    
    @Component
    script InventoryTriggerHandler extends Component
        @EventSender("Self")
        handler HandleTriggerEnterEvent(TriggerEnterEvent event)
        -- Parameters
        local TriggerBodyEntity = event.TriggerBodyEntity
        --------------------------------------------------------
        if self:IsClient() then
        	return
        end
    
        local inventory = self.Entity.InventoryComponent
        local items = inventory:GetItemList()
    
        if TriggerBodyEntity.Name == "Get Item" then
        	local newItem = _ItemService:CreateItem(TestItem, "Test Item", inventory)
        	newItem.ItemCount = 3
        elseif TriggerBodyEntity.Name == "Give Item" then
        	if #items > 0 then
        		items[1].ItemCount = items[1].ItemCount - 1
        		if items[1].ItemCount == 0 then
        			_ItemService:RemoveItem(items[1])
        		end
        	end
        elseif TriggerBodyEntity.Name == "Trash Can" then
        	if #items > 0 then
        		_ItemService:RemoveItem(items[1])
        	end
        end
        end
    end
    

# SeeAlso

  * InventoryComponent
  * TriggerEnterEvent