# Create UGC In-Game

In this How-to, we’ll go through the process of creating a UGC asset candidate, adding some information to it and promoting it to a UGC asset that can be viewed by all players in your game.

## Prerequisites

* [An active Game Session](https://docs.lootlocker.com/players/authentication)
* `Optional` A context to use for the newly created UGC, if none is provided [a default context will be given](https://docs.lootlocker.com/content/working-with-assets)

### Create an asset candidate

The first thing a user needs to do is to create an asset candidate, which is the “working state” of UGC in LootLocker.

{% tabs %}
{% tab title="Unity" %}

```csharp
// Name is required when creating an asset candidate
string name = "New Asset Candidate";

// The below additional variables are optional
Dictionary<string, string> kv_storage = new Dictionary<string, string>();
kv_storage.Add("key", "value"); // Optional
Dictionary<string, string> filters = new Dictionary<string, string>();
filters.Add("key", "value"); // Optional
Dictionary<string, string> data_entities = new Dictionary<string, string>();
filters.Add("data", "name"); // Optional
int context_id = -1; // Optional

string asset_candidate_id = "";
LootLockerSDKManager.CreatingAnAssetCandidate(name, kv_storage, filters, data_entities, (response) =>
{
    if (response.success)
    {
        Debug.Log("Successfully created asset candidate with ID: " + response.asset_candidate_id);
        // Save the asset_candidate_id for future requests
        asset_candidate_id = response.asset_candidate_id;
    }
    else
    {
        Debug.Log("Error asset candidate");
    }
});
```

{% endtab %}

{% tab title="Unreal" %}

<figure><img src="https://534367586-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVu1MPzezO-NgvC98xh%2Fuploads%2Fgit-blob-f2fdac6911ad76235e0121cc7260123553ac0899%2FCreateupdate%20Asset%20Candidate?alt=media" alt=""><figcaption><p><a href="https://blueprintue.com/blueprint/kacnwp5u/">Blueprint example of creating an asset candidate</a></p></figcaption></figure>
{% endtab %}

{% tab title="REST" %}

```bash
curl -X POST "https://api.lootlocker.io/game/v1/player/assets/candidates" \
  -H "x-session-token: your_token_here" \
  -H "Content-Type: application/json" \
  -d "{\"data\": {\"name\": \"My UGC Asset\"}}"
```

{% hint style="info" %}
See the [reference docs](https://ref.lootlocker.com/game-api/#creating-an-asset-candidate) for a list of supported properties
{% endhint %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
We need the asset\_instance\_id for future requests, wait for the request to be done and save the asset\_candidate\_id before calling the next request.
{% endhint %}

## Working with the asset candidate

After the asset candidate has been created you have several ways of modifying it:

### Delete the asset candidate

{% tabs %}
{% tab title="Unity" %}

```csharp
int assetCandidateID = 13;
LootLockerSDKManager.DeletingAnAssetCandidate(assetCandidateID, (response) =>
{
    if (response.success)
    {
        Debug.Log("Successfully deleted asset candidate");
    }
    else
    {
        Debug.Log("Error deleting asset canddidate");
    }
});
```

{% endtab %}

{% tab title="Unreal" %}

<figure><img src="https://534367586-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVu1MPzezO-NgvC98xh%2Fuploads%2Fgit-blob-ac61b979713ef460324d956726393a39e10905d1%2Fimage%20(3)%20(1)%20(2).png?alt=media" alt=""><figcaption><p><a href="https://blueprintue.com/blueprint/4ad-x-qp/">Blueprint example of deleting an asset candidate</a></p></figcaption></figure>
{% endtab %}

{% tab title="REST" %}

```bash
curl -X DELETE "https://api.lootlocker.io/game/v1/player/assets/candidates/1234" \
  -H "x-session-token: your_token_here"
```

{% hint style="info" %}
The `1234` in the url is the asset\_candidate\_id that will be deleted
{% endhint %}
{% endtab %}
{% endtabs %}

### Add files to the asset candidate

{% tabs %}
{% tab title="Unity" %}

```csharp
int assetCandidateID = 12;
string filePath = "Assets/Resources/300.jpg";
string fileName = "300.jpg";
LootLocker.LootLockerEnums.FilePurpose fileType = LootLocker.LootLockerEnums.FilePurpose.primary_thumbnail;
LootLockerSDKManager.AddingFilesToAssetCandidates(assetCandidateID, filePath, fileName, fileType, (response) =>
{
    if (response.success)
    {
        Debug.Log("Successfully added image to asset candidate");
    }
    else
    {
        Debug.Log("Error adding image to asset candidate");
    }
});
```

{% endtab %}

{% tab title="Unreal" %}

<figure><img src="https://534367586-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVu1MPzezO-NgvC98xh%2Fuploads%2Fgit-blob-f75641085eb41af553b9bedc15b94040ac2ad54c%2Fimage%20(2)%20(1)%20(2).png?alt=media" alt=""><figcaption><p><a href="https://blueprintue.com/blueprint/vodoh3dg/">Blueprint example of adding files to an asset candidate</a></p></figcaption></figure>
{% endtab %}

{% tab title="REST" %}

```bash
curl -L -X POST 'https://api.lootlocker.io/game/v1/player/assets/candidates/1234/file' \
  -H "x-session-token: your_token_here" \
  -F 'file=@/path/to/file.ext' \
  -F 'purpose=PRIMARY_THUMBNAIL'
```

{% endtab %}
{% endtabs %}

### Remove files from the Asset candidate

{% tabs %}
{% tab title="Unity" %}

```csharp
int assetCandidateID = 12;
int fileID = 1;
LootLockerSDKManager.RemovingFilesFromAssetCandidates(assetCandidateID, fileID, (response) =>
{
    if (response.success)
    {
      Debug.Log("Successfully removed file from asset candidate");
    }
    else
    {
      Debug.Log("Error removing file from asset candidate");
    }
});
```

{% endtab %}

{% tab title="Unreal" %}

<figure><img src="https://534367586-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVu1MPzezO-NgvC98xh%2Fuploads%2Fgit-blob-dcf96f04de43681954a6007c125aed765232d7a8%2Fimage%20(1)%20(4).png?alt=media" alt=""><figcaption><p><a href="https://blueprintue.com/blueprint/kchilcau/">Blueprint example of deleting files from an asset candidate</a></p></figcaption></figure>
{% endtab %}

{% tab title="REST" %}

```bash
curl -X DELETE "https://api.lootlocker.io/game/v1/player/assets/candidates/1234/file/5678" \
  -H "x-session-token: your_token_here"
```

{% hint style="info" %}
The `1234` in the url is the asset\_candidate\_id, `5678` is the file\_id that can be retrieved when creating the file or inspecting the asset candidate
{% endhint %}
{% endtab %}
{% endtabs %}

### Update or add data to the asset candidate

{% tabs %}
{% tab title="Unity" %}

```csharp
bool isCompleted = false;
// When updating an asset, all properties are optional.
// Empty fields are also updated, only update the ones that you want to replace
string name = "New Name"; // Optional
Dictionary<string, string> kv_storage = new Dictionary<string, string>();
kv_storage.Add("key", "value"); // Optional
Dictionary<string, string> filters = new Dictionary<string, string>();
filters.Add("key", "value"); // Optional
Dictionary<string, string> data_entities = new Dictionary<string, string>();
filters.Add("data", "name"); // Optional
int context_id = -1; // Optional
LootLockerSDKManager.UpdatingAnAssetCandidate(asset_candidate_id, isCompleted, (response) =>
{
    if (response.success)
    {
        Debug.Log("Successfully updated asset candidate with ID: " + response.asset_candidate.id);
    }
    else
    {
        Debug.Log("Error updating asset candidate");
    }
}, name, kv_storage, filters, data_entities, context_id);
```

{% endtab %}

{% tab title="Unreal" %}
{% hint style="info" %}
The boolean "IsCompleted" should be false to Update the asset candidate!
{% endhint %}

<figure><img src="https://534367586-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVu1MPzezO-NgvC98xh%2Fuploads%2Fgit-blob-f2fdac6911ad76235e0121cc7260123553ac0899%2FCreateupdate%20Asset%20Candidate?alt=media" alt=""><figcaption><p><a href="https://blueprintue.com/blueprint/738lz2-5/">Blueprint example of updating an asset candidate</a></p></figcaption></figure>

{% hint style="info" %}
The Boolean "Is Completed", when it is set to true, the Asset Candidate will be sent for moderation, if that is enabled on your game. If Moderation is disabled, the asset will be promoted to an asset.
{% endhint %}

When Updating the Asset Candidate, it is important to remember that it is not enough to just set the values that you do want to update, you have to set every value. This is due to the fact that empty fields will update. So to update, you will need the data from the non-updated version and update from there.
{% endtab %}

{% tab title="REST" %}

```bash
curl -X PUT "https://api.lootlocker.io/game/v1/player/assets/candidates/1234" \
  -H "x-session-token: your_token_here" \
  -H "Content-Type: application/json" \
  -d "{\"completed\": true, \"data\": {\"name\": \"My Renamed Asset Candidate\"}}"
```

{% hint style="info" %}
See the [reference docs](https://ref.lootlocker.com/game-api/#creating-an-asset-candidate) for a list of supported update properties
{% endhint %}
{% endtab %}
{% endtabs %}

When you are satisfied with the changes to the asset candidate, you simply call the `UpdatingAnAssetCandidate()` function again, and change the `isCompleted` bool to `true` and the asset candidate will then be promoted to a UGC asset to be viewed by all your players.

## Conclusion

In this How-to, we’ve created a UGC asset candidate, added some information to it and promoted it to an asset. If UGC moderation is enabled in your game, the newly generated asset will show up in the [UGC moderation tab](https://console.lootlocker.com/feedback/moderation/user-content) in the web console for you to take action on, and otherwise it will be available instantly to all your players by using any of the [ListAssets() functions](https://docs.lootlocker.com/content/working-with-assets). With UGC it can also be a good idea to add a way for players to [report the created content](https://docs.lootlocker.com/game-systems/feedback/how-to/create-ugc-feedback).
