docs.unity3d.com
Search Results for

    Show / Hide Table of Contents

    Use case: Download, update and generate tags for an asset's files

    You can use the Unity Cloud Assets package to download file content, edit file metadata and generate AI tags.

    The SDK supports different workflows for users with different roles.

    Organization or Asset Manager Project role Download files Update files
    Asset Management Viewer no no
    Asset Management Consumer yes no
    Asset Management Contributor yes yes
    Organization Owner yes yes

    Before you start

    Before you start, you must:

    1. Set up a Unity scene in the Unity Editor with an Organization and Project browser. See Get started with Assets for more information.

    2. 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.

    You should also have uploaded files to an asset; see the Create files use case.

    How do I...?

    List the files of a dataset

    If you have not already done so, you must update the behaviour to get the list of files for an asset's dataset.

    See the Use case: Create datasets documentation for more information.

    Download a file

    To download the file of an asset, follow these steps:

    1. Open the AssetManagementBehaviour script you created.
    2. Add the following code to the end of the class:
    
            public async Task DownloadFileAsync(string filePath)
            {
    #if UNITY_EDITOR
                const string dialogHeader = "Download file to location:";
    
                var defaultFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                var folder = UnityEditor.EditorUtility.OpenFolderPanel(dialogHeader, defaultFolder, "");
    
                if (string.IsNullOrEmpty(folder)) return;
    
                var downloadPath = Path.Combine(folder, filePath);
    
                try
                {
                    // Create the necessary directories
                    var directory = Path.GetDirectoryName(downloadPath);
                    if (!string.IsNullOrEmpty(directory))
                    {
                        Directory.CreateDirectory(directory);
                    }
    
                    var file = DatasetFiles.Where(x => x.Key == CurrentDatasetId)
                        .SelectMany(x => x.Value)
                        .FirstOrDefault(x => x.Descriptor.Path == CurrentFilePath);
                    if (file == null) return;
    
                    await using var destination = File.OpenWrite(downloadPath);
    
                    await file.DownloadAsync(destination, new LogProgress(downloadPath), default);
    
                    Debug.Log($"Asset file downloaded: {filePath}.");
                }
                catch (Exception e)
                {
                    Debug.LogError($"Failed to download asset file: {filePath}. {e}");
    
                    if (File.Exists(downloadPath))
                    {
                        File.Delete(downloadPath);
                    }
                }
    #else
                Debug.Log("Feature only supported in Editor.");
    #endif
            }
    
    

    The code snippet does the following:

    • Gets the files of an asset.
    • Downloads the selected file to the desktop.
    • Prints a message to the console when the download is complete OR prints an error message if the download fails.

    Update a file

    The properties of the file that can be updated are the following:

    • Description
    • Tags

    To update a file, follow these steps:

    1. Open the AssetManagementBehaviour script you created.
    2. Add the following code to the end of the class:
    
    public async Task UpdateFileAsync(IFileUpdate fileUpdate)
    {
        var file = DatasetFiles.Where(x => x.Key == CurrentDatasetId)
            .SelectMany(x => x.Value)
            .FirstOrDefault(x => x.Descriptor.Path == CurrentFilePath);
        if (file == null) return;
    
        try
        {
            await file.UpdateAsync(fileUpdate, CancellationToken.None);
            await file.RefreshAsync(CancellationToken.None);
    
            var properties = await file.GetPropertiesAsync(CancellationToken.None);
            FileProperties[CurrentFilePath] = properties;
    
            Debug.Log("File updated.");
        }
        catch (Exception e)
        {
            Debug.LogError($"Failed to update file. {e}");
            throw;
        }
    }
    
    

    The code snippet does the following:

    • Updates the file with new data.
    • Prints a message to the console on success.

    Delete a file

    Deleting a file involves removing all references to the file from the asset. For more information see the use case for Removing a file reference from a dataset.

    Generating tags for a file

    The service can generate a list of suggested tags for any image files in the following supported formats:

    • JPEG
    • PNG
    • GIF
    • TIFF
    • WebP

    The desired tags can then be added to the file through the update method.

    To generate tags for a file, follow these steps:

    1. Open the AssetManagementBehaviour script you created.
    2. Add the following code to the end of the class:
    
    public IEnumerable<GeneratedTag> GeneratedTags { get; private set; }
    
    CancellationTokenSource TagGenerationCancellationSource;
    
    public async Task GenerateTagsAsync()
    {
        CancelTagGeneration();
    
        TagGenerationCancellationSource = new CancellationTokenSource();
    
        try
        {
            var file = DatasetFiles.Where(x => x.Key == CurrentDatasetId)
                .SelectMany(x => x.Value)
                .FirstOrDefault(x => x.Descriptor.Path == CurrentFilePath);
            if (file == null) return;
            GeneratedTags = await file.GenerateSuggestedTagsAsync(TagGenerationCancellationSource.Token);
        }
        catch (OperationCanceledException)
        {
            Debug.Log($"Cancelled tag generation for {CurrentFilePath}.");
        }
        catch (Exception e)
        {
            Debug.LogError(e);
        }
    }
    
    public void CancelTagGeneration()
    {
        if (TagGenerationCancellationSource != null)
        {
            TagGenerationCancellationSource.Cancel();
            TagGenerationCancellationSource.Dispose();
        }
    
        TagGenerationCancellationSource = null;
        GeneratedTags = null;
    }
    
    

    The code snippet does the following:

    • Returns a list of generated tags for the file.
    • Prints any errors to the console.

    Add the UI for interacting with files

    To create UI for interacting with files, follow these steps:

    1. In your Unity Project window, go to Assets > Scripts.
    2. Select and hold the Assets/Scripts folder.
    3. Go to Create > C# Script. Name your script UseCaseManageFileExampleUI.
    4. Open the UseCaseManageFileExampleUI 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 UseCaseManageFileExampleUI : IAssetManagementUI
    {
        readonly BaseAssetBehaviour m_Behaviour;
    
        public UseCaseManageFileExampleUI(BaseAssetBehaviour behaviour)
        {
            m_Behaviour = behaviour;
        }
    
        public void OnGUI() { }
    }
    
    
    1. In the same script, replace the OnGUI function with the following code:
    
    IAsset m_CurrentAsset;
    Vector2 m_DatasetsScrollPosition;
    Vector2 m_ListScrollPosition;
    
    FileUpdate m_FileUpdate;
    string m_TagsString = string.Empty;
    
    public void OnGUI()
    {
        if (m_Behaviour.CurrentAsset == null) return;
    
        if (m_CurrentAsset != m_Behaviour.CurrentAsset)
        {
            m_CurrentAsset = m_Behaviour.CurrentAsset;
            m_FileUpdate = null;
            m_Behaviour.CancelTagGeneration();
            _ = m_Behaviour.GetDatasets();
        }
    
        GUILayout.BeginVertical();
    
        // Get a local copy of the list of datasets to avoid concurrent modification exceptions.
        DisplayDatasetSelection(m_Behaviour.Datasets.ToArray());
    
        GUILayout.EndVertical();
    
        if (m_Behaviour.CurrentDatasetId == null) return;
    
        GUILayout.BeginVertical();
    
        // Get a local copy of the list of files to avoid concurrent modification exceptions.
        IEnumerable<IFile> files = m_Behaviour.DatasetFiles.TryGetValue(m_Behaviour.CurrentDatasetId.Value, out var fileList)
            ? fileList
            : Array.Empty<IFile>();
        DisplayFileSelection(files.Select(x => x.Descriptor.Path).ToArray());
    
        GUILayout.EndVertical();
    
        GUILayout.BeginVertical(GUILayout.Width(250));
    
        DisplaySelectedFile();
    
        GUILayout.EndVertical();
    }
    
    void DisplayDatasetSelection(IReadOnlyCollection<IDataset> datasets)
    {
        if (GUILayout.Button("Refresh", GUILayout.Width(60)))
        {
            _ = m_Behaviour.GetDatasets();
        }
    
        GUILayout.Space(5);
    
        if (datasets.Count == 0)
        {
            GUILayout.Label("No datasets.");
            return;
        }
    
        m_DatasetsScrollPosition = GUILayout.BeginScrollView(m_DatasetsScrollPosition, GUILayout.ExpandHeight(true), GUILayout.Width(250));
    
        foreach (var dataset in datasets)
        {
            GUILayout.BeginHorizontal();
    
            GUILayout.Label(m_Behaviour.GetDatasetName(dataset.Descriptor.DatasetId), GUILayout.Width(150));
    
            GUI.enabled = dataset.Descriptor.DatasetId != m_Behaviour.CurrentDatasetId;
    
            if (GUILayout.Button("Select", GUILayout.Width(60)))
            {
                m_FileUpdate = null;
                m_Behaviour.CancelTagGeneration();
                m_Behaviour.CurrentDatasetId = dataset.Descriptor.DatasetId;
                _ = m_Behaviour.GetFilesAsync(dataset.Descriptor.DatasetId);
            }
    
            GUI.enabled = true;
    
            GUILayout.EndHorizontal();
        }
    
        GUILayout.EndScrollView();
    }
    
    void DisplayFileSelection(IReadOnlyCollection<string> filePaths)
    {
        if (GUILayout.Button("Refresh", GUILayout.Width(60)) && m_Behaviour.CurrentDatasetId.HasValue)
        {
            m_FileUpdate = null;
            m_Behaviour.CancelTagGeneration();
            _ = m_Behaviour.GetFilesAsync(m_Behaviour.CurrentDatasetId.Value);
            return;
        }
    
        GUILayout.Space(15f);
    
        if (filePaths.Count == 0)
        {
            GUILayout.Label("! No files !");
            return;
        }
    
        m_ListScrollPosition = GUILayout.BeginScrollView(m_ListScrollPosition, GUILayout.ExpandHeight(true), GUILayout.Width(330));
    
        DisplayFiles(filePaths);
    
        GUILayout.EndScrollView();
    }
    
    void DisplayFiles(IReadOnlyCollection<string> filePaths)
    {
        foreach (var filePath in filePaths)
        {
            if (!m_Behaviour.FileProperties.TryGetValue(filePath, out var fileProperties))
            {
                GUILayout.Label(filePath);
                continue;
            }
    
            GUILayout.BeginHorizontal();
    
            GUILayout.Label($"{filePath}", GUILayout.Width(150));
    
            GUI.enabled = filePath != m_Behaviour.CurrentFilePath;
    
            if (GUILayout.Button("Select", GUILayout.Width(70)))
            {
                m_FileUpdate = null;
                m_Behaviour.CurrentFilePath = filePath;
                m_TagsString = string.Join(',', fileProperties.Tags ?? Array.Empty<string>());
                m_Behaviour.CancelTagGeneration();
            }
    
            GUI.enabled = true;
    
            if (GUILayout.Button("Download", GUILayout.Width(70)))
            {
                _ = m_Behaviour.DownloadFileAsync(filePath);
            }
    
            GUILayout.EndHorizontal();
        }
    }
    
    void DisplaySelectedFile()
    {
        if (m_Behaviour.CurrentFilePath == null) return;
    
        if (!m_Behaviour.FileProperties.TryGetValue(m_Behaviour.CurrentFilePath, out var properties))
        {
            GUILayout.Label("Loading properties...");
            return;
        }
    
        GUILayout.Label($"Status: {properties.StatusName}");
    
        var createdDate = properties.AuthoringInfo?.Created.ToString("d") ?? "unknown";
        GUILayout.Label($"Created on: {createdDate}");
    
        var modifiedDate = properties.AuthoringInfo?.Updated.ToString("d") ?? "unknown";
        GUILayout.Label($"Last modified on: {modifiedDate}");
    
        GUILayout.Label($"Size: {properties.SizeBytes} bytes");
    
        GUILayout.Label("Description");
        var description = GUILayout.TextField(m_FileUpdate?.Description ?? properties.Description);
        if (m_FileUpdate != null || properties.Description != description)
        {
            m_FileUpdate ??= new FileUpdate();
            m_FileUpdate.Description = description;
        }
    
        GUILayout.Label("Tags (comma separated)");
        var tags = GUILayout.TextArea(m_TagsString);
        if (m_TagsString != tags)
        {
            m_TagsString = tags;
            OnTagStringUpdated();
        }
    
        if (GUILayout.Button("Generate Tags"))
        {
            _ = m_Behaviour.GenerateTagsAsync();
        }
    
        DisplayGeneratedTags(m_FileUpdate?.Tags ?? properties.Tags ?? Array.Empty<string>());
    
        GUILayout.Space(15f);
    
        GUI.enabled = m_FileUpdate != null;
        
        if (GUILayout.Button("Update"))
        {
            _ = m_Behaviour.UpdateFileAsync(m_FileUpdate);
            m_FileUpdate = null;
        }
        
        GUI.enabled = true;
    }
    
    void DisplayGeneratedTags(IEnumerable<string> existingTags)
    {
        if (m_Behaviour.GeneratedTags != null)
        {
            foreach (var tag in m_Behaviour.GeneratedTags)
            {
                GUILayout.BeginHorizontal();
    
                GUI.enabled = !existingTags.Contains(tag.Value);
    
                if (GUILayout.Button("+", GUILayout.Width(20)))
                {
                    if (string.IsNullOrWhiteSpace(m_TagsString))
                    {
                        m_TagsString = tag.Value;
                    }
                    else
                    {
                        m_TagsString += $", {tag.Value}";
                    }
    
                    OnTagStringUpdated();
                }
    
                GUILayout.Label($"{tag.Value}, Confidence: {tag.Confidence:F3}");
    
                GUI.enabled = true;
    
                GUILayout.EndHorizontal();
            }
        }
    }
    
    void OnTagStringUpdated()
    {
        m_FileUpdate ??= new FileUpdate();
        m_FileUpdate.Tags = m_TagsString.Split(',')
            .Select(x => x.Trim())
            .Where(x => !string.IsNullOrWhiteSpace(x))
            .ToArray();
    }
    
    
    1. Open the AssetManagementUI script you created and replace the contents of the Awake 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 UseCaseManageFileExampleUI(m_Behaviour));
    
    

    The code snippet does the following:

    • Displays a button to force refresh the list of files of the selected asset.
    • Displays each file of the selected asset with a UI buttons to select and download.
    • When a file is selected, displays a UI to generate tags and update the file's description and tags.
    In This Article
    Back to top
    Copyright © 2025 Unity Technologies — Trademarks and terms of use
    • Legal
    • Privacy Policy
    • Cookie Policy
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)