Reputation: 13
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
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
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