Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by HakJak · Dec 09, 2016 at 01:34 AM · c#apiexamplewrapper

Steamworks.NET and Steam Workshop

Has anyone here implemented the Steamworks.NET wrapper and used it to upload/download items to Steam Workshop? I'm looking for a simple C# script example of how to do this, and even willing to pay money for help :D

To provide more context: I have a level editor that saves one .txt file for level info, and one image file for the level preview. I just need a C# Steamworks.NET script that will upload those files to the Workshop, and then find them when downloaded from Workshop.

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image HakJak · Dec 09, 2016 at 03:21 PM 0
Share

BU$$anonymous$$P

Really though... can anyone out there help me? Feels like I'm shouting for help in the dark here.

avatar image vitinho444 · Jan 01, 2017 at 09:32 PM 0
Share

Did you find anything?

1 Reply

· Add your reply
  • Sort: 
avatar image
7
Best Answer

Answer by vitinho444 · Jan 02, 2017 at 07:58 PM

So I came across your question and seems like nobody knows the answer. I tried to search on google everything I could and no answers either. Tried to directly ask developers, no answer either. So I made it myself.

The problem was that Steamworks.net calls workshop stuff on the RemoteStorage part.

How to use my script:

  1. Call the SaveToWorkshop function with the file details. This will upload the file to Steam cloud (I think it's mandatory (it will delete afterwards))

  2. Done. You can check the Workshop page, the item is there.

Now to download:

  1. Subscribe to the item you want to download.

  2. Call "GetSubscribedItems" function in my script.

  3. Call "GetItemContent(INDEX)" to download the contents of the INDEX item.

  4. Check the itemContent property on the script.

This script was made by me for my game AffordaGolf and it suits my needs, but each case is a case, so you might want to change some things.

Good luck!

Here's the script I'm using in my game:

 using UnityEngine;
 using System.Collections.Generic;
 using Steamworks;
 
 /// <summary>
 /// This class was created by Vitor Pêgas on 01/01/2017
 /// </summary>
 public class SteamWorkshop : MonoBehaviour {
     public static SteamWorkshop singleton;
     void Awake() { singleton = this; subscribedItemList = new List<PublishedFileId_t>(); }
     private CallResult<RemoteStoragePublishFileResult_t> RemoteStoragePublishFileResult;
     private CallResult<RemoteStorageEnumerateUserSubscribedFilesResult_t> RemoteStorageEnumerateUserSubscribedFilesResult;
     private CallResult<RemoteStorageGetPublishedFileDetailsResult_t> RemoteStorageGetPublishedFileDetailsResult;
     private CallResult<RemoteStorageDownloadUGCResult_t> RemoteStorageDownloadUGCResult;
     private CallResult<RemoteStorageUnsubscribePublishedFileResult_t> RemoteStorageUnsubscribePublishedFileResult;
 
     private PublishedFileId_t publishedFileID;
     private UGCHandle_t UGCHandle;
 
     public List<PublishedFileId_t> subscribedItemList;
 
     public bool fetchedContent;
     private string itemContent;
 
 
     private string lastFileName;
     void OnEnable()
     {
         RemoteStoragePublishFileResult = CallResult<RemoteStoragePublishFileResult_t>.Create(OnRemoteStoragePublishFileResult);
         RemoteStorageEnumerateUserSubscribedFilesResult = CallResult<RemoteStorageEnumerateUserSubscribedFilesResult_t>.Create(OnRemoteStorageEnumerateUserSubscribedFilesResult);
         RemoteStorageGetPublishedFileDetailsResult = CallResult<RemoteStorageGetPublishedFileDetailsResult_t>.Create(OnRemoteStorageGetPublishedFileDetailsResult);
         RemoteStorageDownloadUGCResult = CallResult<RemoteStorageDownloadUGCResult_t>.Create(OnRemoteStorageDownloadUGCResult);
         RemoteStorageUnsubscribePublishedFileResult = CallResult<RemoteStorageUnsubscribePublishedFileResult_t>.Create(OnRemoteStorageUnsubscribePublishedFileResult);
     }
 
     public string getContent()
     {
         return itemContent;
     }
 
     public void GetSubscribedItems()
     {
         SteamAPICall_t handle = SteamRemoteStorage.EnumerateUserSubscribedFiles(0);
         RemoteStorageEnumerateUserSubscribedFilesResult.Set(handle);
     }
 
     /// <summary>
     /// Gets the Item content (subscribed) to variable itemContent
     /// When done downloading, fetchedContent will be TRUE.
     /// </summary>
     /// <param name="ItemID"></param>
     public void GetItemContent(int ItemID)
     {
         fetchedContent = false;
         publishedFileID = subscribedItemList[ItemID];
 
         SteamAPICall_t handle = SteamRemoteStorage.GetPublishedFileDetails(publishedFileID, 0);
         RemoteStorageGetPublishedFileDetailsResult.Set(handle);
     }
 
     public void DeleteFile(string filename)
     {
         bool ret = SteamRemoteStorage.FileDelete(filename);
     }
 
     /// <summary>
     /// This functions saves a file to the workshop.
     /// Make sure file size doesn't pass the steamworks limit on your app settings.
     /// </summary>
     /// <param name="fileName">File Name (actual physical file) example: map.txt</param>
     /// <param name="fileData">File Data (actual file data)</param>
     /// <param name="workshopTitle">Workshop Item Title</param>
     /// <param name="workshopDescription">Workshop Item Description</param>
     /// <param name="tags">Tags</param>
     public void SaveToWorkshop(string fileName, string fileData, string workshopTitle, string workshopDescription, string[] tags)
     {
         lastFileName = fileName;
         bool fileExists = SteamRemoteStorage.FileExists(fileName);
 
         if(fileExists)
         {
             Debug.Log("A file already exists with that name!");
         }
         else
         {
             //Try to upload to Steam Cloud
             bool upload = UploadFile(fileName, fileData);
 
             if(!upload)
             {
                 Debug.Log("Upload failed!");
             }
             else
             {
                 UploadToWorkshop(fileName, workshopTitle, workshopDescription, tags);
             }
         }
     }
 
     private bool UploadFile(string fileName, string fileData)
     {
         byte[] Data = new byte[System.Text.Encoding.UTF8.GetByteCount(fileData)];
         System.Text.Encoding.UTF8.GetBytes(fileData, 0, fileData.Length, Data, 0);
         bool ret = SteamRemoteStorage.FileWrite(fileName, Data, Data.Length);
 
         return ret;
     }
 
     private void UploadToWorkshop(string fileName, string workshopTitle, string workshopDescription, string[] tags)
     {
         SteamAPICall_t handle = SteamRemoteStorage.PublishWorkshopFile(fileName, null, SteamUtils.GetAppID(), workshopTitle, workshopDescription, ERemoteStoragePublishedFileVisibility.k_ERemoteStoragePublishedFileVisibilityPublic, tags, EWorkshopFileType.k_EWorkshopFileTypeCommunity);
         RemoteStoragePublishFileResult.Set(handle);
     }
 
     public void Unsubscribe(PublishedFileId_t file)
     {
         SteamAPICall_t handle = SteamRemoteStorage.UnsubscribePublishedFile(file);
         RemoteStorageUnsubscribePublishedFileResult.Set(handle);
     }
 
 
     ///CallBacks
     ///
 
 
     void OnRemoteStorageUnsubscribePublishedFileResult(RemoteStorageUnsubscribePublishedFileResult_t pCallback, bool bIOFailure)
     {
         Debug.Log("[" + RemoteStorageUnsubscribePublishedFileResult_t.k_iCallback + " - RemoteStorageUnsubscribePublishedFileResult] - " + pCallback.m_eResult + " -- " + pCallback.m_nPublishedFileId);
     }
 
     void OnRemoteStoragePublishFileResult(RemoteStoragePublishFileResult_t pCallback, bool bIOFailure)
     {
         if (pCallback.m_eResult == EResult.k_EResultOK)
         {
             publishedFileID = pCallback.m_nPublishedFileId;
             DeleteFile(lastFileName);
         }
     }
 
     void OnRemoteStorageEnumerateUserSubscribedFilesResult(RemoteStorageEnumerateUserSubscribedFilesResult_t pCallback, bool bIOFailure)
     {
         subscribedItemList = new List<PublishedFileId_t>();
 
         for (int i = 0; i < pCallback.m_nTotalResultCount; i++)
         {
             PublishedFileId_t f = pCallback.m_rgPublishedFileId[i];
             Debug.Log(f);
             subscribedItemList.Add(f);
         }
     }
 
     void OnRemoteStorageGetPublishedFileDetailsResult(RemoteStorageGetPublishedFileDetailsResult_t pCallback, bool bIOFailure)
     {
         if (pCallback.m_eResult == EResult.k_EResultOK)
         {
             UGCHandle = pCallback.m_hFile;
             SteamAPICall_t handle = SteamRemoteStorage.UGCDownload(UGCHandle, 0);
             RemoteStorageDownloadUGCResult.Set(handle);
         }
     }
 
     void OnRemoteStorageDownloadUGCResult(RemoteStorageDownloadUGCResult_t pCallback, bool bIOFailure)
     {
         byte[] Data = new byte[pCallback.m_nSizeInBytes];
         int ret = SteamRemoteStorage.UGCRead(UGCHandle, Data, pCallback.m_nSizeInBytes, 0, EUGCReadAction.k_EUGCRead_Close);
 
         itemContent = System.Text.Encoding.UTF8.GetString(Data, 0, ret);
 
         fetchedContent = true;
         Debug.Log("content:" + itemContent);
     }
 }
 







Comment
Add comment · Show 25 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image HakJak · Jan 03, 2017 at 02:39 AM 0
Share

Thank you very much!!

I ended up giving up on getting an answer here and got it figured out elsewhere. But I'm sure others will find this helpful too.

Thanks again!

avatar image vitinho444 HakJak · Jan 03, 2017 at 09:43 AM 0
Share

Yeah no problem ;) I was almost giving up when I decided to just read every single line of code and see what it did, and I found it out.

Good luck ;)

avatar image Raive · Feb 01, 2017 at 03:03 PM 0
Share

@vitinho444 Awesome script!

I have a question:

Let's say I have something I have uploaded to Workshop already and I have since updated the content and wish to upload that to the same Workshop item, updating it to the latest version.

How would I go about that?

avatar image vitinho444 Raive · Feb 01, 2017 at 03:06 PM 0
Share

Very good question. Although my code doesn't cover, check out the S$$anonymous$$mworks.net example on RemoteStorage and UCG (or UGC i don't remember quite well) and there's the example of the option to update a already published workshop item with a new file.

Good luck :)

avatar image Select10 · Jun 20, 2017 at 09:17 PM 0
Share

Your code doesnt seem to work, the upload always fails

avatar image vitinho444 Select10 · Jun 20, 2017 at 09:57 PM 0
Share

Hm, well I assure you that that's an exact copy of the code I'm using on my game and it works. Check out the S$$anonymous$$mworks.NET Test and go to the remote storage part and check if it works there.

Good luck :)

avatar image Thial · Aug 12, 2017 at 06:06 PM 1
Share

After modifying the code a little bit I can publish zip files along with preview images without any problems. Although when it comes to the downloading part, the subscribed items are getting listed in the console and m-eResult == EResult.k_EresultO$$anonymous$$ and my special download directory is getting created afterwards but no files are getting downloaded. I changed UGCDownload to UGCDownloadToLocation and I'm 100% sure that my path is right but still nothing is downloading. Any ideas ?

avatar image Thial Thial · Aug 12, 2017 at 06:15 PM 0
Share

never$$anonymous$$d, fixed it :) turns out that UGCDownloadToLocation path requires the name of the file and the extension as well.

avatar image vitinho444 Thial · Aug 12, 2017 at 06:25 PM 0
Share

Thanks for that info. I wonder, how did you turn the zip file into a byte[] and vice-versa? Thank you!

Show more comments
avatar image buggy_glitch · Oct 31, 2017 at 08:45 AM 0
Share

Thanks and it is really helpful ! Just wanted to know if there is any other way to do it ,without subscribing to the content in workshop page?

avatar image vitinho444 buggy_glitch · Oct 31, 2017 at 09:27 AM 0
Share

I believe not. That's just how S$$anonymous$$m Workshop is setup. You have to subscribe items in order to download them. But there may be a way, I just don't know it. Check the S$$anonymous$$mworks docs, maybe you'll find something there.

Good luck.

avatar image buggy_glitch vitinho444 · Oct 31, 2017 at 09:34 AM 0
Share

Ohh I see this is the S$$anonymous$$mWorkshop way to store and restore stuff,I will look further in the docs,to achieve it without workshop. Thanks for the help.

Show more comments
Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

260 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

Getting the Location of a Laptop 0 Answers

Using a class library in Unity [Free version] 1 Answer

Creating Scenes Programmatically From A Deployed Build in Unity 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges