ChunkManager Abstract Class

public abstract class ChunkManager : MonoBehaviour

Provides a base implementation for Chunk Managers. These managers perform two tasks:

1) They provide implementations for Asset Chunk Type specific logic, like getting/setting chunk positions and activating/deactivated asset chunks.

2) They interface between the World and Chunk Streamers. When the World needs chunks for one or more World Cells, it requests them from the Chunk Manager assigned to a particular LOD. The manager may have the needed chunks already (if using a pooling manager), however if it does not, it requests new chunks be streamed in via the Chunk Streamer assigned to the same LOD. In addition, when the World no longer needs a World Cell, the World Cell is sent to the manager so that its chunks can be processed. The manager may choose to pool the chunks, or unload them from the scene (via the Chunk Streamer). This strategy allows for different chunk life cycle management strategies to be employed, including custom ones you write yourself.

The provided default managers are the NonPoolingChunkManager , PoolingChunkManager, and DistanceBasedPoolingChunkManager .

The actual method of loading new chunks into the scene and unloading uneeded chunks from the scene is left up to the Chunk Streamer you are using. Think of the Chunk Manager not as a creator/destroyer, but as a manager that determines whether uneeded objects should be kept in the scene, and if so, managing the lifetime of them so that they can be reused in the future. You can also think of it as specific logic that targets the exact type of objects you are using.

All Chunk Managers are configured to work with any chunk (both game object based and non game object based), however there are certain methods of the Chunk Manager class that are by default, configured to work with Game Objects. Those methods include:

GetChunkPosition - For retrieving the Vector3Double position of a chunk. Only called if the LOD using this manager has 'Chunks Use Positional Data' enabled (this setting can be found on your Streamable Grid asset).

SetChunkPosition - For setting the chunk position to a Vector3Double value. Only called if the LOD using this manager has 'Chunks Use Positional Data' enabled (this setting can be found on your Streamable Grid asset).

SetChunkActiveState - For setting the state of the chunk to active or deactive. This method is called only if Auto Activate/Deactivate Cell Chunks is enabled in your World inspector, for any LODs that use this manager.

If you anticipate any of these methods being called, you will need to create a custom class deriving from this one or one of the existing Chunk Managers, and in that class override the methods that will be called, so that they function correctly with your custom chunks.

Additional Note: This component contains its own special class (ChunkManagerUser) which enables multiple users to use the manager at the same time. The data associated with each user is stored in this user object and retrieved using the userID passed into each method.

This user object does not contain any data by default other than the ILODGroup object associated with the user and the chunkStreamerUserID of the user (in reference to the Chunk Streamer it uses). You can access the user object via the RegisteredUsers property and userID, like so: RegisteredUsers[userID].

You may also create your own custom user object class which derives from ChunkManagerUser, in order to store custom data or add custom methods. In fact, this strategy is utilized by some of the other Chunk Managers in the kit. Simply override the CreateNewUser method and return your custom user object.

The properties, methods, and constructors of this ChunkManagerUser class have been included on this webpage along side the other members of the ChunkManager class. You can easily identify them as their member names include a ChunkManagerUser prefix. You can use these as a reference when creating custom ChunkManagerUser classes.

You should never have to interact directly with the Chunk Manager unless deriving from it, as its methods/properties are called/used as needed by the Streamable Assets Manager automatically.

Properties

Name Type Description
AttachmentProgress float

Tracks the progress of this Chunk Manager's current AttachChunksToCells method call as a value between 0 (no chunks attached) and 1 (all chunks attached). The progress is calculated automatically by the base Chunk Manager class. It does so by calculating the total number of Asset Chunks that need to be attached. After AttachChunksAlreadyInSceneToCells is called, it increments the progress by a value equal to total reused chunks / total chunks to attach. The remaining Cell's that still need Chunks are passed to the LOD Group's Chunk Streamer. The progress from the Chunk Streamer is then used to increment the AttachmentProgress the rest of the way to 1.

ChunkManagerUser.ChunkManager ChunkManager

Gets the Chunk Manager instance that created this user object.

ChunkManagerUser.ChunkStreamerUserID int

Gets the User ID of the LOD Group that was assigned to it by the Chunk Streamer when it was registered with it.

ChunkManagerUser.LODGroup ILODGroup

Gets the LOD Group this user object is associated with.

ChunkManagerUser.StreamableGrid StreamableGrid

Get the Streamable Grid associated with the LOD Group.

ChunkReusePossible bool

Gets a value indicating whether chunk reuse is possible on this manager. Reuse allows chunks from one World Cell to be used by another. This just returns the value as set in the inspector of your manager, which is by default set to true, as reuse is an invaluable means of removing some unecessary loading and unloading.

When true, the managers ChunkReuseJudge is used to determine if a deactivated World Cell's chunks can be reused on a World Cell that is soon to be activated. If the reuse judge determines that objects can be reused, the chunks are transferred from the old World Cell to the new World Cell, reducing the number of new assets that need to be streamed in.

You can set the setting to false in the inspector, which is especially useful if you know that reuse is impossible.

For instance, imagine a scenario where the manager is used to load unique per World Cell chunks. Reuse would only be possible on two World Cells with the same Streamable Grid Cell index in this scenario. If, however, the World is not endless, there would never be a situation where a deactivated World Cell and new World Cell (that is soon to be activated) both exist with the same Streamable Grid Cell index. Thus, reuse would be impossible. By setting this value to false, some overhead related to checking for reuse potential is eliminated, which should result in slightly faster loading and unloading.

With that said, you should take extreme care when setting the value to false, as it will disable all attempts to reuse objects on whatever worlds/World Groupings, and/or LODs that are using the manager, which may eliminate some potential performance boosts.

Also note that Chunk Reuse does not apply to pooling logic on any derived Chunk Managers. If you want to create a pooling manager that allows chunks from different Streamable Grid Cell's to be used interchangeably, you will need to create a custom manager that does so.

RegisteredUsers RegistrationHandler<ChunkManagerUser>

Gets the users registered with the manager.

Constructors

ChunkManagerUser.ChunkManagerUser(ChunkManager, ILODGroup, int)

public ChunkManagerUser(ChunkManager chunkManager, ILODGroup LODGroup, int chunkStreamerUserID)

Create an instance of the Chunk Manager User object. If you are overriding the ChunkManager class and not overriding the ChunkManagerUser, you can create a new instance of this user object via this constructor, which can be returned in the ChunkManager's CreateNewUser method.

If you are overriding ChunkManagerUser, your custom user class will need constructors with at least these parameters (but can also have more), and they must also call the base constructor, which is accomplished by placing : (chunkManager, LODGroup, chunkStreamerUserID) after your constructor declaration.

Note, this construct can only be used from a class deriving from ChunkManager or ChunkManagerUser.

Parameters

Name Type Description
chunkManager ChunkManager

The parent Chunk Manager instance creating the user object.

LODGroup ILODGroup

The LOD Group the user object is being created for.

chunkStreamerUserID int

The User ID of the LOD Group that was assigned to it by the Chunk Streamer when it was registered with it.

Methods

AttachChunksAlreadyInSceneToCells(List<WorldCell>, ChunkManagerUser)

protected virtual IEnumerator<YieldInstruction> AttachChunksAlreadyInSceneToCells(List<WorldCell> cells, ChunkManagerUser user)

When overridden in a derived class, attaches any chunks already in the scene to the appropriate cells over multiple frames.

Overriding this method is optional. If you don't, all cells will be sent to the Chunk Streamer for it to stream new chunks into the scene.

If you do have chunks to attach, you must attach all chunks needed by the cell using the WorldCell.AttachChunkToCell method, and then remove the cell from the list so that it is not sent to the Chunk Streamer (otherwise, uneeded objects will be loaded into the scene!).

Never store the World Cells themselves for later use; only store non reference data associated with the World Cells (although, for this method, that should not be needed).

Parameters

Name Type Description
cells List<WorldCell>

The cells that need chunks attached.

user ChunkManagerUser

The user requesting the attachment.

Returns

IEnumerator<YieldInstruction>
An IEnumerator<YieldInstruction> that can be iterated over or used as a coroutine. See the YieldInstruction page for more info.


AttachChunksAlreadyInSceneToCellsInSingleFrame(List<WorldCell>, ChunkManagerUser)

protected virtual void AttachChunksAlreadyInSceneToCellsInSingleFrame(List<WorldCell> cells, ChunkManagerUser user)

When overridden in a derived class, attaches any chunks already in the scene to the appropriate cells in a single frame.

Overriding this method is optional. If you don't, all cells will be sent to the Chunk Streamer for it to load new chunks into the scene.

If you do have chunks to attach, you must attach all chunks needed by the cell using the WorldCell.AttachChunkToCell method, and then remove the cell from the list so that it is not sent to the Chunk Streamer (otherwise, uneeded chunks will be loaded into the scene!).

Parameters

Name Type Description
cells List<WorldCell>

The cells that need chunks attached.

user ChunkManagerUser

The user requesting the attachment.


AttachChunksToCells(List<WorldCell>, int)

public IEnumerator<YieldInstruction> AttachChunksToCells(List<WorldCell> cells, int userID)

Attaches chunks to the list of passed in cells. This is done by first calling the AttachChunksAlreadyInSceneToCells method. If any cells still need objects after calling this method, they are passed to the attached Chunk Streamer, which carries out this function.

Parameters

Name Type Description
cells List<WorldCell>

The cells whose objects need to be attached.

userID int

The ID of the user requesting the attachment.

Returns

IEnumerator<YieldInstruction>
An IEnumerator<YieldInstruction> that can be iterated over or used as a coroutine. See the YieldInstruction page for more info.


AttachChunksToCellsInSingleFrame(List<WorldCell>, int)

public abstract void AttachChunksToCellsInSingleFrame(List<WorldCell> cells, int userID)

Attaches chunks to the list of passed in cells in a single frame. This is done by first calling the AttachChunksAlreadyInSceneToCellsInSingleFrame method. If any cells still need chunks after calling this method, they are passed to the Chunk Streamer associated with the user, which carries out this function.

Parameters

Name Type Description
cells List<WorldCell>

The cells that need chunks attached.

userID int

The ID of the user requesting the attachment.


Awake()

protected void Awake()

The Chunk Manager's Awake method, called by Unity. You cannot utilize Awake in your derived class. If you need to perform some sort of Awake related logic, override the AwakeExtended method, which will be called by this classes Awake method. Also note that you do not need to call base.AwakeExtended(); from your AwakeExtended method, as this is a virtual empty method that does nothing unless you override it. Also note that this method is protected simply so that if you derive from this class, you will see an error when trying to add the Awake method.


AwakeExtended()

protected virtual void AwakeExtended()

Can be overriden to perform logic that would normally go in Awake (which is used by the base class). Use this instead of implementing Awake! You do not need to call base.AwakeExtended if you override this, as the base method is empty.


CreateNewUser(ILODGroup, int)

protected virtual ChunkManagerUser CreateNewUser(ILODGroup LODGroup, int chunkStreamerUserID)

Method used to create a new user object during user registration. This can be overridden to return a custom user object. User objects store pertitent information about a particular LODGroup. They allow the Chunk Manager to be used with multiple LOD's.

Parameters

Name Type Description
LODGroup ILODGroup

The lod group that the user object is being created for.

chunkStreamerUserID int

When the LODGroup registered with the manager, the manager automatically registered the LODGroup with the Chunk Streamer associated with it. This is the user ID assigned to the LODGroup by that Chunk Streamer, and can be used if you need to interface with the Chunk Streamer for some reason.

Returns

ChunkManagerUser
The new user created, which may be a basic ChunkManagerUser or may be a custom user object as returned by the derived Chunk Manager.


DeRegister(int)

public void DeRegister(int userID)

A user can call this method to de register with the Chunk Manager. The Chunk Manager will also automatically de-register the LOD Group with its assigned Chunk Streamer.

Parameters

Name Type Description
userID int

The ID of the user to de register.


DetachAndProcessChunksFromDeactivatedCells(List<WorldCell>, int)

public abstract IEnumerator<YieldInstruction> DetachAndProcessChunksFromDeactivatedCells(List<WorldCell> cells, int userID)

Detaches and processes the chunks associated with the input cells over a period of frames.

This method first calls the DetachAndProcessChunksToKeepInScene method, which is implemented by derived classes. This method loops through the list of cells and determines if any of them can be reused or otherwise do not need to be unloaded from the scene. It removes those cells from the list and stores or does whatever with the chunks (chunks).

If there are any cells remaining, they are sent to the Chunk Streamer via its DetachAndUnloadChunksFromCells method so that the objects associated with the cells can be unloaded.

Please note, previously this method was abstract and had to be implemented by derived classes. The new method to implement is DetachAndProcessChunksFromDeactivatedCells, which should do pretty much the same thing, except cells from the list need to be removed if you don't want their objects to be unloaded, and you must not do any sort of object unloading yourself.

Parameters

Name Type Description
deactivatedCells List<WorldCell>

The cells whose objects need to be detached and processed.

userID int

The ID of the user requesting the detachment and processing.

Returns

IEnumerator<YieldInstruction>
An IEnumerator<YieldInstruction> that can be iterated over or used as a coroutine. See the YieldInstruction page for more info.


DetachAndProcessChunksToKeepInScene(List<WorldCell>, ChunkManagerUser)

protected virtual IEnumerator<YieldInstruction> DetachAndProcessChunksToKeepInScene(List<WorldCell> cells, ChunkManagerUser user)

Optionally overridable method that should detach and processes the objects associated with the input cells over a period of frames, but only for cells with objects that should be kept in the scene. For example, if using a pooling system, this method would store the objects for any cells determined to be reusable. When such reusable cells are found, you must remove the World Cell from the list, and you must remove all chunks belonging to the cell. As such, it is best to process the list of cell in descending order so that you can remove them as you go.

Once this processing is complete, any remaining cells are passed along to the Chunk Streamer to be unloaded from the scene.

If you are NOT using a pooling solution or otherwise don't want to keep any objects in the scene, you can choose to NOT override this method, however consider that there is very little point in creating a custom Chunk Manager if you are not retaining objects in the scene.

It's also important to note that you SHOULD not store the World Cells themselves for later use, for example for the purpose of determining if specific objects can be reused by another World Cell down the line. Instead, store non reference data of the World Cell, such as its CellOnStreamableGrid or CellOnEndlessGrid, and use that data instead to make those determinations.

The reason is, internally SAM keeps track of these World Cells and once this method is finished executing, it clears the World Cell's data and returns them to an internal pool to be reused, thus conserving memory. The input list is a duplicated list, therefore removing a World Cell from the list does not effect this process.

Parameters

Name Type Description
deactivatedCells List<WorldCell>

The cells whose objects need to be detached and processed.

user ChunkManagerUser

The user requesting the detachment and processing.

Returns

IEnumerator<YieldInstruction>
An IEnumerator<YieldInstruction> that can be iterated over or used as a coroutine. See the YieldInstruction page for more info.


GetChunkActiveState(object)

public virtual bool GetChunkActiveState(object chunk)

Gets the active state of the chunk. This is not necessarily whether the chunk is active in the scene view, but should be instead the active state of the chunk itself (such as activeSelf).

Parameters

Name Type Description
chunk System.Object

The chunk whose position should be set.

Returns

bool
True if the chunk is active, false otherwise. For Game Objects (which the default implementation assumes the chunk is) this returns the activeSelf property, meaning the chunk may not actually be active in the scene.


GetChunkPosition(object)

public virtual Vector3Double GetChunkPosition(object chunk)

Default implementation to get the position of a single asset chunk associated with a World Cell.

The default behaviour is to simply get the transform position of the chunk, which assumes the chunk is a GameObject. You can override this using a custom manager if your objects are not traditional game objects (and thus do not have transform components), however you only need to do so if you have indicated on your Streamable Grid LOD that the objects use positional data, or if the objects are Terrain.

Parameters

Name Type Description
chunk System.Object

The chunk whose position to get.

Returns

Vector3Double.html
The Chunk's position as a Vector3Double.


GetChunkStreamerIDOfUser(int)

public int GetChunkStreamerIDOfUser(int userID)

Can be used to retrieve the chunk streamer ID of a given Chunk Manager user.

Parameters

Name Type Description
userID int

the ID of the chunk manager user.

Returns

int
The chunk streamer user ID.


OnDestroy()

protected void OnDestroy()

The Chunk Manager's OnDestroy method, called by Unity. You cannot utilize OnDestroy in your derived class, if you need to perform some sort of OnDestroy related logic, override the OnDestroyExtended method, which will be called by this classes OnDestroy method. Also note that you do not need to call base.OnDestroyExtended(); from your OnDestroyExtended method, as this is a virtual empty method that does nothing unless you override it. Also note that this method is protected simply so that if you derive from this class, you will see an error when trying to add the OnDestroy method.


OnDestroyExtended()

protected virtual void OnDestroyExtended()

Can be overriden to perform logic that would normally go in OnDestroy (which is used by the base class). Use this instead of implementing OnDestroy! You do not need to call base.OnDestroyExtended if you override this, as the base method is empty.


OnUserDeRegistered(ChunkManagerUser)

public virtual void OnUserDeRegistered((ChunkManagerUser user)

Called just after a user has been deregistered by the Chunk Manager. You can override this in a custom manager to perform additional post-deregistration logic on a per user basis.

Parameters

Name Type Description
user ChunkManagerUser

The user that has just beeen deregistered.


OnUserDeRegistering(ChunkManagerUser)

public virtual void OnUserDeRegistering((ChunkManagerUser user)

Called just before a user is deregistered by the Chunk Manager. You can override this in a custom manager to perform additional pre-deregistration logic on a per user basis.

Parameters

Name Type Description
user ChunkManagerUser

The user that is about to be deregistered.


OnUserRegistered(ChunkManagerUser)

public virtual void OnUserRegistered((ChunkManagerUser user)

Called just after a user has been registered by the Chunk Manager. You can override this in a custom manager to perform additional post-registration logic on a per user basis.

Parameters

Name Type Description
user ChunkManagerUser

The user that has just beeen registered.


Register(ILODGroup, out int)

public void Register(ILODGroup LODGroup, out int userID)

A user can call this method to register with the Chunk Manager. The userID must be stored by the user and passed in when calling the methods of the Chunk Manager.

The Chunk Manager automatically registers the LOD Group with its assigned Chunk Streamer as well.

Parameters

Name Type Description
LODGroup ILODGroup

The lod group being registered.

userID int

An ID that is assigned to the user when this method is called. Each user has its own ChunkManagerUser object created for it.


SetChunkActiveState(object, bool)

public virtual void SetChunkActiveState(object chunk, bool isActive)

Default implementation to set the chunk for a World Cell as active or deactive. The default behaviour, which calls GameObject.SetActive, should be sufficient if your chunks are normal Unity Game Objects. Typically, you would only override this method if using non game objects.

Also note that this method is only called if either 'Auto Activate Chunks When Adding Cells' or 'Auto Deactivate Chunks When Removing Cells' are enabled for the LOD using your Chunk Manager, so if these options would always be disabled, there is no need to override this method.

Parameters

Name Type Description
chunk System.Object

The chunk to set to active or deactive.

isActive bool

True if the chunk should be set to active, false if it should be set to deactive.


SetChunkPosition(object, Vector3Double)

public virtual void SetChunkPosition(object chunk, Vector3Double position)

Default implementation to set the position of a single chunk associated with a World Cell.

The default behaviour is to simply set the transform position of the object to the passed in position. You can override this using a custom manager, which would typically be done for one of two reasons.

1) If you do not need your chunks to be positioned (i.e., the position of the chunks does not matter, in which case setting the position is an uneccesary performance hit).

2) If your chunks are not traditional GameObjects and thus cannot be positioned using a transform component.

Note, you only need to do so if you have indicated on your Streamable Grid LOD that the objects use positional data, or if the objects are Terrain.

Parameters

Name Type Description
chunk System.Object

The chunk whose position should be set.

position Vector3Double

The position to set the chunk to.