Use case: Create and upload files to a dataset
You can use the Unity Cloud Assets package to:
- view the files of an asset.
- upload files to an asset's dataset.
- reference files between datasets.
The SDK supports several workflows for users with different roles.
Organization or Asset Manager Project role | View files | Upload new file | Add/remove file references |
---|---|---|---|
Asset Management Viewer |
yes | no | no |
Asset Management Consumer |
yes | no | no |
Asset Management Contributor |
yes | yes | yes |
Organization Owner |
yes | yes | yes |
Before you start
Before you start, you must:
Set up a Unity scene in the Unity Editor with an Organization and Project browser. See Get started with Assets for more information.
Have some assets in the cloud. There are several ways to do so:
- You can create assets through the Get started with Assets.
- You can create assets through the dashboard; see the Managing assets on the dashboard documentation.
How do I...?
List an asset's datasets and files
To list datasets, open the AssetManagementBehaviour
script you created and add the following code to the end of the class:
public List<IDataset> Datasets { get; private set; }
public async Task GetDatasets()
{
Datasets = null;
if (CurrentAsset == null) return;
var datasets = new List<IDataset>();
var asyncList = CurrentAsset.ListDatasetsAsync(Range.All, CancellationToken.None);
await foreach (var dataset in asyncList)
{
datasets.Add(dataset);
}
Datasets = datasets;
}
To list files, open the AssetManagementBehaviour
script you created and add the following code to the end of the class:
public Dictionary<DatasetId, IEnumerable<IFile>> DatasetFiles { get; } = new();
public async Task GetFilesAsync(DatasetId datasetId)
{
DatasetFiles.Remove(datasetId);
var dataset = Datasets?.FirstOrDefault(d => d.Descriptor.DatasetId == datasetId);
if (dataset == null) return;
DatasetFiles[datasetId] = null;
var files = new List<IFile>();
var fileList = dataset.ListFilesAsync(Range.All, CancellationToken.None);
await foreach (var file in fileList)
{
files.Add(file);
}
DatasetFiles[datasetId] = files;
}
Upload a file
To upload a file to an asset's dataset, follow these steps:
- Open the
AssetManagementBehaviour
script you created. - Add the following code to the end of the class:
class LogProgress : IProgress<HttpProgress>
{
public void Report(HttpProgress value)
{
if (!value.UploadProgress.HasValue) return;
Debug.Log($"Upload progress: {value.UploadProgress * 100} %");
}
}
public async Task UploadFile(IDataset dataset, string filePath)
{
var fileCreation = new FileCreation(Path.GetFileName(filePath))
{
Description = "Documentation example asset file creation.",
Tags = new List<string> {"Texture", "Gray"}
};
try
{
var progress = new LogProgress();
var fileStream = File.OpenRead(filePath);
var file = await dataset.UploadFileAsync(fileCreation, fileStream, progress, default);
_ = GetFilesAsync(dataset.Descriptor.DatasetId);
Debug.Log($"Asset file upload: {file.Descriptor.Path} added and uploaded.");
}
catch (Exception e)
{
Debug.LogError($"Failed to upload file: {fileCreation.Path}. {e}");
}
}
The code snippet does the following:
- Displays a UI button for creating a new file.
- When the button is clicked, a file dialog opens to select a file.
- When a file is selected, a new file definition is created and the file content is uploaded.
- Prints a progress log for the upload to the console.
- Prints a message to the console when the upload is complete OR an error message if the upload fails.
Reference a file in a different dataset
To reference a file in a different dataset, follow these steps:
- Open the
AssetManagementBehaviour
script you created. - Add the following code to the end of the class:
public async Task LinkFile(IDataset dataset, IFile file)
{
try
{
await dataset.AddExistingFileAsync(file.Descriptor.Path, file.Descriptor.DatasetId, CancellationToken.None);
Debug.Log($"File: {file.Descriptor.Path} linked to dataset {dataset.Descriptor.DatasetId}.");
}
catch (Exception e)
{
Debug.LogError($"Failed to link asset file: {file.Descriptor.Path}. {e}");
}
}
The code snippet does the following:
- Links a file to a dataset.
- Prints a message to the console on success OR an error message if the linking fails.
Remove a file reference from a dataset
To remove a file reference from a dataset, follow these steps:
- Open the
AssetManagementBehaviour
script you created. - Add the following code to the end of the class:
public async Task UnlinkFile(IDataset dataset, IFile file)
{
try
{
await dataset.RemoveFileAsync(file.Descriptor.Path, CancellationToken.None);
Debug.Log($"File: {file.Descriptor.Path} unlinked from dataset {dataset.Descriptor.DatasetId}.");
_ = GetFilesAsync(dataset.Descriptor.DatasetId);
}
catch (Exception e)
{
Debug.LogError($"Failed to unlink asset file: {file.Descriptor.Path}. {e}");
}
}
The code snippet does the following:
- Unlinks a file from a dataset.
- Prints a message to the console on success OR an error message if the unlinking fails.
Add the UI for creating files
To create UI for creating files, follow these steps:
- In your Unity Project window, go to Assets > Scripts.
- Select and hold the
Assets/Scripts
folder. - Go to Create > C# Script. Name your script
UseCaseFileCreationExampleUI
. - Open the
UseCaseFileCreationExampleUI
script you created and replace the contents of the file with the following code sample:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Unity.Cloud.Assets;
using Unity.Cloud.Common;
using UnityEngine;
public class UseCaseFileCreationExampleUI : IAssetManagementUI
{
readonly AssetManagementBehaviour m_Behaviour;
public UseCaseFileCreationExampleUI(AssetManagementBehaviour behaviour)
{
m_Behaviour = behaviour;
}
public void OnGUI() { }
}
- In the same script, replace the
OnGUI
function with the following code:
IAsset m_CurrentAsset;
Vector2 m_DatasetsScrollPosition;
Dictionary<DatasetId, bool> m_Expanded = new();
public void OnGUI()
{
if (!m_Behaviour.IsProjectSelected) return;
if (m_CurrentAsset != m_Behaviour.CurrentAsset)
{
m_CurrentAsset = m_Behaviour.CurrentAsset;
_ = m_Behaviour.GetDatasets();
}
if (m_CurrentAsset == null)
{
GUILayout.Label(" ! No asset selected !");
return;
}
if (m_Behaviour.Datasets == null)
{
GUILayout.Label("Loading datasets...");
return;
}
GUILayout.BeginVertical();
if (GUILayout.Button("Refresh Datasets", GUILayout.Width(120)))
{
_ = m_Behaviour.GetDatasets();
}
GUILayout.Space(5f);
DisplayDatasets(m_Behaviour.Datasets.ToArray());
GUILayout.EndVertical();
}
void DisplayDatasets(IReadOnlyCollection<IDataset> datasets)
{
if (datasets.Count == 0)
{
GUILayout.Label("No datasets.");
return;
}
m_DatasetsScrollPosition = GUILayout.BeginScrollView(m_DatasetsScrollPosition, GUILayout.Height(Screen.height * 0.8f));
foreach (var dataset in datasets)
{
DisplayDataset(dataset);
GUILayout.Space(10f);
}
GUILayout.EndScrollView();
}
void DisplayDataset(IDataset dataset)
{
GUILayout.BeginHorizontal();
GUILayout.Label(dataset.Name);
GUILayout.Space(5f);
#if UNITY_EDITOR
if (GUILayout.Button("Upload new file", GUILayout.Width(100)))
{
var filePath = UnityEditor.EditorUtility.OpenFilePanel("File to upload", "Assets", string.Empty);
if (!string.IsNullOrEmpty(filePath))
_ = m_Behaviour.UploadFile(dataset, filePath);
}
#endif
var expanded = m_Expanded.GetValueOrDefault(dataset.Descriptor.DatasetId);
if (GUILayout.Button(expanded ? "-" : "+", GUILayout.Width(20f)))
{
expanded = !expanded;
m_Expanded[dataset.Descriptor.DatasetId] = expanded;
if (!expanded)
{
m_Behaviour.DatasetFiles.Remove(dataset.Descriptor.DatasetId);
}
}
GUILayout.EndHorizontal();
if (expanded)
{
GUILayout.BeginHorizontal();
GUILayout.Space(25);
DisplayFiles(dataset);
GUILayout.EndHorizontal();
}
if (m_SelectedFile != null)
{
m_WindowRect = GUILayout.Window(0, m_WindowRect, DisplayWindow, "Select files to link");
}
}
void DisplayFiles(IDataset dataset)
{
if (!m_Behaviour.DatasetFiles.ContainsKey(dataset.Descriptor.DatasetId))
{
_ = m_Behaviour.GetFilesAsync(dataset.Descriptor.DatasetId);
}
var files = m_Behaviour.DatasetFiles.GetValueOrDefault(dataset.Descriptor.DatasetId);
if (files == null)
{
GUILayout.Label("Loading files...");
return;
}
var enumerable = files.ToArray();
if (!enumerable.Any())
{
GUILayout.Label("No files.");
return;
}
GUILayout.BeginVertical();
foreach (var file in enumerable)
{
DisplayFile(dataset, file);
}
GUILayout.EndVertical();
}
void DisplayFile(IDataset dataset, IFile file)
{
GUILayout.BeginHorizontal();
GUILayout.Label($"{file.Descriptor.Path} ({file.SizeBytes} kb)");
if (GUILayout.Button("Link to", GUILayout.Width(60)))
{
m_WindowRect = new Rect(Screen.width * 0.4f, Screen.height * 0.4f, Screen.width * 0.2f, Screen.height * 0.2f);
m_SelectedFile = file;
m_AvailableDatasets = m_Behaviour.Datasets?.Where(f => !m_SelectedFile.LinkedDatasets.Contains(dataset.Descriptor)).ToList();
}
if (GUILayout.Button("Unlink", GUILayout.Width(60)))
{
_ = m_Behaviour.UnlinkFile(dataset, file);
}
GUILayout.EndHorizontal();
}
Rect m_WindowRect;
IFile m_SelectedFile;
List<IDataset> m_AvailableDatasets;
void DisplayWindow(int windowId)
{
GUILayout.BeginVertical();
GUILayout.Label($"Link {m_SelectedFile.Descriptor.Path} to:");
if (m_AvailableDatasets.Count == 0)
{
GUILayout.Label(" ! No datasets to link to !");
}
else
{
for (var i = 0; i < m_AvailableDatasets.Count; ++i)
{
GUILayout.BeginHorizontal();
GUILayout.Label(m_AvailableDatasets[i].Name);
if (GUILayout.Button("Link", GUILayout.Width(60)))
{
_ = m_Behaviour.LinkFile(m_AvailableDatasets[i], m_SelectedFile);
m_AvailableDatasets.RemoveAt(i);
// Force a refresh of the dataset files, including the already linked ones of the selected one
foreach (var linkedDatasetId in m_SelectedFile.LinkedDatasets.Select(d => d.DatasetId))
{
m_Behaviour.DatasetFiles.Remove(linkedDatasetId);
m_Expanded.Remove(linkedDatasetId);
}
m_Behaviour.DatasetFiles.Remove(m_AvailableDatasets[i].Descriptor.DatasetId);
m_Expanded.Remove(m_AvailableDatasets[i].Descriptor.DatasetId);
GUILayout.EndHorizontal();
break;
}
GUILayout.EndHorizontal();
}
}
GUILayout.Space(10f);
if (GUILayout.Button("Close", GUILayout.Width(60)))
{
m_SelectedFile = null;
m_AvailableDatasets = null;
}
GUILayout.EndVertical();
}
- Open the
AssetManagementUI
script you created and replace the contents of theAwake
function with the following code:
m_UI.Add(new OrganizationSelectionExampleUI(m_Behaviour));
m_UI.Add(new ProjectSelectionExampleUI(m_Behaviour));
m_UI.Add(new AssetSelectionExampleUI(m_Behaviour));
m_UI.Add(new UseCaseFileCreationExampleUI(m_Behaviour));
The code snippet does the following:
- Provides a UI button to refresh the list of files within each dataset.
- Provides UI buttons to trigger the creation of a new file within a dataset.
- Provides a UI button to link an existing file to a dataset.
- Provides a UI button for each existing file to unlink it from its dataset.