Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Steamworks.NET API and Linux with Proton? Crash for user

Discussion in 'Formats & External Tools' started by GameDevSA, Dec 3, 2021.

  1. GameDevSA

    GameDevSA

    Joined:
    Dec 12, 2016
    Posts:
    252
    Has anyone got the Steamworks.net API working with Linux and proton users?

    I've got a game released on Steam that has been working fine for Windows users. I had no Steamworks API integrated.

    Recently I launched v2.1 of the game, which includes some Steamworks API stuff. Previously the save file was just stored in the "C:\Users\Admin\AppData\LocalLow\Developer\Game" folder.

    Since adding the Steamworks API, I'm now grabbing the users unique SteamID to create a unique sub folder with the save data, which enables multiple Steam users on the same windows account to have their own save file - something I didn't realise was being shared before. This also means the game will work better with cloud saves.

    Since enabling this feature, however, and adding in cloud saves, I had a friend test the game who did it with Linux + Proton and his game crashes. It loads fine, but as soon as the game tries to read from the save file, it just stalls. The reason appears to be because the game is not creating a save file since adding in the Steamworks API and trying to use the SteamID for the filepath.

    A quick birds eye view of what my code is doing.

    This is the old filePath pre-Steamworks, which I called "genericFilePath":

        string genericFilePath = "";

    genericFilePath = Application.persistentDataPath + "/save.data";


    Then on "Start()" I set the 'UniqueFilePath' which is what's created with the Steamworks.net API for each Steam user:

    Code (CSharp):
    1.     private void Start()
    2.     {
    3.         genericFilePath = Application.persistentDataPath + fileName;
    4.         if (SteamManager.Initialized)
    5.         {
    6.             steamID = SteamUser.GetSteamID().m_SteamID;
    7.             uniqueUserFilePath = Application.persistentDataPath + "/" + steamID + fileName;
    8.         }
    9.     }
    Here is saving:

    Code (CSharp):
    1.     public void SaveGame(GameData saveData)
    2.     {
    3.         string filePath = genericFilePath;
    4.         if (SteamManager.Initialized)
    5.             filePath = uniqueUserFilePath;
    6.  
    7.         if (SaveFileExistsAt(uniqueUserFilePath) == false)
    8.             Directory.CreateDirectory(Path.GetDirectoryName(uniqueUserFilePath));
    9.  
    10.         FileStream dataStream = new FileStream(filePath, FileMode.Create);
    11.  
    12.         BinaryFormatter converter = new BinaryFormatter();
    13.         converter.Serialize(dataStream, saveData);
    14.  
    15.         dataStream.Close();
    16.     }
    And here is loading:

    Code (CSharp):
    1.     public GameData LoadGame()
    2.     {
    3.         GameData saveData;
    4.  
    5.         if (SteamManager.Initialized && SaveFileExistsAt(uniqueUserFilePath))
    6.         {
    7.             // File exists
    8.             FileStream dataStream = new FileStream(uniqueUserFilePath, FileMode.Open);
    9.  
    10.             BinaryFormatter converter = new BinaryFormatter();
    11.             saveData = converter.Deserialize(dataStream) as GameData;
    12.  
    13.             dataStream.Close();
    14.         }
    15.         else if (SaveFileExistsAt(genericFilePath))
    16.         {
    17.             FileStream dataStream = new FileStream(genericFilePath, FileMode.Open);
    18.  
    19.             BinaryFormatter converter = new BinaryFormatter();
    20.             saveData = converter.Deserialize(dataStream) as GameData;
    21.  
    22.             dataStream.Close();
    23.  
    24.             SaveGame(saveData);
    25.         }
    26.  
    27.         return saveData;
    28.     }
    This isn't the whole file, just the key points. Bear in mind it does work for Windows, but not on Linux / Proton.

    In the Load() function, if there is no save file at the UniqueFilePath, but there is one at the GenericFilePath, it copies the save data into the unique path.

    Anyway, Application.persistentDataPath is supposed to be cross-platform which is why I use it so I can't see what's wrong? Hence why I'm wondering if anyone has had experience with Linux and Proton and got it working, and can see something I'm missing.
     
  2. GameDevSA

    GameDevSA

    Joined:
    Dec 12, 2016
    Posts:
    252
    I should add that I am specifically referring to a Windows build, as that's what I have built and also stated on Steam. I'm wondering if anyone has got a Steamworks.net API Windows build working for Linux users who are using Proton. I haven't tried making a specific Linux build yet and in this case I'm just looking at the Windows build, though also open to talking about other options.
     
  3. GameDevSA

    GameDevSA

    Joined:
    Dec 12, 2016
    Posts:
    252
    Ok I asked the user to run a developer build and got more information. It looks like it's the Steamworks.net API that's crashing on Linux. Here's the error code:

    Code (CSharp):
    1. [Steamworks.NET] SteamAPI_Init() failed. Refer to Valve's documentation or the comment above this line for more information.
    2. UnityEngine.StackTraceUtility:ExtractStackTrace () (at C:/buildslave/unity/build/Runtime/Export/Scripting/StackTrace.cs:37)
    3. UnityEngine.DebugLogHandler:LogFormat (UnityEngine.LogType,UnityEngine.Object,string,object[])
    4. UnityEngine.Logger:Log (UnityEngine.LogType,object,UnityEngine.Object)
    5. UnityEngine.Debug:LogError (object,UnityEngine.Object)
    6. SteamManager:Awake () (at C:/Game Business/Game Projects/01_Puzzledorf/Puzzledorf Unity v2/Assets/1.Scripts/Steamworks.net/SteamManager.cs:124)
    Not sure how you're supposed to fix this for Linux + Proton.
     
  4. GameDevSA

    GameDevSA

    Joined:
    Dec 12, 2016
    Posts:
    252
    Ok I did a test with Windows. It turns out that if you delete the steam_appid.txt file from the build folder, and submit to steam, it works and doesn't crash on Windows. But for some reason to test outside of steam, you need the steam_appid.txt in the Builds folder. But I still have no idea how to prevent the issue on Linux + Proton because I get the issue there with or without the steam_appid.txt file.