Get started with Asset Management
Asset Management is a Unity Cloud service that allows you to manage your project's assets. You can use Asset Management to:
- Get an asset
- Search for assets
- Aggregate assets based on a set of criteria
- Create, read, update, and delete assets
This section explains how to set up a basic scene and script to initialize and use the Unity Asset Manager SDK package with Asset Management. It performs a basic search for all assets of the selected project and displays the results in a simple GUI.
Requirements
To use Asset Management and manage assets, you must have a minimum role of:
- Manager in the Unity Cloud Organization you belong to.
OR - Asset Manager Viewer in the Unity Cloud Project you belong to.
Configure the package
To configure the Unity Asset Manager SDK package, you must do the following:
- Set up a Unity scene
- Create an
AssetManager
- Create the
PlatformServices
Set up a Unity scene
To set up a Unity scene, perform the following steps:
- In your Unity project window, navigate to Assets > Scenes.
- Right-click the
Assets/Scenes
folder and navigate to Create > Scene. - Name the new scene
AssetManagementExample
.
Create an AssetManager
To create a MonoBehaviour
, perform the following steps:
- In your Unity project window, go to Assets > Scripts. Create an
Assets/Scripts
folder if the folder doesn't already exist. - Right-click the
Assets/Scripts
folder and go to Create > C# Script. Name your scriptAssetManagementUI
. - In the
AssetManagementExample
scene you created earlier, right-click the hierarchy and select Create Empty. - Name your new object
AssetManager
. - Select the
AssetManager
object and add theAssetManagementUI
script you created earlier.
Create the PlatformServices
To instantiate the necessary providers and managers, follow these steps:
- Implement the platform services pattern. See Best practices: dependency injection for more information.
- Update the
PlatformServices
class in yourPlatformServices.cs
file to look like the following:
using System;
using System.Threading.Tasks;
using Unity.Cloud.Assets;
using Unity.Cloud.Common;
using Unity.Cloud.Common.Runtime;
using Unity.Cloud.Identity;
using Unity.Cloud.Identity.Runtime;
public static class PlatformServices
{
/// <summary>
/// Returns a <see cref="ICompositeAuthenticator"/>.
/// </summary>
public static ICompositeAuthenticator Authenticator { get; private set; }
/// <summary>
/// Returns a <see cref="IAuthenticationStateProvider"/>.
/// </summary>
public static IAuthenticationStateProvider AuthenticationStateProvider => Authenticator;
/// <summary>
/// Returns an <see cref="IOrganizationProvider"/>.
/// </summary>
public static IOrganizationProvider OrganizationProvider { get; private set; }
/// <summary>
/// Returns an <see cref="IProjectProvider"/>.
/// </summary>
public static IProjectProvider ProjectProvider { get; private set; }
/// <summary>
/// Returns an <see cref="IAssetManager"/>
/// </summary>
public static IAssetManager AssetManager { get; private set; }
/// <summary>
/// Returns an <see cref="IAssetFileManager"/>
/// </summary>
public static IAssetFileManager AssetFileManager { get; private set; }
/// <summary>
/// Returns an <see cref="IAssetCollectionManager"/>
/// </summary>
public static IAssetCollectionManager AssetCollectionManager { get; private set; }
public static void Create()
{
var httpClient = new UnityHttpClient();
var serviceHostResolver = UnityRuntimeServiceHostResolverFactory.Create();
var playerSettings = UnityCloudPlayerSettings.Instance;
var platformSupport = PlatformSupportFactory.GetAuthenticationPlatformSupport();
var compositeAuthenticatorSettings = new CompositeAuthenticatorSettingsBuilder(httpClient, platformSupport, serviceHostResolver)
.AddDefaultPkceAuthenticator(playerSettings)
.Build();
Authenticator = new CompositeAuthenticator(compositeAuthenticatorSettings);
var serviceHttpClient = new ServiceHttpClient(httpClient, Authenticator, playerSettings);
OrganizationProvider = new CloudOrganizationProvider(serviceHttpClient, serviceHostResolver);
ProjectProvider = new CloudProjectProvider(serviceHttpClient, serviceHostResolver);
AssetManager = new CloudAssetManager(serviceHttpClient, serviceHostResolver);
AssetFileManager = new CloudAssetFileManager(serviceHttpClient, serviceHostResolver);
AssetCollectionManager = new CloudAssetCollectionManager(serviceHttpClient, serviceHostResolver);
}
/// <summary>
/// A Task that initializes all platform services.
/// </summary>
/// <returns>A Task.</returns>
public static async Task InitializeAsync()
{
await Authenticator.InitializeAsync();
}
/// <summary>
/// Shuts down all platform services.
/// </summary>
public static void ShutDownServices()
{
(Authenticator as IDisposable)?.Dispose();
Authenticator = null;
}
}
What this script accomplishes:
- Initializes an
IAuthenticator
for logging in and verifying your identity when accessing the HTTP services. - Initializes an
IOrganizationProvider
to fetch the organizations you belong to. - Initializes an
IProjectProvider
to fetch the projects you have access to. - Initializes an
IAssetManager
to fetch and manage your assets; also acts as anIAssetProvider
.
To initialize the PlatformServices
in your scene, follow these steps:
- In your Unity project window, go to Assets > Scripts.
- Right-click the
Assets/Scripts
folder and go to Create > C# Script. Name your scriptPlatformServicesInitialization
. - In the
AssetManagementExample
scene you created earlier, right-click the hierarchy and select Create Empty. - Name your new object
PlatformServices
. - Select the
PlatformServices
object and add thePlatformServicesInitialization
script you created earlier. - Update the
PlatformServicesInitialization
class in yourPlatformServicesInitialization.cs
file to look like the following:
using System.Threading.Tasks;
using UnityEngine;
/// <summary>
/// A Mono behaviour class to initialize services and dependencies for the Unity Cloud platform.
/// </summary>
[DefaultExecutionOrder(int.MinValue)]
[AddComponentMenu("Assets/Manual/Management/Platform Services Initialization")]
public class PlatformServicesInitialization : MonoBehaviour
{
void Awake()
{
DontDestroyOnLoad(gameObject);
PlatformServices.Create();
}
async Task Start()
{
await PlatformServices.InitializeAsync();
}
}
What this script accomplishes:
- Triggers the creation of the services available in the
PlatformServices
. - Initializes the
IAuthenticator
.
To clean up the PlatformServices
in your scene, follow these steps:
- In your Unity project window, go to Assets > Scripts.
- Right-click the
Assets/Scripts
folder and go to Create > C# Script. Name your scriptPlatformServicesShutdown
. - Select the
PlatformServices
object you created earlier and add thePlatformServicesShutdown
script you created earlier. - Update the
PlatformServicesShutdown
class in yourPlatformServicesShutdown.cs
file to look like the following:
using UnityEngine;
/// <summary>
/// A Mono behaviour class to shut down services and dependencies from the Unity Cloud platform.
/// </summary>
[DefaultExecutionOrder(int.MaxValue)]
[AddComponentMenu("Assets/Manual/Management/Platform Services Shutdown")]
public class PlatformServicesShutdown : MonoBehaviour
{
void OnDestroy()
{
PlatformServices.ShutDownServices();
}
}
This script cleans up of the services when the scene is closed.
Create the behaviour for managing assets
To create the behaviour for asset management, perform the following steps:
- In your Unity project window, go to Assets > Scripts.
- Right-click the
Assets/Scripts
folder and go to Create > C# Script. Name your scriptAssetManagementBehaviour
. - Open the
AssetManagementBehaviour
script you created and replace the contents of the file with the following code sample:
using System;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
public class AssetManagementBehaviour
{
static readonly Pagination m_DefaultPagination = new(nameof(IAsset.Name), 25);
const int k_DefaultCancellationTimeout = 5000;
IOrganization[] m_AvailableOrganizations;
IOrganization m_CurrentOrganization;
IProjectPage m_AvailableProjects;
IProject m_CurrentProject;
IAssetPage m_AvailableAssets;
public IOrganization[] AvailableOrganizations => m_AvailableOrganizations;
public IOrganization CurrentOrganization => m_CurrentOrganization;
public bool IsOrganizationSelected => m_CurrentOrganization != null;
public IProjectPage AvailableProjects => m_AvailableProjects;
public IProject CurrentProject => m_CurrentProject;
public bool IsProjectSelected => m_CurrentProject != null;
public IAssetPage AvailableAssets => m_AvailableAssets;
public IAsset CurrentAsset { get; set; }
public void Clear()
{
m_CurrentProject = null;
m_AvailableProjects = null;
m_CurrentOrganization = null;
}
public void SetSelectedOrganization(IOrganization organization)
{
m_CurrentOrganization = organization;
if (m_CurrentOrganization != null)
{
_ = GetProjectsAsync();
}
}
public void SetSelectedProject(IProject project)
{
m_CurrentProject = project;
if (m_CurrentProject != null)
{
_ = GetAssetsAsync();
}
}
public async Task GetOrganizationsAsync()
{
m_AvailableOrganizations = null;
try
{
var cancellationTokenSrc = new CancellationTokenSource();
m_AvailableOrganizations = await PlatformServices.OrganizationProvider.GetOrganizationsAsync(cancellationTokenSrc.Token);
}
catch (OperationCanceledException oe)
{
Debug.LogError(oe);
}
catch (AggregateException e)
{
Debug.LogError(e.InnerException);
}
catch (Exception e)
{
Debug.LogError(e);
}
}
public async Task GetProjectsAsync()
{
m_AvailableProjects = null;
try
{
var cancellationTokenSrc = new CancellationTokenSource();
m_AvailableProjects = await PlatformServices.ProjectProvider.GetCurrentUserProjectList(m_CurrentOrganization, m_DefaultPagination, cancellationTokenSrc.Token);
}
catch (OperationCanceledException oe)
{
Debug.LogError(oe);
}
catch (AggregateException e)
{
Debug.LogError(e.InnerException);
}
catch (Exception e)
{
Debug.LogError(e);
}
}
public void GetPreviousProjects()
{
m_AvailableProjects = m_AvailableProjects?.PreviousPage as IProjectPage;
}
public Task GetNextAvailableProjectsAsync()
{
return Task.CompletedTask;
}
public void GetPreviousAssets()
{
m_AvailableAssets = m_AvailableAssets?.PreviousPage as IAssetPage;
}
public Task GetNextAvailableAssetsAsync()
{
return Task.CompletedTask;
}
public async Task CreateAssetAsync()
{
var assetCreation = new AssetCreation
{
Organization = m_CurrentOrganization,
Project = m_CurrentProject,
Name = "GrayTexture_0",
Description = $"Documentation example asset creation.",
Type = nameof(Texture2D),
Version = 1,
VersionName = "1.0.0"
};
var cancellationTokenSrc = new CancellationTokenSource(k_DefaultCancellationTimeout);
try
{
var asset = await PlatformServices.AssetManager.CreateAssetAsync(assetCreation, cancellationTokenSrc.Token);
if (asset != null)
{
// Refresh available assets
await GetAssetsAsync();
// Set created asset as current asset
CurrentAsset = asset;
}
}
catch (Exception e)
{
Debug.LogError($"Failed to create asset. {e.Message}");
throw;
}
}
public async Task UpdateAssetAsync(IAsset asset)
{
try
{
var cancellationTokenSrc = new CancellationTokenSource(k_DefaultCancellationTimeout);
await PlatformServices.AssetManager.UpdateAssetAsync(asset, cancellationTokenSrc.Token);
}
catch (OperationCanceledException oe)
{
Debug.LogError(oe);
}
catch (AggregateException e)
{
Debug.LogError(e.InnerException);
}
catch (Exception e)
{
Debug.LogError(e);
}
}
public async Task DeleteAssetAsync(IAsset asset)
{
try
{
var cancellationTokenSrc = new CancellationTokenSource(k_DefaultCancellationTimeout);
await PlatformServices.AssetManager.DeleteAssetAsync(asset, cancellationTokenSrc.Token);
// Refresh available assets
await GetAssetsAsync();
// Reset current asset
CurrentAsset = null;
}
catch (OperationCanceledException oe)
{
Debug.LogError(oe);
}
catch (AggregateException e)
{
Debug.LogError(e.InnerException);
}
catch (Exception e)
{
Debug.LogError(e);
}
}
async Task GetAssetsAsync()
{
m_AvailableAssets = null;
CurrentAsset = null;
try
{
var cancellationTokenSrc = new CancellationTokenSource(k_DefaultCancellationTimeout);
m_AvailableAssets = await PlatformServices.AssetManager.SearchAsync(new AssetSearchFilter(m_CurrentOrganization, m_CurrentProject), m_DefaultPagination, cancellationTokenSrc.Token);
}
catch (OperationCanceledException oe)
{
Debug.LogError(oe);
}
catch (AggregateException e)
{
Debug.LogError(e.InnerException);
}
catch (Exception e)
{
Debug.LogError(e);
}
}
}
The script does the following:
- Provides the functions to list and select organizations.
- Provides the functions to list and select projects.
- Performs a basic search to list the assets of the selected project.
- Provides the functions to create, read, update, delete assets.
Create the UI for navigating assets
To create a simple UI for navigating assets, do the following:
Open the AssetManagementUI
script you created earlier and replace the contents of the file with the following code sample:
using System;
using Unity.Cloud.Identity;
using UnityEditor;
using UnityEngine;
public class AssetManagementUI : MonoBehaviour
{
protected readonly AssetManagementBehaviour m_Behaviour = new();
IAuthenticationStateProvider m_AuthenticationStateProvider;
bool IsLoggedIn => m_AuthenticationStateProvider?.AuthenticationState == AuthenticationState.LoggedIn;
void Start()
{
m_AuthenticationStateProvider = PlatformServices.AuthenticationStateProvider;
m_AuthenticationStateProvider.AuthenticationStateChanged += OnAuthenticationStateChanged;
}
void OnDestroy()
{
if (m_AuthenticationStateProvider != null)
{
m_AuthenticationStateProvider.AuthenticationStateChanged -= OnAuthenticationStateChanged;
}
}
void OnGUI()
{
GUILayout.BeginHorizontal();
UpdateAuthenticationUI(m_AuthenticationStateProvider.AuthenticationState);
if (!IsLoggedIn)
{
GUILayout.EndHorizontal();
return;
}
if (!m_Behaviour.IsOrganizationSelected)
{
// Refresh the org list
if (GUILayout.Button("Refresh"))
{
_ = m_Behaviour.GetOrganizationsAsync();
return;
}
GUILayout.Space(50);
// If an organization is not selected, list those available.
SelectAnOrganization();
}
else if (!m_Behaviour.IsProjectSelected)
{
GUILayout.BeginVertical();
// Go back to select a different scene.
if (GUILayout.Button("Back"))
{
m_Behaviour.SetSelectedOrganization(null);
return;
}
// Refresh the org list
if (GUILayout.Button("Refresh"))
{
_ = m_Behaviour.GetProjectsAsync();
return;
}
GUILayout.EndVertical();
GUILayout.Space(50);
SelectAProject();
}
else
{
// Go back to select a different scene.
if (GUILayout.Button("Back"))
{
m_Behaviour.SetSelectedProject(null);
return;
}
GUILayout.Space(50);
GUILayout.BeginVertical();
GUILayout.Label($"{m_Behaviour.CurrentOrganization.Name} >> {m_Behaviour.CurrentProject.Name}");
GUILayout.Space(10f);
SelectAnAsset();
GUILayout.Space(5f);
ProjectActions();
GUILayout.EndVertical();
GUILayout.Space(50);
AssetActions();
}
GUILayout.EndHorizontal();
}
protected virtual void ProjectActions()
{
// Add additional project related actions here.
}
protected virtual void AssetActions()
{
ManageAnAsset();
// Add additional asset related actions here.
}
void SelectAnOrganization()
{
GUILayout.BeginVertical();
GUILayout.Label("Available Organizations:");
GUILayout.Space(10);
var availableOrganizations = m_Behaviour.AvailableOrganizations;
if (availableOrganizations != null)
{
for (var i = 0; i < availableOrganizations.Length; ++i)
{
if (GUILayout.Button(availableOrganizations[i].Name))
{
m_Behaviour.SetSelectedOrganization(availableOrganizations[i]);
}
}
}
else
{
GUILayout.Label("Loading...");
}
GUILayout.EndVertical();
}
void SelectAProject()
{
GUILayout.BeginVertical();
GUILayout.Label($"{m_Behaviour.CurrentOrganization.Name}");
GUILayout.Space(10);
GUILayout.Label("Available Projects:");
GUILayout.Space(10);
var projectPage = m_Behaviour.AvailableProjects;
if (projectPage != null)
{
var projects = projectPage.Elements;
for (var i = 0; i < projects.Length; ++i)
{
if (GUILayout.Button(projects[i].Name))
{
m_Behaviour.SetSelectedProject(projects[i]);
}
}
GUILayout.BeginHorizontal();
EditorGUI.BeginDisabledGroup(projectPage.PreviousPage == null);
// Go back to select a different scene.
if (GUILayout.Button("Previous Page"))
{
m_Behaviour.GetPreviousProjects();
}
EditorGUI.EndDisabledGroup();
EditorGUI.BeginDisabledGroup(string.IsNullOrEmpty(projectPage.NextPageToken));
// Go back to select a different scene.
if (GUILayout.Button("Next Page"))
{
_ = m_Behaviour.GetNextAvailableProjectsAsync();
}
EditorGUI.EndDisabledGroup();
GUILayout.EndHorizontal();
}
else
{
GUILayout.Label("Loading...");
}
GUILayout.EndVertical();
}
void SelectAnAsset()
{
GUILayout.BeginVertical(EditorStyles.helpBox);
GUILayout.Label("Available Assets:");
GUILayout.Space(10);
var assetPage = m_Behaviour.AvailableAssets;
if (assetPage != null)
{
var assets = assetPage.Elements;
for (var i = 0; i < assets.Length; ++i)
{
if (GUILayout.Button(assets[i].Name))
{
m_Behaviour.CurrentAsset = assets[i];
Debug.Log($"Selected: {assets[i].Name}");
}
}
GUILayout.BeginHorizontal();
EditorGUI.BeginDisabledGroup(assetPage.PreviousPage == null);
// Go back to select a different scene.
if (GUILayout.Button("Previous Page"))
{
m_Behaviour.GetPreviousAssets();
}
EditorGUI.EndDisabledGroup();
EditorGUI.BeginDisabledGroup(string.IsNullOrEmpty(assetPage.NextPageToken));
// Go back to select a different scene.
if (GUILayout.Button("Next Page"))
{
_ = m_Behaviour.GetNextAvailableAssetsAsync();
}
EditorGUI.EndDisabledGroup();
GUILayout.EndHorizontal();
}
else
{
GUILayout.Label("Loading...");
}
GUILayout.EndVertical();
}
static void UpdateAuthenticationUI(AuthenticationState state)
{
GUILayout.BeginVertical();
switch (state)
{
case AuthenticationState.AwaitingInitialization:
GUILayout.Label("Initializing Service...");
break;
case AuthenticationState.AwaitingLogout:
GUILayout.Label("Logging out...");
break;
case AuthenticationState.LoggedOut:
if (GUILayout.Button("Login"))
{
_ = PlatformServices.Authenticator.LoginAsync();
}
break;
case AuthenticationState.AwaitingLogin:
GUILayout.Label("Logging in...");
if (GUILayout.Button("Cancel"))
{
PlatformServices.Authenticator.CancelLogin();
}
break;
case AuthenticationState.LoggedIn:
if (GUILayout.Button("Logout"))
{
_ = PlatformServices.Authenticator.LogoutAsync();
}
break;
default:
throw new ArgumentOutOfRangeException(nameof(state), state, null);
}
GUILayout.EndVertical();
}
void OnAuthenticationStateChanged(AuthenticationState obj)
{
if (obj == AuthenticationState.LoggedIn)
{
_ = m_Behaviour.GetOrganizationsAsync();
}
}
void ManageAnAsset()
{
GUILayout.BeginVertical();
GUILayout.Label("Manage:");
GUILayout.Space(10);
if (GUILayout.Button("Create new asset", GUILayout.Width(150f)))
{
_ = m_Behaviour.CreateAssetAsync();
}
GUILayout.Space(5f);
if (m_Behaviour.CurrentAsset == null)
{
GUILayout.Label(" ! No asset selected !");
}
else
{
GUILayout.Label("Asset selected:");
GUILayout.Space(5f);
DisplayAsset(m_Behaviour.CurrentAsset);
}
GUILayout.EndVertical();
}
protected virtual void DisplayAsset(IAsset asset)
{
GUILayout.BeginHorizontal();
var nameValue = GUILayout.TextField(asset.Name, GUILayout.Width(100f));
if(nameValue != asset.Name)
{
asset.Name = nameValue;
}
GUILayout.Space(5f);
var versionNameValue = GUILayout.TextField(asset.VersionName, GUILayout.Width(50f));
if(versionNameValue != asset.VersionName)
{
asset.VersionName = versionNameValue;
}
GUILayout.Space(5f);
GUILayout.Label(asset.Status);
GUILayout.Space(5f);
if (GUILayout.Button("Update"))
{
_ = m_Behaviour.UpdateAssetAsync(asset);
}
GUILayout.Space(5f);
if (GUILayout.Button("Delete"))
{
_ = m_Behaviour.DeleteAssetAsync(asset);
}
GUILayout.Space(5f);
GUILayout.EndHorizontal();
}
}
The script does the following:
- Registers to the
IAuthenticator
to track login changes. - Creates an instance of an
AssetManagementBehaviour
. - Creates a simple UI flow for selecting organizations, projects and do CRUD operations on assets.