Create a custom entity tile
Create a tile that stores data in native memory, so the Jobs system and the Burst compiler can store and retrieve the tile data to improve performance.
Note
You can't mix entity tiles and normal tiles. If you do, entity tiles fall back to not using the Job system or the Burst compiler.
Prerequisites
To create a custom entity tile, you must enable unsafe code methods in your project. Follow these steps:
- From the main menu, select Edit > Project Settings.
- Select the Player tab to open the Player settings window.
- Enable Allow 'unsafe' Code.
Note
Use unsafe methods with extreme caution to avoid memory leaks, access violations, or data corruption. The UnsafeUtility class is intended for scenarios where performance is critical, and the overhead of managed memory safety is prohibitive. For more information, refer to the UnsafeUtility API.
Write a custom entity tile script
Follow these steps:
Create a new C# script and include the following namespaces:
using System; using Unity.Collections.LowLevel.Unsafe; using Unity.Burst; using Unity.Mathematics; using AOT; using Unity.Tilemaps.Experimental;Create a class that implements
EntityIdTileBase.Inside the class, define a struct that stores the tile data in native memory. For example:
public struct MyTileData { public EntityId spriteEntityId; public Color color; public Matrix4x4 transform; }Create an abstract property that returns the type of the struct. For example:
public override Type structType { get => typeof(MyTileData); }Override the
OnEnablemethod to initialize the tile data. For example:public override void OnEnable() { base.OnEnable(); tileData = new MyTileData() { spriteEntityId = mySprite != null ? mySprite.GetEntityId() : EntityId.None, color = myColor, transform = myTransform, }; }You must also override
OnDisableif you allocate native memory, such as aNativeArray.Implement the
CopyDataStructmethod. In the method, use theCopyStructureToPtrAPI to copy data from your tile data instance to a pointer for the Jobs system.public override unsafe void CopyDataStruct(void* pointerForJobsSystem) { UnsafeUtility.CopyStructureToPtr(ref tileData, pointerForJobsSystem); }Implement the
RefreshTileJobDelegatedelegate method that the Jobs system uses to refresh tilemap positions when you place a tile. For example:protected override unsafe RefreshTileJobDelegate refreshTileJobDelegate => RefreshTileJob; // Indicate that the Burst Compiler can compile this method [BurstCompile] // Required attribute for the Jobs system [MonoPInvokeCallback(typeof(RefreshTileJobDelegate))] static unsafe void RefreshTileJob(int count, int3* position, void* data, ref TilemapRefreshStruct tilemapRefreshStruct) { // Call the RefreshTile method for each tile instance on the tilemap for (var i = 0; i < count; ++i) { tilemapRefreshStruct.RefreshTile(*(position + i)); } }The parameters Unity passes into the method are the following:
count: The number of tilemap positions that have this tile.position: The pointer to an array of the tilemap positions.data: The tile data from theCopyDataStructmethod.tilemapRefreshStruct: A struct that contains tilemap methods.
Implement the
GetTileDataJobDelegatedelegate method that the Jobs system uses to get tile data. For example:protected override unsafe GetTileDataJobDelegate getTileDataJobDelegate => GetTileDataJob; [BurstCompile] [MonoPInvokeCallback(typeof(GetTileDataJobDelegate))] static unsafe void GetTileDataJob(int count, int3* position, void* data, ref TilemapDataStruct tilemapDataStruct, TileData* outTileData) { var myTileData = UnsafeUtility.AsRef<MyTileData>(data); // Get the data for each tilemap position that has the tile for (var i = 0; i < count; ++i) { ref TileData tileData = ref *(outTileData + i); tileData.spriteEntityId = myTileData.spriteEntityId; tileData.color = myTileData.color; tileData.transform = myTileData.transform; } }The
CopyPtrToStructuremethod fills theoutTileDataparameter with the tile data.Implement the
GetTileAnimationDataJobDelegatedelegate method if your tile has animated properties. Otherwise implementnull. For more information, refer to the GetTileAnimationDataJobDelegate API.
The recommended best practice is to also implement the following TileBase methods in case the entity tile falls back to not using the Jobs system:
RefreshTileGetTileDataGetTileAnimationDataStartUp
For more information, refer to Scriptable tiles and the TileBase API.
Example
For a full example, in the Project window, go to the Packages/com.unity.2d.tilemap.extras/Tilemap/Runtime/Tiles/AnimatedEntityIdTile folder, then open the AnimatedEntityIdTile.cs script.