Simple work with Steamworks

Original author: Kyle Kukshtel
  • Transfer


Unity, C #, Steamworks.NET, and Facepunch.Steamworks


Introduction


Like most game developers, I really want to put my game on Steam.

Like most indie game developers, I lack access to resources / knowledge that would make me clear on what it really means to be on Steam.

It’s difficult to fill this knowledge gap, because despite the detailed documentation of Steam’s features, it’s hard to figure out where to start in this huge document repository and how its individual parts are related. In addition, the main discussions of the Steam platform are held in a closed forum, available only to platform confirmed via Steam Direct or Valve developers referral link. That is, for beginners, finding answers to simple questions can be challenging.

So I decided to write a high-level review for people who are just starting to figure out how to get Steam to work with their games. In particular, I will take a closer look at the Steamworks SDK , the Valve software library, which provides access to aspects such as a workshop (Workshop), leaderboards (Leaderboards), achievements (Achievements), and so on.

Steamworks is well documented.by Valve, but the documentation is written from the point of view of a person using the native C ++ library and already having an idea of ​​how all these functions intersect. If this is not your case, then even better! Below is an explanation for another person who writes a game in a higher level language and just wants to provide easy integration with Steamworks (and this is possible, I guarantee!). More specifically, this post is intended for people using C # in one form or another, and ideally working in the Unity game engine.

Steamworks


Steamworks consists of two parts. Firstly, this is a developer portal designed to manage everything related to the existence of a game on Steam, from changing game banners to managing sales and a list of supported controllers. Secondly, this is the SDK provided by Valve so that the developer can interact with everything else on Steam, including the workshop, leaderboards, servers, achievements, etc. Do not forget about this system! SDK " required only to download content on Steam". This means that you can completely refrain from fussing with all the above features of the SDK and focus only on how to download the game on Steam. However, the SDK provides many other useful features, so let's configure it and make it work!

If you write in C ++ you can just add the library to your game, follow these steps .

But if you're a developer in the C # / in the Unity, you have some work to do. the native C ++ header / source compatible with the Unity, you need to use a wrapper library that allows INTEGRATION Vat SDK functions. This wrapper will allow us to use the high-level C # function to call the low-level functions of C ++. In the past, a library-wrapper was Steamworks.NET, which is fully consistent with its name: this is Steamworks, implemented on .NET. However, this is exactly what she does, and nothing more.

Steamworks.NET provides a one-to-one conversion of Steamworks functions to C # functions, but that means you need a full understanding of Steamworks as a library to work. For beginners who want to get off with simple work, this may be too much. If you want to do something more complicated, for Steamworks.NET you have to write your own wrapper on top of its wrapper, which makes the idea of ​​wrapping meaningless.



Facepunch.Steamworks


Due to these limitations and other reasons , Facepunch Studios (known for Rust and Garry's Mod games) wanted to write a more convenient Steamworks library for C # / Unity.

It eliminates the need to write a bunch of code to implement simple (and complex) tasks in Steamworks, allowing you to focus on the very "work" with Steam. The library is used in Rust, that is, its work is tested on a game with one of the largest community of players on Steam. Complex tasks are abstracted into simple function calls, the library itself consists of only three files, that is, it does not really inflate the project. I can not express how useful it is for beginners, this is a real find. Steamworks.NET creator even said Facepunch.Steamworks is "it’s exactly what I wanted to turn Steamworks.NET further “and that” for most developers it should be the default choice . ”Steamworks.NET is still available for those who want to implement their own version of Facepunch.Steamworks, but, by "To me, what’s good for Rust is good enough for me. How does the library work and what’s special about it? Let's get started."

Beginning of work


Firstly, you might think that in order to start working with Steamworks you need to be a confirmed Steamworks developer, but in fact, you can use the SDK right away without going through the registration process. Valve provided developers with a test "AppID" 480, for which you can program.

Appid


AppID is a unique identifier for a game on Steam (and on Steamworks). You get it in immediately after registering the game. It "takes" you a place on Steam / Steamworks and allows you to completely dispose of everything related to this AppID. AppID 480 matches SpaceWar, a demo game created by Valve. It has open source and shows some of the features of Steamworks ( be sure to explore it !).

The unique AppID is convenient and obviously necessary for your game at a certain stage, while the test AppID (480) allows you to work with Steam services as ifYour game is ready. When you get the real AppID, substitute it, and for now, 480 is fine. That is, you should not create a server with the name "Server with the name of my game, waiting to be registered as a trademark."

Download and import Facepunch.Steamworks


So, let's download the Facepunch.Steamworks library (hereinafter I will call it FP), already knowing that we can test it with the AppID 480. Go to the releases section on the Github page (the library has fully open source code and a MIT license) and download the latest release. Unzip the .zip file to get multiple folders. In README, everything is detailed, but in essence it’s enough to simply copy a small set of these files into your Unity project (the details depend on the platform). Facepunch.Steamworks files are the library itself, steam_api files and platform-specific files containing the Steamworks SDK itself. After importing, the Unity folder should look something like this (in the case of Windows x86 / x64):

Unity Project Folder
|— Assets
    |— Plugins
        |— Facepunch.Steamworks
            |— Facepunch.Steamworks.dll
            |— Facepunch.Steamworks.pdb
            |— Facepunch.Steamworks.xml
|— steam_api.dll (Windows x86)
|— steam_api64.dll (Windows x64)
|— steam_appid.txt


The “steam_appid.txt” file is a text file that contains only your AppID, so we will use a text file with “480” (without quotes). The ".dll", ".pdb" and ".xml" files are copied from the Release folder of the downloaded .zip file of the corresponding version of ".NET". For Unity, 3.5 is suitable. If you start with a clean slate, Facepunch generously provides a small test project that does most of the work for you. You can start your project with it.

Unity


By copying all the library files to the appropriate directories, you are almost done with the setup! The only thing we need to do is write some code to integrate everything. I will copy the test file from the test project and simply shorten it for clarity.

using System;
using UnityEngine;
using System.Collections;
using System.Linq;
using Facepunch.Steamworks;
public class SteamTest : MonoBehaviour 
{
    void Start ()
    {
        // Не уничтожать при загрузке новых сцен
        DontDestroyOnLoad( gameObject );
        // Настройка для Unity
        // Это ОЧЕНЬ важно - нужно вызывать это прежде всего остального
        Facepunch.Steamworks.Config.ForUnity( Application.platform.ToString() );
        // Создаём клиент steam с помощью тестового AppID (или вашего AppID)
        new Facepunch.Steamworks.Client( 480 );
        // Проверяем, всё ли запущено правильно
        if ( Client.Instance == null )
        {
                Debug.LogError( "Error starting Steam!" );
                return;
        }
        // Печатаем базовую информацию
        Debug.Log("My Steam ID: " + Client.Instance.SteamId);
        Debug.Log("My Steam Username: " + Client.Instance.Username );
        Debug.Log("My Friend Count: " + Client.Instance.Friends.AllFriends.Count() );
    }
    private void OnDestroy()
    {
        if ( Client.Instance != null )
        {
                // Надлежащим образом избавляемся от клиента, если этот объект уничтожен
                Client.Instance.Dispose();
        }
    }
    void Update()
    {
        if ( Client.Instance != null )
        {
                // Это необходимо вызывать Update для правильной работы библиотеки
                Client.Instance.Update();
        }
    }
}

And that is all! If you attach this script to “GameObject” in the scene and switch to game mode, you will see that you are playing “Spacewar” on Steam, and the Steam’s basic information about you is displayed in the console (if it didn’t work, check if you’re signed in Steam).

Life with Facepunch.Steamworks


Opportunities


Once configured, access to the deeper Steam features is pretty straightforward because the FP library handles and wraps almost all parts of the standard Steamworks SDK. However, the question still remains: what are these parts? Here is a short list with descriptions of what you can work with (in the FP library):

1. Servers - create servers using the player’s client or launch a “headless” server in any other place. It is used for ping-sensitive games with high network requirements (such as Dota 2, Overwatch, etc.)

2. Lobbies are “meeting places” for players used to exchange SteamID or other user information.

3. Friends - You and your fellow Steam player players.

4. Workshop - upload / download content to and from Steam Workshop.

5. Leaderboards - create and store global leaderboards for the game.

6. Achievements - creation and delivery of achievements.

7. Network - sending P2P data to clients.

8. Steam Cloud - save data to the Steam Cloud! Very useful for saving games.

9. Voice - interaction with the Steam voice API for in-game chat.

10. Statistics - sets statistics on the Steam side for a given player.

The best way to learn how to use the features you need is to see if there is a working example of it in the Facepunch.Steamworks test project (NOTE: this is notUnity test project), and simulate its implementation in your game.

Most of the features are documented in the FP library wiki , but in fact, several classes have sufficient description. If you cannot find an example, study the library code and see if the function is implemented at all. If not, then see how far you can go in its implementation on your part, or simply send an error message to the library. Usually, Facepunch developers are very responsive, they can tell you whether they are working on something or not, and they can even help you in helping the community if you decide to implement something yourself.

Subscribers and Callbacks


When working with the FP library (or even with the native API), you will notice that it is not always easy to work with a normal call of something like Client.Instance.SteamId. The reason is that the Steamworks SDK (and, therefore, the FP library) actively uses asynchronous functions so that the game does not “freeze” every time you need to perform non-trivial interaction with Steam. Without asynchronous calls, you would have to wait for the response of the main Steam server before your code was executed , which would obviously become a source of errors and annoyance during the game. Therefore, to use the library you need to get used to the concept of delegation and callbacks . For a beginner, this may seem complicated, but these concepts are easy to understand if you understand the basic idea. I will give an example.

If you need to get a list of all the lobbies in the game using the FP library, then you will write the following:

client.LobbyList.Refresh();

Note that no return or assignment is performed here. But in this case, how do we get what we request? After calling the function on Steamworks, the Steam backend prepares everything you need, and then sends you the data through a “callback”. Steam almost literally “calls you” to say: “Hey, your data is ready!”.

To receive a call, we need to “pick up the phone”, or, as it is commonly called, “subscribe” to a callback. This is realized by defining the function obtainedcallback data. Sometimes it does not transmit data, then the callback is used mainly as a “handler” or as a way to tell what can be continued. When you are inside the callback handler, you can safely continue to work. Here is an example:

void Start()
{
    // Подписываемся на соответствующее событие, определяя функцию, которую нужно вызвать, когда Steam вызывает OnLobbyJoined.
    client.Lobby.OnLobbyJoined += OnLobbyJoinedCallback;
    // Вызываем функцию
    Native.Lobby.Join(LobbyID);
}
void OnLobbyJoinedCallback(bool success)
{
    // Если мы внутри, то обратный вызов успешно выполнен!
    // Мы можем проверить состояние обратного вызова, проверив булеву переменную "success", которое Steam передаёт со значением true или false
    if(success)
    {
        // Если ошибок нет, то можно безопасно вызывать здесь фукнции, требующие особых условий
        // Например, можно вывести id владельца лобби
        Debug.Log(client.Lobby.Owner);
    }
}

Understanding this pattern will be very helpful when using the library. It's also very helpful to figure out what Steamworks actually does, so it's worth exploring its documentation. If you want to learn more about how it works, I recommend reading Valve's documentation on this topic , as well as some sections of the Steamworks.NET website .

Moving on


From now on, you can do anything you want! Valve does not set any requirements, but if you already got on the platform, then it is obvious that you are primarily interested in contacting it and its community in the ways that Valve provided. After registering with Steam Direct, you just need to replace the AppID and transfer all the Steam features that you implemented for the test AppID.

I hope this article is useful for anyone who wants to get started with Steam, and I highly recommend everyone to learn about Facepunch.Steamworks on Github . If you're ready for more, try making a modest contribution, for example, filling in the blanks in the documentation or sending requests. If you have questions about the article, you can contact me on Twitter: @kkukshtel. I will be glad if you read the news about my game on Twitter @isotacticsgame or subscribe to the newsletter . If you want to read more on similar topics, I recently created my blog in which this article was originally published.

Also popular now: