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


# Collect and train characters

Recruit characters in the forest, draw characters, give them experience, and build a three-slot party.



Let players earn a knight by completing the forest quest, and draw either a knight or a mage. Each character has its own identity, so players can train two knights separately and put both in their party.

## 1. Set up character types and inventory capacity


**Studio**

Add **Characters** from **Add features**. Under **Tables → Characters**, edit the following three tables. Select a cell and press Enter to edit it; double-click an array cell to edit its entries.

| Table | Row | Values |
| --- | --- | --- |
| Character slots (CharacterCollection) | Click **Add row**; no ID is needed | Initial capacity `20`, maximum capacity `100` |
| Character experience (CharacterExperience) | Click **Add row**; no ID is needed | Add `1`, `10`, and `20` to the Experience thresholds, in that order. Set both the initial and maximum level caps to `4` |
| Character (Character) | Add a row with ID `knight` | Sort order `1` |
| Character (Character) | Add a row with ID `mage` | Sort order `2` |

Deploy from **Publish → Calculate server differences**, then click **Update the Unity project**. Owned characters are stored in the `Character` namespace, and experience in `CharacterExperience`.


**SDK (Unity)**

Download the <a href="/samples/adventure/en/extensions/characters.json" download>character settings template</a>. In the management console, open the Tokyo region and go to **Deploy → Stack list → Create stack**. Enter `adventure-characters` as the name, select the downloaded file under **Template data**, and create the stack.

This stack contains settings for character inventory, experience, draws, and party formation. Keep using your existing `adventure-game` stack.

| Data | Namespace | Setting name |
| --- | --- | --- |
| Owned characters | `adventure-character` | Inventory `Character`, Item `knight` / `mage` |
| Experience | `adventure-character-experience` | Experience `Experience` |
| Character draws | `adventure-character-gacha` | Lottery `normal`, Showcase `Showcase`, product `normal` |
| Party Formation | `adventure-character-formation` | Mold `CharacterFormation`, save slot `0` |

The initial inventory capacity is 20, the maximum is 100, and each character occupies a stack of one. `allowMultipleStacks` is `true`, allowing players to own multiple characters of the same type.




### Add a knight to the forest completion rewards


**Studio**

Under **Tables → Quests → Quest**, open **Completion rewards** for `forest`. Keep the coin, mission counter, and potion actions, then click **Add item → Not set**. Select `AcquireItemSetByUserId` and enter the following values.

| Field | Value |
| --- | --- |
| namespaceName | `Character` |
| userId | `#{userId}` |
| inventoryName | `Character` |
| itemName | `knight` |
| acquireCount | `1` |

Save and deploy the changes to the server.


**SDK (Unity)**

Open the current template for `adventure-game`. Under `main` → `forest` → `contents` → `completeAcquireActions`, append the following entry. Keep the existing coin, mission counter, and potion entries. Update the stack using the entire modified template.

```yaml
- action: Gs2Inventory:AcquireItemSetByUserId
  request: |-
    {"namespaceName":"adventure-character","userId":"#{userId}","inventoryName":"Character","itemName":"knight","acquireCount":1}
```




### Show owned characters in Unity

Stop Play Mode in Unity and uncheck **Adventure Items** on `Extensions`. Keep the adventure panel on the left.


**Studio**

Place <a href="/samples/adventure/en/extensions/studio/AdventureCharacters.cs" download>AdventureCharacters.cs</a> in `Assets/AdventureExtensions`, then add **Adventure Characters** to `Extensions`. It uses the signed-in `Gs2ClientHolder` and `Gs2GameSessionHolder`.


**SDK (Unity)**

Place <a href="/samples/adventure/en/extensions/sdk/AdventureCharacters.cs" download>AdventureCharacters.cs</a> in `Assets/AdventureExtensions`, then add **Adventure Characters** to `Extensions`. Assign the scene's `AdventureLogin` to **Login**.




Enter Play Mode, then start and complete a new forest quest on the left. The list on the right shows `knight` and an identifier for that individual character. Complete the forest again to see two separate `knight` entries. After deployment, the new reward can take up to five minutes to take effect. If no knight is added, wait a little, then start and complete another forest quest.

The following call loads the initial list. After that, `SubscribeItemSets()` receives additions and removals. `ItemName` identifies the character type, while `ItemSetId` identifies each individual character.

```csharp
var inventory = Client.Inventory.Namespace(InventoryNamespace)
    .Me(Session).Inventory("Character");
await foreach (var item in inventory.ItemSetsAsync())
{
    if (item != null) owned.Add(item);
}
```

## 2. Draw a character for 20 coins


**Studio**

Add **Character Gacha** from **Add features**. Under **Tables → Character Gacha**, create the rows in the following order.

| Table | ID | Values |
| --- | --- | --- |
| Rarity (GachaRarity) | `common` | ID only |
| Gacha (Gacha) | `normal` | Leave the schedule empty |
| Rarity rate (GachaRarityRate) | Add a row | Gacha `normal`, rarity `common`, draw weight `1` |
| Character rate (CharacterRate) | Add a row | Rarity `common`, character `knight`, draw weight `1` |
| Character rate (CharacterRate) | Add another row | Rarity `common`, character `mage`, draw weight `1` |

In the rate tables, selecting the referenced entries sets the ID automatically. Do not enter an ID yourself.

Open **Cost per draw** for `normal` and add one `WithdrawByUserId` action. Set `namespaceName = Currency`, `userId = #{userId}`, `slot = 0`, `withdrawCount = 20`, and `paidOnly = false`. Save, then update the server and Unity project.


**SDK (Unity)**

These settings are already in the `LotteryMaster` and `ShowcaseMaster` of the `characters.json` you deployed. Both prizes have a weight of 1. The product consumes 20 coins and uses `Gs2Lottery:DrawByUserId` as its acquisition action.




Collect at least 20 coins in the adventure panel on the left, then click **Draw a character for 20 coins** on the right. A knight or mage is added to the list. Check that the coin balance on the left decreases by 20.

The purchase uses Showcase, whose acquisition action performs the Lottery draw.

```csharp
private async UniTask Draw(string requestId)
{
    var transaction = await Client.Showcase.Namespace(GachaNamespace).Me(Session)
        .Showcase("Showcase").DisplayItem("normal").BuyAsync(
            1, speculativeExecute: false, duplicationAvoider: requestId);
    if (transaction != null) await transaction.WaitAsync(all: true);
}
```

## 3. Give experience to a selected character

Training uses Exchange to spend 10 coins and grant 10 experience in one operation.


**Studio**

Download the <a href="/samples/adventure/en/extensions/character-training-studio.json" download>training settings for Studio characters</a>. In the management console, open **Deploy → Create stack**, name it `adventure-character-training`, and select the file under **Template data**. This template references the `Currency` and `CharacterExperience` namespaces created by Studio.


**SDK (Unity)**

Download the <a href="/samples/adventure/en/extensions/character-training-sdk.json" download>training settings for SDK characters</a>. Open **Deploy → Create stack**, name it `adventure-character-training`, and select the file under **Template data**. This template references `adventure-coin` and `adventure-character-experience`.




1. Select the character you want to train from the list on the right.
2. Click **Read selected character's experience** and note the current value.
3. Click **Add 10 experience for 10 coins**. The experience display updates automatically and increases by 10.
4. Select another character and read its experience to check that it has not increased.

Pass the `ItemSetId` selected when the button was clicked to `Train()`. The code appends `:level` to identify where that character's experience is stored. The `config` value fills `#{propertyId}` in the template.

```csharp
private async UniTask Train(string itemSetId, string requestId)
{
    var transaction = await Client.Exchange.Namespace("adventure-character-training").Me(Session).Exchange()
        .ExchangeAsync("train", 1, config: new[] {
            new Gs2.Unity.Gs2Exchange.Model.EzConfig { Key = "propertyId", Value = itemSetId + ":level" }
        }, speculativeExecute: false, duplicationAvoider: requestId);
    if (transaction != null) await transaction.WaitAsync(all: true);
}
```

## 4. Save a three-slot party


**Studio**

Add **Party Formation** from **Add features**. Under **Tables → Party Formation**, enter the following settings, then update the server and Unity project.

| Table | Row | Values |
| --- | --- | --- |
| Formation (CharacterFormation) | Click **Add row**; no ID is needed | Initial save slots `1`, maximum save slots `1` |
| Formation slot (CharacterFormationSlot) | Add `slot1`, `slot2`, and `slot3` | Placement condition `.*` for every row |


**SDK (Unity)**

The `FormationMaster` in `characters.json` already defines three slots. Use save slot `0` of `CharacterFormation`.




1. Click **Load party**, select a character from the list, then click **Put selected character in slot 1**.
2. Select another character and put it in slot 2. If you own a third character, put it in slot 3. You can save the party with empty slots.
3. Click **Save party**.
4. Stop and restart Play Mode, log in as the same player, then click **Load party**. Each slot shows the same character ID as before.

To save, the code calls Inventory's `GetItemWithSignatureAsync()` to obtain a signature proving ownership, then passes it to Formation's `SetFormAsync()`. It also checks that the same individual character is not placed in two slots.

[Next: Connect players]()



