itchigo_kurosaki
itchigo_kurosaki

Reputation: 13

How do I select/call an Instantiated GameObject within an array without usind index

I'm currently working on a random grid generation base for game map and I'm kinda stuck at how do I call an instantiated object based on their in game coordinates (not Vector3).

This is my hex generation script:

public HexCell cellPrefab;
HexCell[] cells;

void CreateCell (int x, int z, int i) {

    Vector3 position;
    position.x = (x + z * 0.5f - z / 2) * (HexMetrics.innerRadius * 2f);
    position.y = 0f;
    position.z = z * (HexMetrics.outerRadius * 1.5f);

    HexCell cell = cells[i] = Instantiate<HexCell>(cellPrefab);
    cell.coordinates = HexCoordinates.FromOffsetCoordinates(x, z);
}

I can call the object fine using index of objects' array but I can't wrap my head around the idea of calling it based on its given coordinates.

This is how I give them coordinates based on each hex position;

public class HexCell : MonoBehaviour {
public HexCoordinates coordinates;
}

public struct HexCoordinates {

[SerializeField]
private int x, z;

public int X {
    get { return x; }
}

public int Y {
    get { return -X - Z; }
}

public int Z {
    get { return z; }
}

public HexCoordinates (int x, int z) {
    this.x = x;
    this.z = z;
}

public static HexCoordinates FromOffsetCoordinates (int x, int z) {
    return new HexCoordinates(x - z / 2, z);
}
}

So how do I call/select desired hex based on HexCell coordinates?

Upvotes: 1

Views: 124

Answers (2)

cwharris
cwharris

Reputation: 18125

Alternatively, you could use some built-in functions to make it more readable.

HexCell getHexCellFromCoordinate(int x, int y, int z)
{
    return cells.FirstOrDefault(
        cell =>
           cell.x == x &&
           cell.y == y &&
           cell.z == z
    );
}

HexCell getHexCellFromCoordinate(Vector3Int coord)
{
    return cells.FirstOrDefault(cell =>
         cell.x == coord.x &&
         cell.y == coord.y &&
         cell.z == coord.z
    );
}

It's worth noting, since I'm not sure where you'll be needing to find the cells, that FirstOrDefault makes heap allocations and therefore invoking it too often on too large of a list (as in tens of thousands of times per frame, and/or against tens of thousands of objects) it could result in undesired garbage collections, which may cause a stutter in your application, and that stutter may be noticeable if combined with other code that uses heap allocations willy-nilly.

So as a general rule, start with something simple. If your application starts to slow down or take up too much memory, go back and optimize starting with the hottest (least performant) code. You can use a profiler to help you find those spots. But please, don't riddle your code with for loops just to save some extra cpu cycles.

Upvotes: 0

Programmer
Programmer

Reputation: 125455

So how do I call/select desired hex based on HexCell coordinates?

This is easy to do since you used int instead of float to represent the coordinate. Just loop over the cells array. In each loop, access the coordinates variable from the HexCell component then compare x, y and z values. If they match, return the current HexCell in the loop. If not, simply return null. You can also do this with linq but avoid it.

Your cell array:

HexCell[] cells;

Get HexCell from coordinate:

HexCell getHexCellFromCoordinate(int x, int y, int z)
{
    //Loop thorugh each HexCell
    for (int i = 0; i < cells.Length; i++)
    {
        HexCoordinates hc = cells[i].coordinates;

        //Check if coordinate matches then return it
        if ((hc.X == x) && (hc.Y == y) && (hc.Z == z))
        {
            return cells[i];
        }
    }

    //No match. Return null
    return null;
}

Since the coordinate is in int instead of float, you can also use Vector3Int(Requires Unity 2017.2 and above) to represent them instead of x, y and z. Note that this is different from Vector3.

HexCell getHexCellFromCoordinate(Vector3Int coord)
{
    //Loop thorugh each HexCell
    for (int i = 0; i < cells.Length; i++)
    {
        HexCoordinates hc = cells[i].coordinates;

        //Check if coordinate matches then return it
        if ((hc.X == coord.x) && (hc.Y == coord.y) && (hc.Z == coord.z))
        {
            return cells[i];
        }
    }

    //No match. Return null
    return null;
}

Upvotes: 2

Related Questions