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


# 5. 퀘스트 시작 시 스태미나 소비하기

퀘스트마다 스태미나를 소비하고 부족할 때는 회복을 기다리는 기능을 만듭니다.



이제 퀘스트에서 스태미나를 사용하도록 해 봅시다. 숲 탐험을 시작하는 데 5가 필요하고 부족하면 회복을 기다리는 규칙입니다.

## 시작하기 전에

진행 중인 퀘스트가 있다면 클리어한 뒤 스태미나 설정을 추가합니다.

## 추가할 설정

스태미나 설정 이름은 `stamina`입니다. 초기값과 일반 회복 상한은 모두 20으로 설정합니다. 사용한 스태미나는 300초마다 1씩 자연 회복되게 합니다.

## 따라 하기



**Studio**

### 스태미나 표 만들기

**Add features** 에서 **Stamina** 를 추가한 뒤 **Tables → Stamina (Energy)** 에 다음 행을 만듭니다.

| 항목 | 값 |
| --- | --- |
| ID | `stamina` |
| 초기 상한 (defaultMaximum) | `20` |
| 상한 초과 허용 (useOverflow) | 끄기 |
| 초과 시 상한 (overflowedMaximum) | `20` |
| 회복 간격 (recoveryIntervalMinutes) | `5`분 |
| 한 번의 회복량 (recoveryValue) | `1` |

회복 간격의 입력 단위는 **분** 입니다. 300초로 설정하려면 `5`를 입력합니다.

<a href="/images/adventure/later-chapters/05-stamina-settings.jpg" target="_blank" rel="noopener" aria-label="스태미나 설정. 상한 20, 상한 초과 불가, 5분마다 1 회복 (새 탭에서 확대)"><img src="/images/adventure/later-chapters/05-stamina-settings.jpg" alt="스태미나 설정. 상한 20, 상한 초과 불가, 5분마다 1 회복" loading="lazy"></a>

**Quest (Quest)** 에서 `forest`의 **Start costs** 를 더블 클릭합니다. **Add item → Not set** 을 열고 `ConsumeStaminaByUserId`(스태미나 소비)를 선택합니다. **Target resource** 는 **None** 으로 두고 다음 값을 입력합니다.

| 항목 | 값 |
| --- | --- |
| namespaceName | `Energy` |
| staminaName | `stamina` |
| userId | `#{userId}` |
| consumeValue | `5` |

<a href="/images/adventure/later-chapters/05-consume-stamina.jpg" target="_blank" rel="noopener" aria-label="퀘스트 시작 시 Energy의 stamina에서 consumeValue 5를 소비하는 설정 (새 탭에서 확대)"><img src="/images/adventure/later-chapters/05-consume-stamina.jpg" alt="퀘스트 시작 시 Energy의 stamina에서 consumeValue 5를 소비하는 설정" loading="lazy"></a>

일반 클리어 보상은 3장과 같이 `Currency`의 슬롯 `0`에 10코인을 지급합니다.

서버에 배포하고 Unity를 업데이트합니다.

<a href="/samples/adventure/ko/05/AdventureStudioView.cs" download>이 장의 AdventureStudioView.cs</a>를 다운로드하고 기존 `Assets/AdventureStudioView.cs`를 교체합니다.

Unity의 `Gs2` 오브젝트에 `EnergyHandler`를 추가하고 **Id** 를 `stamina`로 설정한 뒤 `AdventureStudioView`의 **Energy** 에 할당합니다.

현재 값 표시는 `DrawPlayerStatus()`에 모았습니다. 핸들러가 갱신한 스태미나도 여기서 표시합니다.

```csharp
private void DrawPlayerStatus()
{
    GUILayout.Label(wallet.HasValue
        ? "코인: " + wallet.Model.Free
        : "코인 로딩 중");

    if (!progress.HasValue)
    {
        GUILayout.Label("진행 상황 로딩 중");
    }
    else
    {
        GUILayout.Label(progress.Model.InProgress
            ? "모험 진행 중"
            : "모험을 선택하세요");
    }

    GUILayout.Label(energy.HasValue
        ? "스태미나: " + energy.Model.CurrentValue
        : "스태미나 로딩 중");
}
```




**SDK (Unity)**

### 설정 업데이트하기

<a href="/samples/adventure/ko/05/adventure-game.yaml" download>5장 템플릿을 다운로드</a>하고 **Deploy → adventure-game → Update stack** 을 열어 **Template data** 에서 파일을 선택합니다. 이전 리소스도 포함한 전체 템플릿입니다. 변경 내용을 확인하여 적용하고 **Update complete** 가 될 때까지 기다립니다.

템플릿의 스태미나 설정은 다음과 같습니다. `recoverIntervalMinutes`는 분 단위이므로 300이 아니라 `5`를 입력합니다.

```yaml
staminaModels:
  - name: stamina
    initialCapacity: 20
    isOverflow: false
    maxCapacity: 20
    recoverIntervalMinutes: 5
    recoverValue: 1
```

시작 시 소비에 `Gs2Stamina:ConsumeStaminaByUserId`를 설정하고 `staminaName = stamina`, `consumeValue = 5`를 전달합니다. Unity의 시작 버튼은 3장과 같은 `StartAsync()`를 호출합니다.

### Unity 코드 업데이트하기

다음 두 파일을 `Assets`에 넣습니다. 같은 이름의 파일이 있으면 교체합니다.

- <a href="/samples/adventure/ko/05/AdventurePlay.cs" download>AdventurePlay.cs</a>: 퀘스트 조작과 화면 표시
- <a href="/samples/adventure/ko/05/AdventurePlayer.cs" download>AdventurePlayer.cs</a>: 표시용 데이터의 구독과 해제

Inspector 설정은 그대로 사용합니다.

이 장에서 사용하는 부분은 아래와 같습니다. 이 발췌 코드를 별도 클래스로 추가할 필요는 없습니다.

```csharp
var meter = Gs2.Stamina.Namespace("adventure-stamina").Me(Session).Stamina("stamina");
var subscription = await meter.SubscribeWithInitialCallAsync(value => Stamina = value);
```

소비나 구매로 바뀐 값은 이 콜백으로 화면에 반영합니다. 자연 회복은 화면을 그릴 때 SDK의 `PredictRecovery()`로 반영합니다. 반환된 값을 표시하면 기다리는 동안에도 스태미나가 늘어납니다.

```csharp
using Gs2.Unity.Gs2Stamina.Model;

var now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
    + (player.Session.AccessToken.TimeOffset ?? 0) * 1000L;
var stamina = player.Stamina.PredictRecovery(now);
GUILayout.Label("스태미나: " + stamina.Value + " / " + stamina.MaxValue);
```

`now`는 세션 시각에 맞춘 밀리초 값입니다. `PredictRecovery()`는 구독으로 받은 원본 데이터를 바꾸지 않고 자연 회복 후의 값을 반환합니다.






## 스태미나 사용해 보기

지금까지 사용한 플레이어로 시험합니다. 배포 후 소비량 설정이 반영되기까지 최대 5분이 걸릴 수 있습니다. 아직 스태미나가 줄지 않으면 그 퀘스트를 클리어하고 잠시 기다렸다가 새로 시작하여 확인합니다.

1. 스태미나가 5 이상인지 확인하고 현재 값을 기록합니다.
2. 숲 탐험을 시작하여 스태미나가 5 줄었는지 확인합니다. 예를 들어 20이었다면 15가 됩니다.
3. 퀘스트를 클리어하고 코인도 10개 늘었는지 확인합니다.

조작 사이에 자연 회복되었다면 그만큼을 포함하여 비교합니다.

## 연습: 설정 바꿔 보기

퀘스트에 필요한 스태미나를 8로 바꿔 봅시다. Studio는 시작 시 소비의 `consumeValue`, SDK는 템플릿의 `consumeValue`를 `8`로 바꾸어 배포합니다.

스태미나가 8 이상일 때 숲 탐험을 시작하여 8 줄어드는지 확인합니다. 부족하면 자연 회복을 기다립니다. 여전히 5만 줄어들면 클리어하고 잠시 기다렸다가 새로 시작합니다. 확인 후 퀘스트를 클리어하고 소비량을 **5로 되돌려 배포** 합니다. 일반 보상은 10코인으로 둡니다.

## 스태미나가 부족할 때 확인하기

소비량을 되돌려 배포한 뒤 5분을 기다리고 숲 탐험을 새로 시작합니다. 스태미나가 5 줄어드는지 확인하고 클리어한 뒤 부족한 상태를 만듭니다.

1. 숲 탐험의 시작과 클리어를 반복하여 스태미나를 5 미만으로 만듭니다.
2. 시작 버튼을 다시 누릅니다. 오류 메시지가 표시되고 퀘스트가 시작되지 않는지 확인합니다.
3. 실패한 시도에서 스태미나가 소비되지 않았는지도 확인합니다.

스태미나는 300초마다 1씩 자연 회복됩니다. 5 이상이 되면 다시 퀘스트를 시작할 수 있습니다.

[다음: 코인으로 스태미나 회복하기]()



