
Unity, C #, Steamworks.NET and Facepunch.Steamworks
Introduction
Like most game developers, I really want to post
my game on Steam.
Like most
indie game developers, I lack access to resources / knowledge that would give me a clear understanding of what it really means to be on Steam.
')
It is difficult to fill this gap in knowledge, because, despite the
detailed documentation of Steam's capabilities, it is difficult to know where to start in this huge repository of documents and how its parts are interconnected. In addition, the main discussions of the Steam platform are held in a closed forum, accessible only to platform-confirmed via Steam Direct or Valve developers' referral link. That is, for beginners, finding answers to simple questions can be a difficult task.
So I decided to write a high-level review for people who are just starting to figure out how to make Steam work with their games. In particular, I will look in detail at
Steamworks SDK , the Valve software library, which provides access to such aspects 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 it is even better! Below is an explanation for another person who writes the 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 the game on Steam, from changing game banners to sales management 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! The SDK is "
only required to download content to Steam ". This means that you can completely refrain from messing around with all the above SDK features and focus only on how to download the game to Steam. However, the SDK provides many other useful features, so let's configure it and make it work!
If you are writing in C ++, you can simply add the library to your game by
following these instructions .
But if you are a developer on C # / in Unity, you will have to work a little. Native C ++ headers / sources are incompatible with Unity, you need to use a wrapper library that allows you to integrate the functions of the SDK. Such a wrapper will allow us to use high-level C # functions to call low-level C ++ functions. In the past, such a wrapper library was
Steamworks.NET , which fully corresponds to 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 transformation of Steamworks functions into C # functions, but this means that in order to work you will need a
complete understanding of Steamworks as a library. For beginners who want to get rid of simple work, this may be too much. If you want to do something more complicated, for Steamworks.NET you will have to write your own wrapper
on top of its wrapper, which deprives the wrap idea itself.

Facepunch.Steamworks
Due to these limitations and
for 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 “work” with Steam itself. The library is used in Rust, that is, its work is tested on the game with one of the largest communities of players on Steam. Difficult 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. The creator of Steamworks.NET even said that Facepunch.Steamworks is "
exactly what I wanted to turn Steamworks.NET into " 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, in my opinion, what is good for Rust is good enough for me. How does the library work and what is special about it? Let's start to understand.
Beginning of work
First, you might think that to start working with Steamworks you need to be a confirmed developer of Steamworks, 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 game identifier on Steam (and Steamworks). You get it in immediately after registering the game. It "takes" you a place on Steam / Steamworks and allows you to fully dispose of everything related to this AppID. AppID 480 corresponds to SpaceWar, a demo game created by Valve. It has open source and shows some of the features of Steamworks (
be sure to learn it !).
Unique AppID - this 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 if your game is ready. When you get a real AppID, then substitute it, but for now, 480 is fine. That is, you should not create a server called “Server with the name of my game awaiting registration 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 will be able to test it with AppID 480.
Go to the releases section on the Github page (the library has a completely open source code and MIT license) and download the latest release. Unzip the .zip file to get several folders. In README, everything is detailed, but, in essence, it is enough just to copy a small set of these files into your Unity project (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 files ".dll", ".pdb" and ".xml" are copied from the Release folder of the downloaded .zip file of the appropriate version ".NET". For Unity, 3.5 is suitable. If you start from scratch, Facepunch generously
provides a small test project that does most of the work for you. With it, you can start your project.
Unity
By copying all the library files into the appropriate directories, you are almost done setting up! The only thing we need is to write some code to integrate everything. I will copy the test file from the
test project and just cut it for clarity.
using System; using UnityEngine; using System.Collections; using System.Linq; using Facepunch.Steamworks; public class SteamTest : MonoBehaviour { void Start () {
And that is all! If you attach this script to the “GameObject” in the scene and go into game mode, then you will see that on Steam you are playing “Spacewar” and the basic Steam information about you is displayed in the console (if it didn’t work out, check whether Steam).
Life with Facepunch.Steamworks
Opportunities
Once set up, access to the deeper Steam functions becomes quite simple, because the FP library processes and wraps almost all parts of the standard Steamworks SDK. However, the question still remains:
what are these parts? Here is a small list with descriptions of what you can work with (in the FP library):
1. Servers - the creation of servers using a player's client or launching a "headless" server in any other place. Used for ping-sensitive games with high network requirements (such as Dota 2, Overwatch, etc.)
2. The lobby is the “meeting place” of players used to share SteamID or other user information.
3. Friends - you and your friends are players on Steam.
4. Workshop - upload / download content to and from the Steam Workshop.
5. Leaderboards — create and store global leaderboards for the game.
6. Achievements - the creation and issuance of achievements.
7. Network - sending P2P data to clients.
8. Steam Cloud - saving data to the cloud Steam Cloud! Very useful for saving games.
9. Voice - interaction with the Steam voice API for in-game chat.
10. Statistics - setting statistics on the Steam side for a given player.
The best way to learn how to use the necessary functions is to see if there is a working example of it in the
test project Facepunch.Steamworks (NOTE: this is
not a test Unity 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 a sufficient description. If you cannot find an example, examine the library code and see if the function is implemented at all. If not, then see how far you can go into its implementation for 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 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 the usual call of something like
Client.Instance.SteamId
. The reason is that Steamworks SDK (and therefore the FP library) makes extensive use of asynchronous functions so that the game does not “hang” every time you need to perform a non-trivial interaction with Steam. Without asynchronous calls, you would have to wait for a response from the main Steam server before running
your code, 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, you will write the following:
client.LobbyList.Refresh();
Note that no return or assignment is performed here. But in that case, how do we
get what we request? After calling a function in Steamworks, the Steam backend prepares everything you need, and then sends you data through a “callback”. Steam almost literally "calls you" to report: "Hey, your data is ready!".
To receive a call, we need to “pick up the phone”, or, as it is usually called, “subscribe” to the callback. This is implemented by defining the function that
the callback data
receives . Sometimes it does not transmit data, then the callback is used primarily as a “handler” or as a way to communicate what can be continued. When you are inside a callback handler, you can safely continue working. Here is an example:
void Start() {
Understanding this pattern will be very useful when using the library. It is also very helpful to understand what Steamworks actually does, so it’s worth exploring its documentation. If you want to learn more about how it works, I recommend reading the
Valve documentation on this topic , as well as some sections
of the Steamworks.NET website .
Moving on
From now on you can do anything! Valve does not set any requirements, but if you are on the platform, it is obvious that it is first of all interesting for you to contact it and its community in the ways provided by Valve. After registering with Steam Direct, you simply replace AppID and transfer all Steam functions that you have implemented for the test AppID.
I hope this article will be useful for those who want to start working with Steam, and I highly recommend everyone to explore
Facepunch.Steamworks on Github . If you are ready for more, try to make a modest contribution, for example, filling in the gaps in the documentation or sending requests. If you have any 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 own blog in which this article was originally published.