Give Page Feedback

Players - Procedural Players

Procedural Players are players that are only created after your game starts running. These type of players require a special mechanism to be used with SAM, because under normal circumstances SAM expects the Player to be assigned to the Active Grid from within the Unity Editor, which clearly is not possible when using a procedural player.

SAM offers several different mechanisms for handling procedural players, the choice of which will depend on how your game works.

Assigning the Player before Component Manager Initialization.

The easiest method and the one that requires the least effort is to simply delay the initialization of SAM (via the Component Manager) until after your Player is created. Unfortunately, this mechanism can only be used if you are able to delay the loading of the game world until after the player is created/spawned. It will not work in situations where you want the player to see the game world before the player character is spawned in.

In order to use this mechanism, follow these steps:

1) Disable the Initialize On Awake option of the Component Manager component (found on the Component Manager game object).

2) Edit the script that creates/spawns your Player to perform steps 3-5.

3) Add fields for the ActiveGrid and SAMInitializer (and/or Component manager), then assign these components to the fields via drag/drop.

4) If you plan on initializing the Component Manager in a gradual way, you should disable the Player after spawning them, so they do not fall through the game world.

5) After the code that spawns your player, assign your player to the Active Grid using its PreInitialize_SetPlayer method (see https://deepspacelabs.net/html/dynamic_loading_api/ActiveGrid.html#PreInitialize_SetPlayer1 for more information).

You can pass in a PlayerMover component if using one (or null if not). We recommend passing in false for the overrideIgnorePlayerPositionInPersistentData argument, though you can read the API and choose a different value if you wish.

6) Initialize the Component Manager, either using the SAM Initializer (InitializeSAM_Immediate or InitializeSAM_Gradual method) or directly by calling ComponentManager.Initialize or ComponentManager.InitializeGradually.

7) If you initialized the Component Manager gradually, re-enable your Player. Timing this is easy when using ComponentManager.InitializeGradually, since you should know exactly when the enumerator finishes (which is when intialization has completed).

If using the SAM Initializer, you can subscribe to the Component Manager's ComponentManagerInitialized event to receive notification when initialization completes (you do not need to unsubscribe from this event, as it is only called once).

Component Manager API

SAM Initializer API

Using a Custom Player

An alternative to delaying the Component Manager's initialization is to use a Custom Player component by creating a script that derives from the CustomPlayer abstract MonoBehaviour class. This is a very simple class with only a single Position property.

CustomPlayer

This is an incredibly powerful technique as you are basically free to implement whatever logic you want. For instance, you can have the Custom Player track one Transform before your player character is spawned, then when the player spawns you can replace the tracked Transform with the new player's transform. Or you can just return the position of the spawn location when the Position property is queried when no player character transform is assigned. You have complete control (you can even kill your player and return the new spawn location after, until the player respawns)!

There are a few things that should be noted when using this technique, however:

1) If persistent save data exists for SAM and you load it using the Component Manager's Load method, when the Component Manager is initialized, by default the Player objects assigned to Active Grids will be repositioned (by calling IPlayer.Position = savedPosition).

You can either store this position in your Custom Player in order to apply it to the character after it is spawned (recommended), or you can disable this behavior by enabling the Ignore Player Position In Persistent Data setting on each Active Grid component (via their inspector).

2) The Player's position is manipulated by SAM in a few situations, like when an Origin Cell change occurs and your Active Grid's Move Player After Origin Cell Change setting is enabled. If your Custom Player is not currently manipulating the actual player character, you should account for this (perhaps by storing the position changes until your player is respawned, like in 1 above).

Using a Custom IPlayer

This is similar to the technique above except that your custom class will not derive from CustomPlayer, but will instead simply implement the IPlayer interface.

IPlayer Interface

When using this technique, since your class does not derive from MonoBehaviour, the player must be assigned via scripting using the Active Grid's PreInitialize_SetPlayer method. It should go without saying, but this assignment needs to occur before the Component Manager is initialized. However, there is nothing stopping you from using the technique described in the Using a Custom Player sub-section and using a raw position value as the player position before your player character is spawned.

Spawn Locations in a Floating Origin Based World

If you are utilizing spawn locations in a floating origin based world, remember that you should never define your spawn location coordinates in world space, as they will become invalidated if the Origin Cell of the World changes. Instead, you should determine which Streamable Grid Cell a spawn location is in and store that, along with the position of the spawn location relative to this Cell's origin (minimum point).

Spawn Locations With Endless Worlds

When using Endless Worlds, multiple copies of the same Streamable Grid Cell can be loaded into the scene at the same time. As such, you will need to decide which of these cells the spawn should take place in (the one closest to the World Origin Position should generally be used).