From release 0.2.5
onward, all GDK packages and feature modules will be delivered through the Unity Package Manager. To upgrade your project to use these packages do the following:
- Open the
Packages/manifest.json
file inside your Unity project. - Add the following JSON snippet to the this file, under the
"registry: "https://packages.unity.com"
line:"scopedRegistries": [ { "name": "Improbable", "url": "https://npm.improbable.io/gdk-for-unity/", "scopes": [ "io.improbable" ] } ]
- Under the
dependencies
field, find allcom.improbable.*
packages and change the names toio.improbable.*
. - For all these packages, change the value from
file:<something>
to0.2.5
.
Note: You no longer need to checkout the
gdk-for-unity
repository side-by-side your project to sideload these packages.
When calling the build system from the command line, you must change the buildTarget
argument to buildEnvironment
. Previously you may have called the build system like so:
Unity.exe <arguments> \
-executeMethod "Improbable.Gdk.BuildSystem.WorkerBuilder.Build" \
+buildWorkerTypes "UnityGameLogic" \
+buildTarget "cloud" \
+scriptingBackend "mono"
You must change this to:
Unity.exe <arguments> \
-executeMethod "Improbable.Gdk.BuildSystem.WorkerBuilder.Build" \
+buildWorkerTypes "UnityGameLogic" \
+buildEnvironment "cloud" \
+scriptingBackend "mono"
When constructing a ForwardingDispatcher
, you must now provide a UnityEngine.LogType
instead of a Improbable.Worker.CInterop.LogLevel
.
Several utility methods in the TransformUtils
class have been made internal
to the Transform Synchronization package. We highly recommend that if you were using the TransformInternal
component in your logic, to use UnityEngine.Transform
instead.
You must no longer use the TransformInternal.Snapshot
constructor.
// Sample of INVALID code - the `Location` and `Quaternion` schema types have been removed.
var transform = new TransformInternal.Snapshot
{
Location = new Location((float) coords.X, (float) coords.Y, (float) coords.Z),
Rotation = new Quaternion(1, 0, 0, 0),
TicksPerSecond = 1f / Time.fixedDeltaTime
};
Instead, you must use the TransformUtils.CreateTransformSnapshot
static method. This is to ensure that the contents of an entity's TransformInternal
component are compressed using the Transform Synchronization module's new compression scheme.
// This is the correct way of initialising a `TransformInternal` snapshot manually.
var transform = TransformUtils.CreateTransformSnapshot(Coordinates.Zero, Quaternion.identity, Vector3.forward)
If you use the AddTransformSynchronizationComponents
method in the TransformSynchronizationHelper
class, you do not need to update code.
You must regenerate any snapshots which contain entities that make use of the Transform Synchronization feature module.
This release brought a number of changes to the WorkerConnector
and its derived classes. A crucial difference is now that the logic for connecting a worker is described by composing objects in a builder-like pattern rather than class level methods on the WorkerConnector
methods.
As a result of this the DefaultWorkerConnector
and DefaultMobileWorkerConnector
have been removed, with their logic preserved in other objects. More about that later.
As a general rule for this upgrade, the changes in the ClientWorkerConnector.cs
, GameLogicWorkerConnector.cs
, and MobileClientWorkerConnector.cs
classes between the 0.2.3
and 0.2.4
releases will be illustrative in the upgrade process. The upgrade process depends on how heavily you customized your worker connector.
Previously, your connection logic may have looked something like:
private async void Connect()
{
// Some custom logic..
await Connect(WorkerUtils.MyWorkerType, new ForwardingDispatcher()).ConfigureAwait(false);
}
All the details for how the connection was made and which flow it used were contained in the class methods like GetConnectionService
, GetReceptionistConfig
, etc.
Now, your connection logic will look something like:
private async void Connect()
{
var builder = new SpatialOSConnectionHandlerBuilder()
.SetConnectionParameters(CreateConnectionParameters(WorkerUtils.MyWorkerType));
var initializer = new CommandLineConnectionFlowInitializer();
switch (initializer.GetConnectionService())
{
case ConnectionService.Receptionist:
builder.SetConnectionFlow(new ReceptionistFlow(CreateNewWorkerId(WorkerUtils.MyWorkerType), initializer));
break;
case ConnectionService.Locator:
builder.SetConnectionFlow(new LocatorFlow(initializer));
break;
case ConnectionService.AlphaLocator:
builder.SetConnectionFlow(new AlphaLocatorFlow(initializer));
break;
default:
throw new ArgumentOutOfRangeException();
}
await Connect(builder, new ForwardingDispatcher()).ConfigureAwait(false);
}
There are a few new things here:
- The
SpatialOSConnectionHandlerBuilder
. This object is used for configuring and creating a single SpatialOS connection. - The
xyzFlow
objects. These encapsulate the configuration and implementation for connecting to SpatialOS via a specific connection flow. - The
xyzFlowInitializer
objects. These describe how the configuration for a flow object is obtained.
For upgrading mobile worker connectors, see below. We preserved the semantics of the DefaultWorkerConnector
implementation in the CommandLineConnectionFlowInitializer
and connection flow objects to make upgrading as easy as possible.
In order to replicate the DefaultWorkerConnector
behaviour exactly:
- Change your mobile worker connector implementation to inherit from
WorkerConnector
instead ofDefaultWorkerConnector
. - Use the following code snippet to connect:
private async void Connect() { var builder = new SpatialOSConnectionHandlerBuilder() .SetConnectionParameters(CreateConnectionParameters(WorkerUtils.MyWorkerType)); var initializer = new CommandLineConnectionFlowInitializer(); switch (initializer.GetConnectionService()) { case ConnectionService.Receptionist: builder.SetConnectionFlow(new ReceptionistFlow(CreateNewWorkerId(WorkerUtils.UnityClient), initializer)); break; case ConnectionService.Locator: builder.SetConnectionFlow(new LocatorFlow(initializer)); break; case ConnectionService.AlphaLocator: builder.SetConnectionFlow(new AlphaLocatorFlow(initializer)); break; default: throw new ArgumentOutOfRangeException(); } await Connect(builder, new ForwardingDispatcher()).ConfigureAwait(false); }
Previously, there were a set of virtual methods on the WorkerConnector
class that changed the behaviour of some of the connection flows. These methods now live in their respective connection flow objects (and are still virtual). You can inherit from the flow object and override the methods to achieve the same behaviour. See the table below for a mapping of where these methods currently exist.
Method | Class |
---|---|
SelectDeploymentName(DeploymentList deployments) |
LocatorFlow |
GetPlayerId() |
AlphaLocatorFlow |
GetDisplayName() |
AlphaLocatorFlow |
string SelectLoginToken(List<LoginTokenDetails> loginTokens) |
AlphaLocatorFlow |
string GetDevelopmentPlayerIdentityToken(string authToken, string playerId, string displayName) |
AlphaLocatorFlow |
List<LoginTokenDetails> GetDevelopmentLoginTokens(string workerType, string playerIdentityToken) |
AlphaLocatorFlow |
The mobile setup is a little bit special. There are built-in initializers for the connection flows and connection parameters in the mobile package. These replicate the behaviour of the DefaultMobileWorkerConnector
.
The MobileConnectionFlowInitializer
constructor takes any number of IMobileSettingsProvider
objects and will use these to get mobile specific settings (such as the host IP address for the receptionist). The order in which you provide these objects does matter as the first one to return a valid setting for each setting will be used. We provide two implementations of this interface in the mobile package, one for command line arguments and one for player prefs.
In order to replicate the DefaultMobileWorkerConnector
exactly:
- Change your mobile worker connector implementation to inherit from
WorkerConnector
instead ofDefaultMobileWorkerConnector
. - Add a
[SerializeField] private string ipAddress;
field to yourWorkerConnector
. - Implement
MobileConnectionFlowInitializer.IMobileSettingsProvider
for your mobile worker connector:public Option<string> GetReceptionistHostIp() { return string.IsNullOrEmpty(ipAddress) ? Option<string>.Empty : new Option<string>(ipAddress); } public Option<string> GetDevAuthToken() { var token = Resources.Load<TextAsset>("DevAuthToken")?.text.Trim(); return token ?? Option<string>.Empty; } public Option<ConnectionService> GetConnectionService() { return Option<ConnectionService>.Empty; }
- Use the following code snippet to connect:
var connParams = CreateConnectionParameters(WorkerUtils.MobileClient, new MobileConnectionParametersInitializer()); var flowInitializer = new MobileConnectionFlowInitializer( new MobileConnectionFlowInitializer.CommandLineSettingsProvider(), new MobileConnectionFlowInitializer.PlayerPrefsSettingsProvider(), this); var builder = new SpatialOSConnectionHandlerBuilder() .SetConnectionParameters(connParams); switch (flowInitializer.GetConnectionService()) { case ConnectionService.Receptionist: builder.SetConnectionFlow(new ReceptionistFlow(CreateNewWorkerId(WorkerUtils.MobileClient), flowInitializer)); break; case ConnectionService.AlphaLocator: builder.SetConnectionFlow(new AlphaLocatorFlow(flowInitializer)); break; default: throw new ArgumentException("Received unsupported connection service."); } await Connect(builder, new ForwardingDispatcher()).ConfigureAwait(false);