Future recipes will cover how to add custom functionality. This includes more complex solutions: for example, where
players log in using 3rd-party authentication via a splash screen, and where you load stored user data. You could even
make the player entity persist while the player is offline.

Creating a Player entity when a client connects

Workers create entities using the CreateEntity() command. But in games, you don’t want to give clients the power to
send such commands directly, to limit what a malicious client would be able to do (you could also enforce this using
worker permissions, which aren’t covered in this recipe).

This means clients need to communicate with a server-side worker in order to create a player. So instead of creating an
entity themselves, you can use a pattern where clients send a component command to a PlayerCreator entity, requesting
that the creation of an entity. On the server side, the PlayerCreator then runs the CreateEntity() command to create
the player entity.

This diagram illustrates the pattern:

Overview of player creation process:

Create the required components for requesting the Player creation, connecting the client and positioning the Player.

Extend Bootstrap.cs with a callback when the client connects to request the Player creation.

Set up the templates and prefabs for the PlayerCreator and Player entities.

Respond to the CreatePlayer command on the PlayerCreator entity.

Set the initial position of the Player in the Unity client.

1. Create the components in schema

The following components are needed for connection. Create these schema files in the /schema directory:

PlayerCreation.schema: defines a PlayerCreation component, which contains a command that a client can use to
request the creation of a player entity.

ClientConnection.schema: this is just an example component that will be added to the player. A client worker
needs to have write access to at least one component on the player entity.

package improbable.player;
component ClientConnection {
id = 1002;
}

Now run spatial worker codegen to generate Unity code for these schema changes.

If you haven’t built the project since cloning it, you also need to run spatial worker build.

2. Extend Bootstrap.cs

All SpatialOS projects should contain a GameEntry object in both the UnityClient and UnityWorker scenes. This object
has a script called Bootstrap which controls the worker connection to SpatialOS. You can use this script to implement
a custom login flow.

Bootstrap is used to start both client and server-side workers, so it does a lot. The following method call adds the
MonoBehaviours that enable interaction with SpatialOS to the GameEntry:

SpatialOS.Connect(gameObject);

Referring back to the diagram, Bootstrap needs to:

Locate the PlayerCreator entity using an entity query

Send a CreatePlayer command to that entity

You’ll implement this in the callback for a successful SpatialOS.Connect(...) call. The callback will search for a
PlayerCreator entity (via the PlayerCreation component), and if it finds one, send it the command:

In Bootstrap.cs, replace the line SpatialOS.OnConnected += OnSpatialOsConnection; with a callback to a method with
a more descriptive name, for example SpatialOS.OnConnected += CreatePlayer;:

In EntityTemplateFactory.cs, add any of the following using statements that you don’t have already:

using Assets.Gamelogic.Core;
using Improbable;
using Improbable.Core;
using Improbable.Player;
using Improbable.Unity.Core.Acls;
using Improbable.Unity.Entity;
using Improbable.Worker;
using UnityEngine;

4. Respond to the player creation command

At this point, Bootstrap is sending a CreatePlayer command, but nothing is responding to it. The PlayerCreator entity
should receive the CreatePlayer command and then create a Player entity. Here’s a basic implementation, adhering to
the basic patterns for both receiving commands
and creating new entities:

On the PlayerCreator prefab, create a new script, PlayerCreatingBehaviour.

Add the following using statements:

using Assets.Gamelogic.EntityTemplates;
using Assets.Gamelogic.Core;
using Improbable;
using Improbable.Entity.Component;
using Improbable.Core; // or whichever package you used for the schema files earlier
using Improbable.Unity;
using Improbable.Unity.Core;
using Improbable.Unity.Visualizer;
using Improbable.Worker;
using UnityEngine;

In OnEnable, register an asynchronous response to the command CreatePlayer, and deregister it in OnDisable.

Implement the callback, which sends the entity creation command. This responds to the CreatePlayer command with a SpatialOS
status code indicating if the player entity was created successfully. If it was not, the client will retry after a few seconds.
This retry logic is in Bootstrap.cs.

The completed code extends this further, to also receive rotation information.

Removing the player entity when the client disconnects

In most SpatialOS simulations you will want to delete the Player entity when the user exits the
Unity client.

A deliberate client disconnection would be implemented with some UI where you could save game state to some third party
storage before calling SpatialOS.Disconnect(). Implementing such a feature is outside the scope of this recipe, so we’ll
handle the general case of a client detected as inactive. This encompasses both when the user unclicks the play button
within Unity, and when the application crashes. This is handled using heartbeats.

Heartbeats involve the client repeatedly indicating to a server-side worker that it is still connected to SpatialOS. This
sounds intensive, but triggering one event per client every few seconds is okay. If the server-side worker doesn’t receive any
events from the client within a given period of time, the server-side worker will assume the client has died, and deletes
the Player entity associated with that client. Both the scripts for the client and server worker sides of this
interaction can be implemented as MonoBehaviours on the Player prefab as follows:

Add a SendClientConnection client-side script that uses a coroutine to send heartbeat events periodically:
```csharp
using Assets.Gamelogic.Core;
using Assets.Gamelogic.Utils;
using Improbable.Player;
using Improbable.Unity;
using Improbable.Unity.Visualizer;
using UnityEngine;

Add a HandleClientConnection server-side script that uses a coroutine to check whether the client is still sending
heartbeats.

This is implemented through the coroutine decrementing the timeoutBeatsRemaining property; receiving a Heartbeat
event resets to the default count. If the server worker doesn’t receive a Heartbeat for too long,
timeoutBeatsRemaining will reach 0, and the server worker will delete the Player entity.

In the Inspector, you should see the UnityClient disappearing from the Workers list. If you wait a few seconds, the
heartbeat timeout should kick in, causing the Player entity to be successfully deleted.