> For the complete documentation index, see [llms.txt](/llms.txt)

# GS2-Limit SDK for Game Engine API 레퍼런스

게임 엔진용 GS2-Limit SDK의 모델 사양과 API 레퍼런스



## 모델

### EzCounter

사용 횟수 제한의 현재 값<br>

각 사용자의 사용 횟수 제한 모델에 속한 특정 카운터의 현재 사용 횟수를 추적합니다. 하나의 사용 횟수 제한 모델 아래에 여러 카운터를 만들 수 있습니다(예: 1회 한정 보상을 위해 퀘스트마다 하나의 카운터). 카운트 값은 카운트업 조작 시 지정되는 최대값과 비교되며, 사용 횟수 제한 모델의 리셋 일정에 따라 자동으로 0으로 리셋됩니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| counterId | string |  | ※ |  |  ~ 1024자 | 카운터 GRN<br>※ 서버가 자동으로 설정 |
| limitName | string |  | ✓ |  |  ~ 128자 | 사용 횟수 제한 모델 이름<br>이 카운터가 속한 사용 횟수 제한 모델의 이름입니다. 이 카운터 값에 적용되는 리셋 일정(매일, 매주, 매월 등)을 결정합니다. |
| name | string |  | ✓ |  |  ~ 128자 | 카운터 이름<br>사용 횟수 제한 모델 내에서 이 카운터를 고유하게 식별하는 이름입니다. 동일한 사용 횟수 제한 모델을 서로 다른 이름의 여러 카운터로 공유할 수 있어, 개별 사용 횟수 제한 모델을 만들지 않고도 별도의 사용 횟수 추적(예: 퀘스트별 또는 상품별로 카운터 1개)이 가능합니다. |
| count | int |  |  | 0 | 0 ~ 2147483646 | 카운트 값<br>이 카운터의 현재 사용 횟수입니다. countUp 조작으로 증가하며, 이때 지정된 최대값과 비교됩니다. 사용 횟수 제한 모델의 리셋 시점에 도달하면 자동으로 0으로 리셋됩니다. |
| createdAt | long |  | ※ | 현재 시각 |  | 생성일시<br>UNIX 시간・밀리초<br>※ 서버가 자동으로 설정 |
| updatedAt | long |  | ※ | 현재 시각 |  | 최종 갱신일시<br>UNIX 시간・밀리초<br>※ 서버가 자동으로 설정 |

**관련 메서드:**
countUp - 횟수 제한 카운터 카운트업
getCounter - 특정 횟수 제한 카운터 조회
listCounters - 플레이어의 횟수 제한 카운터 목록 조회


---

### EzLimitModel

횟수 제한 모델<br>

횟수 제한 모델에는 사용 횟수를 리셋하는 타이밍을 설정할 수 있습니다.<br>
리셋 간격은 "매일", "매주", "매월", "리셋하지 않음", "일정 일수마다" 5가지 중에서 선택할 수 있습니다.<br>

또한, 횟수 제한의 최대값은 마스터 데이터 쪽에서는 고정하지 않습니다.<br>
이는 게임 내 컨텍스트에 따라 허용되는 최대 횟수를 동적으로 변경할 수 있도록 하기 위함입니다.<br>
예를 들어 스텝업 가챠처럼,<br>
- 구매 횟수 카운터가 3회 미만일 때 구매할 수 있는 상품<br>
- 위 상품을 구매할 수 없을 때, 구매 횟수 카운터가 5회 미만이면 구매할 수 있는 다른 상품<br>

과 같이, 상황에 따라 "최대 횟수"를 전환할 수 있는 설계를 상정하고 있습니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| limitModelId | string |  | ※ |  |  ~ 1024자 | 횟수 제한 모델 GRN<br>※ 서버가 자동으로 설정 |
| name | string |  | ✓ |  |  ~ 128자 | 횟수 제한 모델명<br>횟수 제한 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| metadata | string |  |  |  |  ~ 2048자 | 메타데이터<br>메타데이터에는 임의의 값을 설정할 수 있습니다.<br>이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. |
| resetType | 문자열 열거형<br>enum {<br>"notReset",<br>"daily",<br>"weekly",<br>"monthly",<br>"days"<br>}<br> |  | ✓ |  |  | 리셋 타이밍<br>이 횟수 제한 모델 하위의 카운터 값이 자동으로 0으로 리셋되는 타이밍을 결정합니다. notReset(영구적, 리셋 없음), daily(매일 지정된 시각에 리셋), weekly(지정된 요일에 리셋), monthly(지정된 날짜에 리셋), days(기준 일시로부터 일정 일수마다 리셋) 중에서 선택합니다. 모든 시각은 UTC입니다.notReset: 리셋 안 함 / daily: 매일 / weekly: 매주 / monthly: 매월 / days: 일정 일수마다 /  |
| resetDayOfMonth | int | {resetType} == "monthly" | ✓※ |  | 1 ~ 31 | 리셋 날짜<br>resetType이 "monthly"인 경우 카운터가 리셋되는 날짜(일)입니다. 1~31 사이의 값이 유효합니다. 지정한 날짜가 해당 월의 일수를 초과하는 경우(예: 2월의 31일), 해당 월의 마지막 날에 리셋됩니다.<br><br>※ resetType이(가) "monthly" 이면 필수 |
| resetDayOfWeek | 문자열 열거형<br>enum {<br>"sunday",<br>"monday",<br>"tuesday",<br>"wednesday",<br>"thursday",<br>"friday",<br>"saturday"<br>}<br> | {resetType} == "weekly" | ✓※ |  |  | 리셋 요일<br>resetType이 "weekly"인 경우 카운터가 리셋되는 요일입니다. 이 요일의 resetHour(UTC)로 지정된 시각에 리셋됩니다.sunday: 일요일 / monday: 월요일 / tuesday: 화요일 / wednesday: 수요일 / thursday: 목요일 / friday: 금요일 / saturday: 토요일 / <br><br>※ resetType이(가) "weekly" 이면 필수 |
| resetHour | int | {resetType} in ["monthly", "weekly", "daily"] | ✓※ |  | 0 ~ 23 | 리셋 시각<br>daily, weekly, monthly 리셋 타입에서 카운터가 리셋되는 UTC 시각(0~23)입니다. 예를 들어 값이 0이면 UTC 자정에 카운터가 리셋됩니다.<br><br>※ resetType이(가) "monthly","weekly","daily"이면 필수 |
| anchorTimestamp | long | {resetType} == "days" | ✓※ |  |  | 경과 일수를 계산하는 기준 일시<br>UNIX 시간(밀리초)<br><br>※ resetType이(가) "days" 이면 필수 |
| days | int | {resetType} == "days" | ✓※ |  | 1 ~ 2147483646 | 리셋 일수<br>resetType이 "days"인 경우 카운터 리셋 간격(일수)입니다. 리셋 주기는 anchorTimestamp를 기준으로 계산됩니다. 예를 들어 days가 7이고 anchorTimestamp가 월요일 정오라면, 매주 월요일 정오에 카운터가 리셋됩니다.<br><br>※ resetType이(가) "days" 이면 필수 |

**관련 메서드:**
getLimitModel - 이름을 지정하여 특정 횟수 제한 정의 조회
listLimitModels - 횟수 제한 정의 목록 조회


---

## 메서드

### countUp

횟수 제한 카운터 카운트업<br>

지정한 카운터를 지정한 양만큼 증가시킵니다. 카운터가 최대값을 초과하는 경우 작업은 실패합니다. 이것이 횟수 제한이 적용되는 방식입니다.<br>
예를 들어, 데일리 구매 제한이 3회로 설정되어 있고 플레이어가 이미 2회 구매한 경우, 1만큼 카운트업하면 성공합니다(합계: 3). 하지만 다시 카운트업하려고 하면 제한을 초과하므로 실패합니다.<br>
증가량(countUpValue)과 허용되는 최대값(maxValue)을 모두 지정할 수 있습니다.<br>
플레이어가 제한 액션을 실행할 때 사용합니다. 예를 들어 데일리 상점 구매나 제한된 던전 입장 시 호출합니다. 카운트업이 실패하면 플레이어가 제한에 도달했음을 의미합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| limitName | string |  | ✓|  |  ~ 128자 | 사용 횟수 제한 모델 이름<br>이 카운터가 속한 사용 횟수 제한 모델의 이름입니다. 이 카운터 값에 적용되는 리셋 일정(매일, 매주, 매월 등)을 결정합니다. |
| counterName | string |  | ✓|  |  ~ 128자 | 카운터 이름<br>사용 횟수 제한 모델 내에서 이 카운터를 고유하게 식별하는 이름입니다. 동일한 사용 횟수 제한 모델을 서로 다른 이름의 여러 카운터로 공유할 수 있어, 개별 사용 횟수 제한 모델을 만들지 않고도 별도의 사용 횟수 추적(예: 퀘스트별 또는 상품별로 카운터 1개)이 가능합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| countUpValue | int |  | | 1 | 1 ~ 2147483646 | 카운트업할 양 |
| maxValue | int |  | |  | 1 ~ 2147483646 | 카운트업을 허용하는 최댓값 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzCounter](#ezcounter) | 카운트를 증가시킨 카운터|

#### Error

이 API에는 특별한 예외가 정의되어 있습니다.<br>
GS2-SDK for Game Engine에서는 게임 내에서 핸들링이 필요할 것으로 예상되는 에러를, 일반적인 예외에서 파생된 특수화된 예외로 제공하여 다루기 쉽게 하고 있습니다.<br>
일반적인 에러의 종류와 핸들링 방법은 [여기]() 문서를 참고해 주세요.

| 타입 | 베이스 클래스 | 설명 |
| --- | --- | --- |
| OverflowException | BadRequestException | 횟수 제한의 상한에 도달했습니다 |

#### 구현 예제




**Unity (UniTask)**
```csharp

try {
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        limitName: "daily",
        counterName: "counter1"
    );
    var result = await domain.CountUpAsync(
        countUpValue: 1,
        maxValue: 100
    );
    var item = await result.ModelAsync();
} catch(Gs2.Gs2Limit.Exception.OverflowException e) {
    // The maximum number of times limit has been reached.
}

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        limitName: "daily",
        counterName: "counter1"
    );
    var future = domain.CountUpFuture(
        countUpValue: 1,
        maxValue: 100
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2Limit.Exception.OverflowException)
        {
            // The maximum number of times limit has been reached.
        }
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Limit->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Counter(
        "daily", // limitName
        "counter1" // counterName
    );
    const auto Future = Domain->CountUp(
        1, // countUpValue
        100 // maxValue
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::Limit::Error::FOverflowError::Class))
        {
            // The maximum number of times limit has been reached.
        }
        return false;
    }

    // 변경된 값 / 결과 값을 취득
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

```

**Godot**
```gdscript

var domain = ez.limit.namespace_(
        "namespace-0001"
    ).me(game_session).counter(
        "daily",
        "counter1"
    )

var async_result = await domain.count_up(
    1, # count_up_value
    100 # max_value
)
if async_result.error != null:
    if async_result.error is Gs2LimitOverflowException:
        # 횟수 제한의 상한에 도달했습니다
        pass
    push_error(str(async_result.error))
    return

var result = async_result.result

```


---

### getCounter

특정 횟수 제한 카운터 조회<br>

횟수 제한 모델명과 카운터명을 지정하여 특정 카운터를 조회합니다.<br>
카운터는 현재 기간 내에 플레이어가 이 특정 액션을 몇 번 실행했는지를 나타냅니다.<br>
특정 액션의 남은 횟수를 확인하는 데 사용합니다. 예를 들어 던전 입장 화면에서 "데일리 던전: 3/5회 사용 완료 — 남은 횟수 2회"와 같이 표시하는 데 유용합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| limitName | string |  | ✓|  |  ~ 128자 | 사용 횟수 제한 모델 이름<br>이 카운터가 속한 사용 횟수 제한 모델의 이름입니다. 이 카운터 값에 적용되는 리셋 일정(매일, 매주, 매월 등)을 결정합니다. |
| counterName | string |  | ✓|  |  ~ 128자 | 카운터 이름<br>사용 횟수 제한 모델 내에서 이 카운터를 고유하게 식별하는 이름입니다. 동일한 사용 횟수 제한 모델을 서로 다른 이름의 여러 카운터로 공유할 수 있어, 개별 사용 횟수 제한 모델을 만들지 않고도 별도의 사용 횟수 추적(예: 퀘스트별 또는 상품별로 카운터 1개)이 가능합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzCounter](#ezcounter) | 카운터|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        limitName: "daily",
        counterName: "counter1"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        limitName: "daily",
        counterName: "counter1"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Limit->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Counter(
        "daily", // limitName
        "counter1" // counterName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.limit.namespace_(
        "namespace-0001"
    ).me(game_session).counter(
        "daily",
        "counter1"
    )

var async_result = await domain.model()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


##### 값 변경 이벤트 핸들링




**Unity (UniTask)**
```csharp
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        limitName: "daily",
        counterName: "counter1"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        limitName: "daily",
        counterName: "counter1"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Limit->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Counter(
        "daily", // limitName
        "counter1" // counterName
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Limit::Model::FCounter> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->Unsubscribe(CallbackId);

```

**Godot**
```gdscript

var domain = ez.limit.namespace_(
        "namespace-0001"
    ).me(game_session).counter(
        "daily",
        "counter1"
    )

# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
    # 값이 변화했을 때 호출됨
    # value에는 변경 후의 값이 전달됩니다
    pass
)

# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)

```


**⚠️ Warning**

이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.

로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.

따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.

---

### listCounters

플레이어의 횟수 제한 카운터 목록 조회<br>

플레이어의 모든 횟수 제한 카운터를 조회하여, 각 제한 액션을 몇 번 실행했는지 확인할 수 있습니다.<br>
횟수 제한 모델명으로 필터링할 수도 있습니다. 생략하면 모든 제한 유형의 카운터가 반환됩니다.<br>
각 카운터는 특정 액션의 현재 카운트를 추적합니다(예: "데일리 상점 구매: 오늘 2/3회 사용").<br>
"남은 횟수" 또는 "데일리 제한" 개요 화면을 구축하는 데 사용합니다. 예를 들어 "상점 구매: 2/3회, 던전 입장: 1/5회, 무료 가챠: 0/1회"와 같은 표시에 유용합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| limitName | string |  | |  |  ~ 128자 | 횟수 제한 모델명<br>횟수 제한 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| pageToken | string |  | |  |  ~ 1024자 | 데이터 취득을 시작할 위치를 지정하는 토큰 |
| limit | int |  | | 30 | 1 ~ 1000 | 취득할 데이터 건수 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzCounter&gt;](#ezcounter) | 카운터 리스트|
| nextPageToken | string | 목록의 나머지를 취득하기 위한 페이지 토큰|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var items = await domain.CountersAsync(
        limitName: "daily"
    ).ToListAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var it = domain.Counters(
        limitName: "daily"
    );
    List<EzCounter> items = new List<EzCounter>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Limit->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto It = Domain->Counters(
        "daily" // limitName
    );
    TArray<Gs2::UE5::Limit::Model::FEzCounterPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

```


##### 값 변경 이벤트 핸들링




**Unity (UniTask)**
```csharp
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeCounters(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeCounters(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeCounters(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeCounters(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Limit->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->SubscribeCounters(
        []() {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->UnsubscribeCounters(CallbackId);

```


**⚠️ Warning**

이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.

로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.

따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.

---

### getLimitModel

이름을 지정하여 특정 횟수 제한 정의 조회<br>

이름을 지정하여 횟수 제한 모델을 1건 조회합니다.<br>
반환되는 정보에는 리셋 타입(리셋 없음 / 데일리 / 위클리 / 먼슬리)과 관련 설정이 포함됩니다.<br>
특정 제한의 규칙을 표시하는 데 사용합니다. 예를 들어 상점 상세 화면에서 "데일리 상점 제한 — 매일 자정에 리셋"과 같이 표시하는 데 유용합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| limitName | string |  | ✓|  |  ~ 128자 | 횟수 제한 모델명<br>횟수 제한 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzLimitModel](#ezlimitmodel) | 횟수 제한 모델|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).LimitModel(
        limitName: "limit-model-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).LimitModel(
        limitName: "limit-model-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Limit->Namespace(
        "namespace-0001" // namespaceName
    )->LimitModel(
        "limit-model-0001" // limitName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.limit.namespace_(
        "namespace-0001"
    ).limit_model(
        "limit-model-0001"
    )

var async_result = await domain.model()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


##### 값 변경 이벤트 핸들링




**Unity (UniTask)**
```csharp
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).LimitModel(
        limitName: "limit-model-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).LimitModel(
        limitName: "limit-model-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Limit->Namespace(
        "namespace-0001" // namespaceName
    )->LimitModel(
        "limit-model-0001" // limitName
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Limit::Model::FLimitModel> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->Unsubscribe(CallbackId);

```

**Godot**
```gdscript

var domain = ez.limit.namespace_(
        "namespace-0001"
    ).limit_model(
        "limit-model-0001"
    )

# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
    # 값이 변화했을 때 호출됨
    # value에는 변경 후의 값이 전달됩니다
    pass
)

# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)

```


**⚠️ Warning**

이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.

로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.

따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.

---

### listLimitModels

횟수 제한 정의 목록 조회<br>

이 네임스페이스에 등록된 모든 횟수 제한 모델을 조회합니다.<br>
제한 모델은 사용 횟수 카운터의 동작 방식, 특히 리셋 시점을 정의합니다. 리셋 옵션은 다음과 같습니다:<br>
- 리셋 없음: 카운터가 리셋되지 않음(예: 1회 한정 첫 클리어 보너스)<br>
- 데일리: 매일 리셋(예: "하루 최대 3회 구매 가능")<br>
- 위클리: 매주 리셋(예: 주간 던전 도전 횟수)<br>
- 먼슬리: 매월 리셋(예: 월간 보상 수령 횟수)<br>
게임에 어떤 종류의 횟수 제한이 있는지 확인하는 데 사용합니다. 예를 들어 상점이나 활동 화면에서 "데일리 제한", "위클리 제한" 카테고리를 표시할 때 유용합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzLimitModel&gt;](#ezlimitmodel) | 횟수 제한 모델의 리스트|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    );
    var items = await domain.LimitModelsAsync(
    ).ToListAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    );
    var it = domain.LimitModels(
    );
    List<EzLimitModel> items = new List<EzLimitModel>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Limit->Namespace(
        "namespace-0001" // namespaceName
    );
    const auto It = Domain->LimitModels(
    );
    TArray<Gs2::UE5::Limit::Model::FEzLimitModelPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

```


##### 값 변경 이벤트 핸들링




**Unity (UniTask)**
```csharp
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeLimitModels(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeLimitModels(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeLimitModels(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeLimitModels(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Limit->Namespace(
        "namespace-0001" // namespaceName
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->SubscribeLimitModels(
        []() {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->UnsubscribeLimitModels(CallbackId);

```


**⚠️ Warning**

이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.

로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.

따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.

---



