Part 1 - Choose your Workshop type
| Type | How it works | Good for |
|---|---|---|
| Ready-to-use | Items go live the moment a player uploads them. Subscribers get them automatically. | Levels, mods, blueprints. The default choice. |
| Curated | Players vote on submissions; you accept winners and typically integrate or sell them. | Official item pipelines, cosmetics with revenue share. |
Enable it under Steamworks → your app → Community → Workshop → General. Pick the type, write the visible description, set up tags so players can filter content (e.g. Maps, Mods, Skins).
Part 2 - Upload code (creating items)
Most games ship an in-game uploader. With Steamworks.NET the flow is create once, then push updates to the same item:
using Steamworks;
// 1. Create the item (once) - returns the published file id
SteamAPICall_t call = SteamUGC.CreateItem(
SteamUtils.GetAppID(), EWorkshopFileType.k_EWorkshopFileTypeCommunity);
// handle the CreateItemResult_t callback, store m_nPublishedFileId
// 2. Update content + metadata
UGCUpdateHandle_t h = SteamUGC.StartItemUpdate(SteamUtils.GetAppID(), publishedFileId);
SteamUGC.SetItemTitle(h, "My Cool Level");
SteamUGC.SetItemDescription(h, "A level I made.");
SteamUGC.SetItemContent(h, "C:/path/to/content/folder"); // whole folder is uploaded
SteamUGC.SetItemPreview(h, "C:/path/to/preview.png"); // shown in the Workshop UI
SteamUGC.SetItemVisibility(h, ERemoteStoragePublishedFileVisibility.k_ERemoteStoragePublishedFileVisibilityPublic);
SteamUGC.SubmitItemUpdate(h, "First upload");
Part 3 - Downloads (consuming items)
When a player subscribes on the Workshop page, Steam downloads the item in the background to steamapps/workshop/content/<your-app-id>/<item-id>/.
Use SteamUGC.GetSubscribedItems to list what the player has, SteamUGC.GetItemInstallInfo to get each item's folder, then load the content with your own loader. Listen for ItemInstalled_t to hot-load items subscribed while the game runs.
Workshop content is user input. Never execute arbitrary code from items unless modding is explicitly your design, and sanity-check file sizes and formats before loading.