동적으로 맵 생성, 파괴하기

# 학습 과정 소개

맵을 동적으로 생성, 파괴하는 방법을 알아봅시다.

##### 참고 가이드

  * [월드 인스턴스](/docs?postId=984%7B%22target%22:%22_blank%22%7D)
  * [인스턴스 맵 만들기](/docs/?postId=540%7B%22target%22:%22_blank%22%7D)
  * [DynamicMapService](/apiReference/Services/DynamicMapService%7B%22target%22:%22_blank%22%7D)
  * [DynamicMapResultCode](/apiReference/Enums/DynamicMapResultCode%7B%22target%22:%22_blank%22%7D)



# 원본 맵

원본 맵이란 크리에이터가 메이커에서 생성한 맵으로, 스크립트로 별도의 호출을 하지 않아도 월드 입장 시 자동으로 생성되는 맵을 의미합니다. 동적 맵 생성 시 원본 맵으로 사용할 수 있는 맵은 룸의 타입에 따라 달라집니다. 정적 룸에서는 정적 맵만 원본 맵으로 사용할 수 있고, 인스턴스 룸에서는 인스턴스 맵만 원본 맵으로 사용할 수 있습니다.

#### 원본 맵의 초기 상태

원본 맵의 초기 상태란 월드 입장 시 자동으로 생성된 가장 첫 시점의 맵 상태를 의미 합니다. 맵을 동적으로 생성하는 시점의 원본 맵 상태와 상관없이 동적 맵은 늘 항상 원본 맵의 초기 상태와 동일하게 생성됩니다.

# 동적 맵

동적 맵이란 월드 플레이 중 동적으로 생성되는 맵을 의미합니다. 예를 들어 크리에이터가 만드는 월드에 따라 한 맵에 특정 인원만 입장하는 동일한 형태의 맵이 필요할 수 있습니다. 이때 메이커에서 제작한 맵을 복사해 필요한 맵의 수만큼 미리 생성할 수도 있습니다. 그러나 맵의 개수가 늘어날수록 월드 서버에 부담이 되고, 월드 로딩 속도가 느려질 수 있습니다. 이때 DynamicMapService를 활용하면 필요한 때에만 생성할 수 있어 월드를 효율적으로 제작하는데 도움이 됩니다.

# 동적 맵 생성

맵을 동적으로 생성할 때는 `CreateDynamicMap()` 함수를 사용합니다. 이 함수로 맵을 생성하면 원본 맵에 속한 모든 컴포넌트의 `OnBeginPlay()`이 호출된 이후 결괏값으로 [DynamicMapResultCode](/apiReference/Enums/DynamicMapResultCode)를 반환합니다. [png](1757313592097179ef701cdbc4f06847445e16dbe93dd) 동적 맵을 사용하는 맵의 경우 `OnBeginPlay()`에서 실행에 시간이 오래 걸리는 작업이 수행되지 않도록 주의해야 합니다. 실행 시간이 오래 걸리는 경우 서버 성능에 악영향을 끼칠 수 있기 때문입니다. 또한 동적 맵을 생성할 때 `OnBeginPlay()`에서 동적 맵을 생성하지 않도록 유의해야 합니다. `OnBeginPlay()`에서 동적 맵을 생성할 경우 재귀 호출로 인해 동적 맵이 무한히 반복적으로 생성되어 오류가 발생할 수 있습니다.

[png](17573136093876287b8a065484a47ae8ebb646ea7a3f7)

> Tip. 동적 맵 생성 시 맵의 속성을 변경할 수 없습니다. 정적 룸의 정적 맵은 오직 정적 맵으로만 생성되고, 인스턴스 맵은 인스턴스 맵으로만 동적으로 생성됩니다.

#### 동적 맵 생성 시 유의 사항

`DynamicMapService`로 동적 맵을 생성할 때의 기준은 원본 맵의 초기 상태입니다. 메이커에서 제작한 맵의 모습이 아래와 같다면 동적으로 생성되는 맵은 늘 아래 상태로 생성됩니다. 월드에서 처음 생성된 원본 맵의 데이터가 변경되었다 하더라도 그 변경된 데이터는 새롭게 생성될 동적 맵에 반영되지 않고 초기 상태로 생성됩니다.

[{"index":"초기 상태","0":"[png](1756980791490973aeecd2496440faba844a80585270c)"},{"index":"플레이 중인 원본 맵","0":"[png](1756980818537570eca05f30a4376ba796d157114aeb7)"}]

동적 맵을 생성 하면 아래와 같이 초기 상태로 생성됩니다. [png](1756980791490973aeecd2496440faba844a80585270c)

# 동적 맵과 프로퍼티 타입

동적 맵을 생성할 때 경로를 사용하는 타입의 프로퍼티가 초기 상태에 있다면, 절대 경로 대신 상대 경로를 사용해야 합니다. 상대 경로를 사용해야 하는 프로퍼티 타입은 아래와 같습니다.

  * Entity, Component, EntityRef, ComponentRef



예를 들어 아래 그림과 같이 원본 맵에서 Portal A의 목적지는 Portal B, Portal B의 목적지는 Portal A로 지정했다고 생각해 봅시다. [png](1756980939504b01e26564c99479094d726cf011279f4)

동적 맵의 특성은 원본 맵의 초기 데이터를 그대로 복제하는 것이므로 동적 맵 생성 시 문제가 발생하게 됩니다.새로 생성된 동적 맵에서도 경로가 동일한 절대 경로로 유지되므로 새롭게 생성된 동적 맵에서 Portal A로 이동하면 DynamicMap1(원본 맵)의 Portal B로 이동하게 됩니다.

[png](175730580015799115a0e1bf842aa88bf70fb01616fe8)

이 문제는 `OnBeginPlay()`와 같은 특정 시점에서 참조 대상을 직접 지정해 대응할 수 있습니다. 예를 들어 `PortalComponent`를 Extend해 포털의 목적지를 상대 경로로 지정할 수 있습니다.
    
    
    @Component
    script PortalLinker extends Component
        property string PortalEntityPath = nil
    
        method void OnBeginPlay()
        local fullPath = self.Entity.CurrentMap.Path .. "/" .. self.PortalEntityPath
        local targetEntity = _EntityService:GetEntityByPath(fullPath)
    
        if targetEntity == nil or targetEntity.PortalComponent == nil then
            log_warning("Target entity is invalid. path : " .. fullPath)
        	return
        end
        self.PortalEntityRef = targetEntity
        end
    end
    

# 동적 맵 제거

동적 맵을 제거할 때는 `DestroyDynamicMap()` 함수를 사용합니다. 동적 맵에 유저가 없을 경우만 제거가 가능합니다. 동적 맵 제거 함수를 실행하면 [DynamicMapResultCode](/apiReference/Enums/DynamicMapResultCode)로 결괏값을 반환합니다.