Give Page Feedback | API

Component Managers - Creating And Destroying Active Grids

Using the Component Manager, you have the incredibly powerful ability to both create and destroy Active Grids at runtime. This gives you flexibility to change the patterns that are loaded on a large scale (versus changing them one by one via Active Grid methods) and also give you the freedom to change which Player is being tracked at any given time.

Destroyed Active Grids are always tracked and saved with persistent data, so that upon loading of that data the Active Grids that were previously destroyed can be removed from the scene.

You can also create Persistent Active Grids from Prototypes, which are automatically recreated when persistent data is loaded. Both of these factors allow you to switch between using different Active Grids without having to worry about saving/loading the data needed to restore their state between persistent gaming sessions.

Active Grid Prototypes

Active Grids are complex components that have complex relationships with other components and Scriptable Assets, as well as a myriad of settings. It would be incredibly difficult to establish these relationships and configure these settings at runtime. Fortunately, using Prototypes, this is not necessary..

An Active Grid Prototype is simply any Active Grid component placed on a deactivated Game Object. You can configure the Active Grid Prototype just as you would any other Active Grid, assigning Loading Blueprint Repositories, Worlds, Players, and configuring its settings as normal. You can then create Active Grids at runtime using the same settings and Components/Scriptable Assets assigned to the Prototype.

You can assign as many Prototypes as you wish to each Component Manager, allowing you to pick and choose which Prototypes are used to create runtime Active Grids in response to any criteria you wish.

Active Grid Prototypes are identified using their ID, so all Active Grid Prototypes in a scene must have unique IDs!

When a Runtime Persistent Active Grid exist at time of saving, this ID is saved and used to reconstruct the Active Grid when the data is loaded. As such, the ID should remain the same for the lifetime of your Application.

You can remove Prototypes at any time, however if Runtime Active Grids referencing the removed Prototype exists in persistent save data, they will be ignored (and not recreated) when that data is loaded.

Persistent vs Non Persistent Active Grids

Persistent Active Grids are Active Grids that persist between gaming sessions via Persistent Save Data. The Component Manager tracks the creation of Persistent Active Grids and saves information on their IDs (as well as the IDs of the prototypes used to construct them), so that it can recreate them whenever that data is loaded. Each Persistent Active Grid also has data specific to it that is tracked and saved, ensuring the state of that Active Grid is consistent between gaming sessions.

Non Persistent Active Grids, on the other hand, are not saved between gaming sessions. Whenever these Active Grids are destroyed or unloaded (as the result of a scene unload operation, for example), they are gone for good.

--Special Note--
Active Grids that are added to the scene in the Editor (and not used as Prototypes) by the developer are always Persistent. So long as you do not manually destroy them, they are always present when save data is loaded and data specific to them is always tracked and saved between gaming sessions.

Creation Methods

You can use the CreatePersistentActiveGrid, CreateNonPersistentActiveGridUsingTransform and/or CreateNonPersistentActiveGridUsingIPlayer methods to create persistent or non persistent Active Grids. The latter two methods are virtually the same except that they accept different Player types.

Notice that the only the Non Persistent versions accept alternate Player (and PlayerMover) objects. This is because the Player object is a reference type that cannot be resolved automatically when persistent save data is loaded. If we allowed setting an alternate Player on the Persistent Active Grid, when save data is loaded that causes that Active Grid to automatically be recreated, we would not be able to assign a Player object to it. For this reason, if you need to assign an alternative Player (alternative to the one assigned to the Prototype) to the Active Grid, you MUST create it as non persistent.

Besides this Player object and the ID of the prototype used to construct the Active Grid, each creation method allows you to assign an alternative World that the Active Grid will start synced to (passing in null is valid; in this case, the Active Grid will start synced to whatever World is assigned to the prototype in the inspector).

In the case of the Persistent Active Grid, however, the World you pass in must also be Persistent, to ensure that it can automatically be re-assigned to the Active Grid when persistent save data is loaded.

For Non Persistent Active Grids, you may assign either a Persistent or Non Persistent World; it makes no difference.

Create Persistent Active Grid API

Create Non Persistent Active Grid API

Note that while the created Active Grid may start synced to a World, Update World is always disabled for all Groupings on newly created Active Grids (even if it is enabled on the Prototype). This is intended to give you more control over the timing and mechanism of the initial loading of the World's Cells (and Asset Chunks). In order to load World Cells using the Active Grid, you must call {BoldTagOpen}TrySetIfWorldShouldBeUpdated{BoldTagClose} (or one of the similarly named methods).

TrySetIfWorldShouldBeUpdated API

--Special Note--
If you want to assign a runtime created World to a runtime created Active Grid, you must create the World first then pass it in to the Active Grid creation method via the alternateWorldToSyncTo argument.

Destruction Methods

You can use the DestroyActiveGrid or DestroyActiveGridAndWaitForCellUsersToBeRemoved method to destroy Active Grids at runtime. Under the hood, both methods use an IEnumerator based destruction method from the Active Grid class to destroy the Active Grid.

When an inspector created Persistent Active Grid is destroyed, its ID is recorded and saved with persistent data. When that data is loaded, the Active Grid is automatically destroyed. This is not necessary when destroying a runtime created Persistent Active Grid; instead, the ID of the runtime Active Grid is simply removed from the internal tracking so that it is not written to persistent save data.

This both reduces the amount of data needed to be saved and frees up the ID to be re-used.

Destroy Active Grid API

Destroy Active Grid & Wait API

DestroyActiveGrid is slightly easier to use as you call it like a normal method. Under the hood, however, StartCoroutine is called to run the Active Grid's destruction method. Not only will this generate garbage, you will not able to track the destruction which means you cannot time other code to the destruction.

DestroyActiveGridAndWaitForCellUsersToBeRemoved is more complicated to use, but it gives you the freedom to drive the enumerator in a garbage free way (at least it won't generate garbage at this point). In addition, you will have knowledge of when the enumerator finishes, which allows you to time code with the removal of the Cell Users from the World the Active Grid is synced to. Typically, a removal of Cell Users will correspond with the removal of World Cells (and Asset Chunks), however this is not guaranteed, as there may be other sources that are making use of the World Cells (other Active Grids, World Regions, etc.).

--Special Note--
DestroyActiveGridAndWaitForCellUsersToBeRemoved has a return type of IEnumerator. This return type is special as it allows the method to be iterated over, possibly over multiple frames. This allows the execution's performance impact to be spread out over multiple frames, which is awesome! There are two strategies for implementing methods with this return type:

1) Simply include yield return statements within the method's body where the returned object is either null or an instance of a YieldInstruction.

The compiler will auto generate a state machine class, which will be used to iterate the method's logic. The drawback of this technique is every time the method is called, a new instance of the auto generated class is created, resulting in garbage generation throughout the lifetime of the game.

2) Implement one of the reusable enumerator classes found within the API.

This strategy is harder to implement as you will need to implement the state machine logic yourself, as well as perform some other code related task necessary to use the reusable enumerators. It is recommended for experienced coders only!

If you elect to go with option 2, you can find detailed information on how to use the Reusable Enumerator classes in the Yield Enumerator Section within the Secondary Non Components Chapter.

Yield Enumerator Classes

--Special Note 2--
If you have a save file containing data related to an Inspector Created Active Grid and you remove that Active Grid from the scene within the Unity Editor, the next time you load the save file the data pertaining to the Active Grid is simply read in and discarded. This is useful if you have an already built game that you need to make changes to, as you can do so without worrying about exceptions being thrown, even though the save file contains data that is no longer used.