This page tells you how to distribute a Unity SpatialOS game via Steam, using the Steamworks SDK to authenticate a player.
Note that, in order to integrate your game with Steam, you'll need to acquire the means to publish a game on Steam, and pass the Steam Direct process.
If you haven't already:
- Register with Steamworks.
- Submit your game to Steam Direct and complete the process.
Once you've done that, you'll need to get in touch with us:
-
Find your Steam AppID.
You'll be given an AppID once you've completed the Steam Direct process.
-
Generate a Steam Web API key by following these instructions.
-
Get in touch: ask us to add your AppID and Web API key to your project.
Only send this information privately to Improbable staff. Don't post your AppID or WebAPI key publicly.
In this step, you'll implement a simple version of Steam integration that lets you launch Unity clients using Steam.
To do this:
-
In your SpatialOS project, install Steamworks.NET into your
workers/unity
project by following these instructions. -
In
SteamManager.cs
(inworkers/unity/Assets/Scripts/Steamwork.NET
), implement the following method:// Return steam access token as a hexadecimal string. public static string GetSteamTicketString() { var steamTicketData = new byte[1024]; uint steamTicketLength; HAuthTicket hAuthTicket = SteamUser.GetAuthSessionTicket( steamTicketData, 1024, out steamTicketLength); if (hAuthTicket == HAuthTicket.Invalid) { throw new System.Exception("Couldn't get valid steam ticket."); } return BitConverter.ToString( steamTicketData, 0, (int)steamTicketLength ).Replace("-", ""); }
-
In
Bootstrap.cs
(normally located on a single GameEntry object located in both yourUnityWorker
andUnityClient
scenes), implement the following method:private void StartGameWithSteamAuthentication() { // Set the auth to Steam and include the token from the Steam API. // "steam_deployment" should be a tag on the deployment Steam clients will use // Make sure we don't connect to "localhost" or a custom IP but use the locator instead Configuration.SpatialOsApplication.DeploymentTag = "steam_deployment"; Configuration.Networking.SteamToken = SteamManager.GetSteamTicketString(); Configuration.Networking.Ip = Defaults.LocatorAddress; SpatialOS.ApplyConfiguration(Configuration); SpatialOS.Connect(gameObject); }
-
Create and manage a conditional callback to make sure that
SteamUser.GetAuthSessionTicket()
is only called after Steamworks has been initialised:-
In
Steammanager.cs
, add the following method delegate as a class member variable:public static Action StartGameCallback = delegate {};
-
At the end of
Awake()
, afterm_bInitialized = SteamAPI.Init()
(ie after Steamworks has been initialised) call this method by adding the following line:StartGameCallback();
-
In
Bootstrap.cs
, inStart()
, replace the lineSpatialOS.Connect(gameObject);
with the following lines:if (!SteamManager.Initialized) { // Defer the StartGameWithSteamAuthentication() call to after Steamworks has been initialised SteamManager.StartGameCallback = StartGameWithSteamAuthentication; } else { // Safely call StartGameWithSteamAuthentication(), SteamManager.StartGameCallback() will now do nothing when called in Awake() StartGameWithSteamAuthentication(); }
-
At this stage, you can start a game client from Steam. However, the current implementation has several side effects:
- UnityClients can only be started from Steam and nowhere else.
- UnityWorkers won't connect.
- The Launcher (SpatialOS documentation) will no longer work.
To fix these problems, you can wrap the Steam logic in a check for a command-line argument: steamClient
.
This argument will be present when you launch a client from Steam. But it won't be there when you launch a client
from the Launcher, or when you run UnityWorkers.
To do this:
-
Open
Bootstrap.cs
. -
In the
Start()
method, replace the above logic with the following lines:if (WorkerConfiguration.GetCommandLineValue(System.Environment.GetCommandLineArgs(), "steamClient", false)) { // For Unity clients that were started from Steam if (!SteamManager.Initialized) { // Defer the StartGameWithSteamAuthentication() // call to after Steamworks has been initialised SteamManager.StartGameCallback = StartGameWithSteamAuthentication; } else { // Safely call StartGameWithSteamAuthentication() after Steamworks has been initialised. // SteamManager.StartGameCallback() will do nothing in Awake() StartGameWithSteamAuthentication(); } } else { // For Unity Clients started from the Improbable Launcher and UnityWorkers SpatialOS.Connect(gameObject); }
-
Find the zipped version of the client executable called
UnityClient@<your-target-platform>.zip
in<spatialos-project-root>/build/assembly/worker
, and unzip it. -
Upload the unzipped content to SteamPipe using the ContentBuilder.
For details on how to do this, see the SteamPipe documentation.
-
On the Steamworks App Admin page, navigate to
Installation > General
. -
Create a new Launch Option with the following settings:
- Executable: Your client executable, for example
[email protected]
or[email protected]
. - Arguments:
+appName <your SpatialOS project name> +assetDatabaseStrategy Streaming +steamClient true
+appName
needs to be set to your SpatialOS project name (SpatialOS documentation), as specified in yourspatialos.json
(SpatialOS documentation).+assetDatabaseStrategy Streaming
specifies that entity prefabs loaded as part of your project assemblies will be downloaded to the game client at runtime.+steamClient true
means that clients launched from Steam will use Steam authentication, using the logic you implemented in step 3 above.
- Executable: Your client executable, for example
If you want a deployment to use Steam authentication, you must tag the deployment with the string you entered
for Configuration.SpatialOsApplication.DeploymentTag
in step 2.3 above (steam_deployment
by default).
To do this for all the deployments in your project:
-
Open
Bootstrap.cs
. -
In
StartGameWithSteamAuthentication()
, add the following line (replacingsteam_deployment
with your own string):EngineConfiguration.Instance.DeploymentTag = "steam_deployment";
Alternatively, you can:
-
Add the tag when launching a cloud deployment (SpatialOS documentation) (replacing
steam_deployment
with your own string):spatial cloud launch [...] --tags=steam_deployment
-
After you've launched a deployment, add the tag from the console:
You've now successfully integrated your game with Steam!
To generate and manage access keys which will allow you to distribute your game, take a look at the SteamWorks packages documentation.