1
votes

I have been trying to work with Unity's pure ECS approach to make a basic nxn grid of tiles.

Before using ECS I would just use a 2d array Tiles[,] grid where I can simply index (x,y) to find the tile I want.

Now moving into ECS, I want to create an entity for each tile using an IComponentData struct like so:

public struct Tile : IComponentData
{
    public int xIndex;
    public int yIndex;

    public int isValid;
}

Somewhere during the start of my game I create the tile entities

    for (int i = 0; i < tilesInMap; i++)
    {
        Entity tileEntity = entityManager.CreateEntity(tileArchetype);

        int xIndex = i % terrainSize;
        int yIndex = i / terrainSize;

        entityManager.SetComponentData(tileEntity, new Position { Value = new float3(xIndex , 0, yIndex) });

        Tile newTile;
        newTile.xIndex = xIndex;
        newTIle.yIndex = yIndex;
        newTile.isValid = 1;

        entityManager.SetComponentData(tileEntity, newTile);
    }

Now somewhere else in my code I have a ComponentSystem that pulls in the tiles using a group struct

public struct TileGroup
{
    public readonly int Length;
    public EntityArray entity;
    public ComponentDataArray<Tile> tile;
}

[Inject] TileGroup m_tileGroup;

As far as I'm aware, as long as I don't change the archetype of any of those entities in the TileGroup (for instance by calling AddComponent or RemoveComponent), the ordering of that injected array will be preserved (I'm not even sure of that!)

So say in my OnUpdate method I want to "get the tile at grid coordinate (23, 43)". I can calculate this (assuming a 1d array of tiles with the order preserved) by

int arrayIndex = yIndex * tilesPerMapWidth + xIndex;

But this only works as long as the injected array order of tiles is preserved which I doubt it will be eventually.

So a few questions: 1. Should I ever rely on the order of an injected array for behaviour logic? 2. Are there any better methods in achieving what I want using ECS?

1
I don't know how Unity ECS works, but relying on assumptions (like the ordeR) is never a good idea. - sebas

1 Answers

0
votes

From the Unity forums, "Order of Entities":

  • ComponentDataArray<> / ComponentGroup makes zero gurantees on the actual ordering of your entities except for that its deterministic. But generally the indices are not stable. (E.g. Adding a component to an entity, will change the index in ComponentDataArray of that entity and likely of another one) The only stable id is the "Entity" ID.

To answer your questions:

So a few questions: 1. Should I ever rely on the order of an injected array for behaviour logic?

Based on "...makes zero guarantees on the actual ordering of your entities..." I would say no.

  1. Are there any better methods in achieving what I want using ECS?

You don't need arrayIndex to access entities in your tile group. You can iterate through the entities and access x and y for each to perform the required behavior. Depending on your actual functionality you may want to use the job system as well.

for (int i = 0; i < m_tileGroup.Length; i++) {
    int x = m_tileGroup.tile[i].xIndex;
    int y = m_tileGroup.tile[i].yIndex;
    // do something with x and y
}