Unity User-Generated Content Quick Start Guide
Welcome to Unity User-Generated Content (UGC)!
UGC is a format and content-agnostic that helps you incorporate user-generated content features into your game, no matter your implementation. You can write your content creation edition tools while UGC handles content storage, discovery, ingestion, moderation, and ratings.
Use this quick start guide to:
- Onboard your Unity project with UGC.
- Set up the UGC Unity Package.
- Integrate UGC into your project.
Before we start, it's helpful to understand the two types of UGC users:
- The player
- The content creator
A player can browse, rate, report, and play published content. A content creator (creator) is a type of player that can do everything a player can plus create, update, and delete their content.
The simplest way to handle content is to use the same format for what the creator "writes" and the game "reads" when a player wants to play that content.
However, there are use cases where you will want a distinct format for "edit-time" content versus "play-time" content, for example, a platform-specific version of the content for each platform your game supports. By adding one or more representations to the content, you can create one or more such version, each with its specific format and tags.
Thank you for testing this version of our product. We encourage you to provide feedback to help us improve it.
Enable UGC in Unity Dashboard
- Log in to the Unity Dashboard.
- Navigate to your project, then select Live Ops > User Generated Content > Overview.
- Select Enable UGC.
- Note: Contact us if you don't have the option to Enable UGC.
Complete the form by providing the Project Name, Project Description, Project Threshold, and Review Rule. You can also add an image for the project.
Project Name - A name that identifies the project.
- Project Description - A brief description of the project.
- Project Threshold - A moderation setting that determines how many players must report a content entry as inappropriate before it is unpublished and moderated.
- Select Submit.
📝 Note You must enable UGC through the settings to make your project visible to the SDK. Go to User Generated Content > Settings, then enable User Generated Content.
Install Unity UGC Package
The UGC Package is available as a tarball archive. See Installing a package from a local tarball file to learn how to add a tarball package to your Unity Project.
📝 Note Like other Unity Gaming Services, you must link your project to your Unity Account through the Unity Dashboard before using the UGC SDK. See Enable UGC in the Unity Dashboard.
Integrate with the UGC SDK
The following code samples show how to perform various tasks with the UGC SDK:
- Authenticate a player
- Create and modify content
- Retrieve content
- Manage player content subscriptions
- Create and modify representation
- Retrieve representation
- Moderation
Authenticate a player
In most cases, you will want a content creator to log in before they can submit content to your project. Authenticating content creators has multiple benefits:
- It allows creators to edit their content to fix or improve it.
- It prevents creators from editing content that isn't theirs.
- It helps you reward or sanction creators for their content.
You can authenticate players, including creators, using any supported Unity Authentication identity providers. If it is your first time using the UGC package and you don't want to start implementing the identity providers, you can authenticate your users anonymously.
public async Task SignInAnonymouslyAsync()
{
try
{
await AuthenticationService.Instance.SignInAnonymouslyAsync();
Debug.Log("Sign in anonymously succeeded!");
// Shows how to get the playerID
Debug.Log($"PlayerID: {AuthenticationService.Instance.PlayerId}");
}
catch (AuthenticationException ex)
{
// Compare error code to AuthenticationErrorCodes
// Notify the player with the proper error message
Debug.LogException(ex);
}
catch (RequestFailedException ex)
{
// Compare error code to CommonErrorCodes
// Notify the player with the proper error message
Debug.LogException(ex);
}
}
Here's an authentication example using Apple ID as the identity provider.
public async Task SignInWithAppleAsync(string idToken)
{
try
{
await AuthenticationService.Instance.SignInWithAppleAsync(idToken);
Debug.Log("SignIn is successful.");
}
catch (AuthenticationException ex)
{
// Compare error code to AuthenticationErrorCodes
// Notify the player with the proper error message
Debug.LogException(ex);
}
catch (RequestFailedException ex)
{
// Compare error code to CommonErrorCodes
// Notify the player with the proper error message
Debug.LogException(ex);
}
}
📝 Tip See the Unity Authentication documentation to learn more.
Create and modify content
Create content
After the creator logs in and is ready to publish their content, the game can upload it.
public async Task<Content> CreateNewContentAsync()
{
using var contentStream = File.Open("<path-to-content-file>", FileMode.Open, FileAccess.Read, FileShare.Read);
using var thumbnailStream = File.Open("<path-to-the-image-representation-of-the-content>", FileMode.Open, FileAccess.Read, FileShare.Read);
var content = await UgcService.Instance.CreateContentAsync(new CreateContentArgs("A new content", "A description", contentStream) { IsPublic = true, TagsId = null, Thumbnail = thumbnailStream});
Debug.Log($"Created content with id: {content.Id}.");
return content;
}
Content creators can have a thumbnail image of content before they create content. However, if they don't have a thumbnail ready, they have a couple of options:
- Use a placeholder image and update it later.
- Generate a screenshot of the content asset to use as the thumbnail.
- Leave it empty.
Use ScreenCapture.CaptureScreenshot
(ScreenCapture) to generate a screenshot of the content asset to use as the thumbnail.
📝 Tip Move the camera in the scene view to align the game view with the asset before calling ScreenCapture.CaptureScreenshot.
Update content
Creators can update published content they created by creating a new version for that content.
📝 Note You must authenticate content creators before allowing them to update or delete their content. See Authenticate a player.
public async Task<Content> CreateContentVersionAsync(string contentId)
{
using var contentStream = File.Open("<path-to-content-file>", FileMode.Open, FileAccess.Read, FileShare.Read);
using var thumbnailStream = File.Open("<path-to-the-image-representation-of-the-content>", FileMode.Open, FileAccess.Read, FileShare.Read);
var content = await UgcService.Instance.CreateContentVersionAsync(contentId, contentStream, thumbnailStream);
Debug.Log($"Updated the following content: {content.Id} version: {content.Version}.");
return content;
}
Delete content
Creators can delete content they created.
📝 Note You must authenticate content creators before allowing them to update or delete their content. See Authenticate a player.
public async void DeleteContentAsync(string contentId)
{
await UgcService.Instance.DeleteContentAsync(contentId);
Debug.Log($"Deleted content with id: {contentId}.");
}
Update content metadata
Creators can update their content's metadata without uploading new code (binaries).
📝 Note You must authenticate content creators before allowing them to update or delete their content. See Authenticate a player.
public async Task<Content> UpdateContentDetailsAsync(string contentId)
{
var metadata = new UpdateContentDetailsArgs(contentId, "a new title", "A another new description!", true, new List<string>() { "Art" });
var content = await UgcService.Instance.UpdateContentDetailsAsync(metadata);
Debug.Log($"Updated the following content details: {content.Id} version: {content.Version}.");
return content;
}
Retrieve content
📝 Note Most methods in the UGC SDK use a
Content
class to transport the metadata of a content entity.
Players, including content creators, can search for content by calling GetContentsAsync
. It allows players to filter content by text and tags and sort results by various properties.
📝 Note Players only see published content, and content creators see published and unpublished content they created. Unity Cloud Project Owners can view, update, and delete any content.
Retrieve a list of content
Use GetContentsAsync
to get a list of content without filters.
public async Task<List<Content>> GetContentsListAsync()
{
var contents = await UgcService.Instance.GetContentsAsync(new GetContentsArgs());
Debug.Log("The following contents were retrieved:");
foreach (var content in contents.Results)
{
Debug.Log(content.Id);
}
return contents.Results;
}
Retrieve a list of the player's content
Use GetPlayerContentsAsync
to get a list of the player's content without filters.
public async Task<List<Content>> GetPlayerContentAsync()
{
var contents = await UgcService.Instance.GetPlayerContentsAsync(new GetPlayerContentsArgs());
Debug.Log("The following contents were retrieved:");
foreach (var content in contents.Results)
{
Debug.Log(content.Id);
}
return contents.Results;
}
Page through results
You can page through paginated content, such as Content
and Subscription
. Most methods that return a list of items are paginated. You can set the page and the page size using the Offset
and Limit
properties of the Get[ItemType]Args
.
public async Task<List<Content>> GetContentsListByPageAsync(int pageIndex, int contentPerPage)
{
var offset = pageIndex * contentPerPage;
var limit = (pageIndex + 1) * contentPerPage;
var getContentsArgs = new GetContentsArgs()
{
Offset = offset,
Limit = limit
};
var contents = await UgcService.Instance.GetContentsAsync(getContentsArgs);
Debug.Log("The following contents were retrieved:");
foreach (var content in contents.Results)
{
Debug.Log(content.Id);
}
return contents.Results;
}
Search content
You can filter and sort lists of content by calling GetContentsAsync
and setting the appropriate GetContentsArgs
properties.
public async Task<List<Content>> GetContentsListBySearchAsync(string searchFilter)
{
var getContentsArgs = new GetContentsArgs()
{
Search = searchFilter
};
var contents = await UgcService.Instance.GetContentsAsync(getContentsArgs);
Debug.Log("The following contents were retrieved:");
foreach (var content in contents.Results)
{
Debug.Log(content.Id);
}
return contents.Results;
}
Search content with content report type.
You can get a specialized content list by calling GetContentsAsync
with a ReportType
set to any property value of ContentReportType
.
📝 Tip You can mix and match
ReportType
and any otherGetContentsArgs
properties.
public async Task<List<Content>> GetContentsListBySearchWithReportAsync(string searchFilter)
{
var getContentsArgs = new GetContentsArgs()
{
Search = searchFilter
};
var contents = await UgcService.Instance.GetContentsAsync(getContentsArgs);
Debug.Log("The following contents were retrieved:");
foreach (var content in contents.Results)
{
Debug.Log(content.Id);
}
return contents.Results;
}
Get specific content
You can get content with or without its binary data (details).
public async Task<Content> GetContentByIdAsync(string contentId)
{
var content = await UgcService.Instance.GetContentAsync(new GetContentArgs(contentId) { DownloadContent = true, DownloadThumbnail = true});
Debug.Log($"Retrieved content with id: {content.Id}.");
return content;
}
You can retrieve content by its ID (Content.Id
). If you don't know the ID of the content, you can try to retrieve the ID by getting all the contents and comparing it to other parameters, like the name.
public async Task<string> GetContentIdAsync(string name)
{
var contents = await UgcService.Instance.GetContentsAsync(new GetContentsArgs());
var contentId = "";
foreach (var content in contents.Results)
{
if (content.Name == name)
{
contentId = content.Id;
break;
}
}
if (!string.IsNullOrEmpty(contentId))
{
Debug.Log($"Content id retrieved for {name}: {contentId}");
}
return contentId;
}
Display the thumbnail as a sprite
If you are listing the retrieved content, you might want to show the thumbnail to your players. To convert the bytes array of the content thumbnail you receive to a sprite, you can use Texture2D.LoadImage()
and then create a sprite asset from it.
public Sprite ConvertContentThumbnailToSprite(Content content)
{
var downloadedTexture = new Texture2D(2, 2);
downloadedTexture.LoadImage(content.DownloadedThumbnail);
var sprite = Sprite.Create(
texture: downloadedTexture,
rect: new Rect(0.0f, 0.0f, downloadedTexture.width, downloadedTexture.height),
pivot: new Vector2(0.5f, 0.5f),
pixelsPerUnit: 100.0f);
return sprite;
}
Manage player content subscriptions
Get all tags
Use GetTagsAsync to get your project's tags.
📝 Note Tags are simple strings generated alongside a GUID to ensure uniqueness. You can associate content with specific tags to allow for quick searching.
public async Task<List<Tag>> GetTagsListAsync()
{
var tags = await UgcService.Instance.GetTagsAsync();
Debug.Log("The following tags were retrieved:");
foreach (var tag in tags)
{
Debug.Log(tag);
}
return tags;
}
Subscribe to content
Players can subscribe to content. It's up to you to decide what you do with this information. For example, you could notify them whenever a creator the player is subscribed to publishes a newer version.
public async void SubscribeToContentAsync(string contentId)
{
await UgcService.Instance.CreateSubscriptionAsync(contentId);
Debug.Log($"Subscribed to the following content: {contentId}.");
}
Get subscribed contents list
Players can retrieve a list of content they have subscribed to.
public async Task<List<Subscription>> GetSubscribedContentListAsync()
{
var subscriptions = await UgcService.Instance.GetSubscriptionsAsync(new GetSubscriptionsArgs());
Debug.Log("Player is subscribed to the following contents:");
foreach (var subscription in subscriptions.Results)
{
Debug.Log(subscription.Content.Id);
}
return subscriptions.Results;
}
Unsubscribe from content
Players can unsubscribe from content.
public async void UnsubscribeFromContentAsync(string contentId)
{
await UgcService.Instance.DeleteSubscriptionAsync(contentId);
Debug.Log($"Unsubscribed from the following content: {contentId}.");
}
Rate content
Players can rate published content—valid values for ratings range from 1.0f to 5.0f.
public async void SubmitUserContentRatingAsync(string contentId, float rating)
{
await UgcService.Instance.SubmitUserContentRatingAsync(contentId, rating);
Debug.Log($"The following content was rated: {contentId} {rating}/5.");
}
Create and modify representation
Create representation
Creators can create representations for the content they created.
public async Task<Representation> CreateNewRepresentationAsync(Content content)
{
var tags = new List<string>() { "example" };
var representation = await UgcService.Instance.CreateRepresentationAsync(new CreateRepresentationArgs(content.Id, tags));
Debug.Log($"Created representation with id: {representation.Id}.");
return representation;
}
Create representation version
Creators can create new representation version for the content they created.
public async Task<RepresentationVersion> CreateNewRepresentationVersionAsync(Content content, Representation representation)
{
using var contentStream = File.Open("<path-to-content-file>", FileMode.Open, FileAccess.Read, FileShare.Read);
var representationVersion = await UgcService.Instance.CreateRepresentationVersionAsync(content.Id, representation.Id, contentStream);
Debug.Log($"Created representation version with id: {representationVersion.Id}.");
return representationVersion;
}
Update representation
Creators can update published representation they created.
📝 Note You must authenticate content creators before allowing them to update or delete their content. See Authenticate a player.
public async Task<Representation> UpdateRepresentationAsync(Content content, Representation representation)
{
using var contentStream = File.Open("<path-to-content-file>", FileMode.Open, FileAccess.Read, FileShare.Read);
var representationVersion = await UgcService.Instance.CreateRepresentationVersionAsync(content.Id, representation.Id, contentStream);
Debug.Log($"Created representation version with id: {representationVersion.Id}.");
var tags = new List<string>() { "example" };
var newRepresentation = await UgcService.Instance.UpdateRepresentationAsync(new UpdateRepresentationArgs(content.Id, representation.Id, tags, representationVersion.Id));
Debug.Log($"Updated representation version with id: {newRepresentation.Id}.");
return newRepresentation;
}
Delete representation
Creators can delete representation they created.
📝 Note You must authenticate content creators before allowing them to update or delete their content. See Authenticate a player.
public async void DeleteRepresentationAsync(string contentId, string representationId)
{
await UgcService.Instance.DeleteRepresentationAsync(new DeleteRepresentationArgs(contentId, representationId));
Debug.Log($"Deleted representation with id: {representationId}.");
}
Retrieve representation
📝 Note Most methods in the UGC SDK use a
Representation
andRepresentationVersion
class to transport the metadata of a representation/representationVersion entity.
Retrieve a list of representation
Use GetRepresentationsAsync
to get all representations of a content.
public async Task<List<Representation>> GetRepresentationsListAsync(string contentId)
{
var representations = await UgcService.Instance.GetRepresentationsAsync(new GetRepresentationsArgs(contentId));
Debug.Log("The following representations were retrieved:");
foreach (var representation in representations.Results)
{
Debug.Log(representation.Id);
}
return representations.Results;
}
Retrieve a list of representation version
Use GetRepresentationVersionsAsync
to get a list of representation versions.
public async Task<List<RepresentationVersion>> GetRepresentationVersionsListAsync(string contentId, string representationId)
{
var representationVersions = await UgcService.Instance.GetRepresentationVersionsAsync(new GetRepresentationVersionsArgs(contentId, representationId));
Debug.Log("The following representation versions were retrieved:");
foreach (var representationVersion in representationVersions.Results)
{
Debug.Log(representationVersion.Id);
}
return representationVersions.Results;
}
Search representation within project
With SearchRepresentationsAsync
you can search representations from any content within the current project.
public async Task<List<Representation>> SearchRepresentationsInProjectAsync(string searchFilter)
{
var searchRepresentationsArgs = new SearchRepresentationsArgs(searchFilter);
var representations = await UgcService.Instance.SearchRepresentationsAsync(searchRepresentationsArgs);
Debug.Log("The following representations were retrieved:");
foreach (var representation in representations.Results)
{
Debug.Log(representation.Id);
}
return representations.Results;
}
Get specific representation
You can get representation with or without its binary data (details).
public async Task<Representation> GetRepresentationByIdAsync(string contentId, string representationId)
{
var representation = await UgcService.Instance.GetRepresentationAsync(new GetRepresentationArgs(contentId, representationId) { DownloadRepresentation = true });
Debug.Log($"Retrieved representation with id: {representation.Id}.");
return representation;
}
Moderation
Report inappropriate content
Players can report inappropriate content. You, as the developer, or the community, can set guidelines for what determines the appropriateness of content. Each time a unique player reports content as inappropriate, it increments a report counter specific to that content. As the developer, you must set a threshold for content reports. After an instance of content goes over your project's report threshold, you can hide it until you review it. During the review, you can decide whether to republish it or not.
public async void ReportContentAsync(string contentId)
{
var result = await UgcService.Instance.ReportContentAsync(new ReportContentArgs(contentId, Reason.NonFunctional));
Debug.Log($"The following content was reported: {result.Id}.");
}
Approve content
A player with moderation rights is able to approve a content marked for moderation. The content would then be available publicly.
public async void ApproveContentAsync(string contentId)
{
var result = await UgcService.Instance.ApproveContentAsync(contentId);
Debug.Log($"The following content was approved: {result.Id}.");
}
Reject content
A player with moderation rights is able to reject a content marked for moderation. The content would then be hidden.
public async void RejectContentAsync(string contentId)
{
var result = await UgcService.Instance.RejectContentAsync(contentId);
Debug.Log($"The following content was rejected: {result.Id}.");
}
Search content waiting for moderation
A player with moderation rights is able to search all contents marked for moderation.
public async Task<List<Content>> SearchContentModerationAsync()
{
var contents = await UgcService.Instance.SearchContentModerationAsync(new SearchContentModerationArgs());
Debug.Log("The following contents were retrieved:");
foreach (var content in contents.Results)
{
Debug.Log(content.Id);
}
return contents.Results;
}
Glossary
The following list contains a list of glossary terms associated with the UGC service.
Player - A player is a user authenticated by the Unity Authentication Service.
Content creator - A content creator, also called a creator, is a player who creates content for the project. They can do everything a player can and have ownership of their content.
Tag - A tag is a developer-managed text label that creators can associate with their content, and its primary purpose is to help players find relevant content.
Content - Content refers to the user-generated content that creators contribute, composed of metadata and a binary.
Content entry - Content entry refers to a specific published content entry.
Binary - A binary, or content binary, is part of a user-generated content entry that represents the payload containing the playable part of the content.
Content metadata - Content metadata is part of a user-generated content entry that refers to all attributes describing the content, such as the title, description, last update date, and ratings.
Content thumbnail - A content thumbnail is a small picture representing a user-generated content entry the creator provides when they publish content. Ideally, the thumbnail should illustrate the content; however, it’s also possible for content creators to use a placeholder image as the thumbnail. The thumbnail makes it easy for players to identify a specific user-generated content entry when searching through the UGC User Portal or sharing content on social media.
Content rating - A content rating refers to the average rating of a user-generated content entry. Players can rate content and use content ratings to sort and filter content.
Content rate threshold - A content rate threshold is a moderation setting in the Unity Dashboard indicating how many players must report a content entry as inappropriate before it is unpublished and moderated.
Published content - Published content refers to content that players can search for, rate, report, and play.
Unpublished content - Unpublished content refers to content available only to its creator. Content creators can publish and unpublished content they created.
Subscribe - Subscribe refers to a player's action to subscribe to updates from a particular content entry. Players can also subscribe to content to demonstrate their interest in the content. Subscribing to content adds the content to the player’s subscription list.
Unsubscribe - Unsubscribe refers to a player's action to unsubscribe from a particular content entry’s updates. Players can also unsubscribe to indicate they’re no longer interested in the content. Unsubscribing from content removes the content from the player’s subscription list.
Subscription list - A subscription list contains all the content a player has subscribed to. You, as the developer, can use subscription lists to perform quality-of-life operations for the player, such as preloading content and notifying the player when new versions of content become available.
Content list - The content list contains all published content available to other players.