Hi, I’ve been banging my head against this problem for over a day now, and I’m sure I’m missing something really straightforward, please help!
I’ve tried to simplify the problem, so made the test script below which is called in start:
void Test(int q, int r, int elevation)
{
HexCoord h = GetHexAt(q, r);
h.elevation = elevation;
Debug.Log($"elevation {h.elevation}"); //this outputs 1
Debug.Log($"elevation {hexes[q,r].elevation}"); //this outputs 0
//hexes[q, r].elevation = elevation;
UpdateHexVisuals();
}
public HexCoord GetHexAt(int q, int r) {
return hexes[q, r];
}
I would expect both of my debug.log entries to be 1, but they aren’t.
The commented code below the debug.log works, and everything behaves correctly. I realise in this instance there isn’t much benefit in factoring out this code, but it is useful in the bigger picture.
I’d be grateful if someone could explain why assigning elevation via this method doesn’t seem to be actually changing the elevation of the object in the hexes array.
Full code below.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class MapAxial : MonoBehaviour
{
public GameObject HexPrefab;
public Mesh meshWater;
public Mesh meshFlat;
public Mesh meshRaised;
public Mesh meshCliff;
public Material MatDesert;
public Material MatRock;
public Material MatGrass;
public Material MatWater;
public Material MatCliff;
public int mapHeight; //in hexes
public int mapWidth; //in hexes
protected HexCoord[,] hexes;
protected Dictionary<HexCoord, GameObject> hexToGameObjectMap;
void Start()
{
GenerateMap();
Test(2,2,1);
}
void Test(int q, int r, int elevation)
{
HexCoord h = GetHexAt(q, r);
h.elevation = elevation;
Debug.Log($"elevation {h.elevation}"); //this outputs 1
Debug.Log($"elevation {hexes[q,r].elevation}"); //this outputs 0
//hexes[q, r].elevation = elevation;
UpdateHexVisuals();
}
public HexCoord GetHexAt(int q, int r) {
return hexes[q, r];
}
virtual public void GenerateMap() {
hexes = new HexCoord[mapWidth, mapHeight]; //create array to store hexCoord structs
hexToGameObjectMap = new Dictionary<HexCoord, GameObject>(); //create dictionary
//Generate a flat map
for (int column = 0; column < mapWidth; column++)
{
for (int row = 0; row < mapHeight; row++)
{
//add new HexCoord to array
HexCoord h = new HexCoord(column, row);
hexes[column, row] = h;
//instantiate hex GameObject and position it using method in HexCoord
GameObject hex_go = (GameObject)Instantiate(HexPrefab, h.WorldPosition(), Quaternion.identity, this.transform);
//name the new hex GameObject in the hierarchy
hex_go.name = "hex_" + column + "_" + row;
//map the game object to the data structure in the dictionary
hexToGameObjectMap[h] = hex_go;
StaticBatchingUtility.Combine(this.gameObject);
}
}
UpdateHexVisuals();
}
public void UpdateHexVisuals()
{
for (int column = 0; column < mapWidth; column++)
{
for (int row = 0; row < mapHeight; row++)
{
HexCoord h = hexes[column, row];
GameObject hex_go = hexToGameObjectMap[h];
//get meshrenderer of hex gameObject and assign it default desert material
MeshRenderer mr = hex_go.GetComponentInChildren<MeshRenderer>();
mr.material = MatDesert;
if (h.elevation > 0)
{
Debug.Log($" Q {h.Q} R{h.R}");
mr.material = MatGrass;
}
//get meshfilter of hex gameobject and assign it flat mesh as a default
MeshFilter mf = hex_go.GetComponentInChildren<MeshFilter>();
mf.mesh = meshFlat;
}
}
}
HexCoord, adapted from this code on GitHub (GitHub - akhra/HexCoord: Hexagon Grid Coordinate System for Unity/C#)
public struct HexCoord
{
/// <summary>
/// Position on the q axis.
/// </summary>
[SerializeField]
public int Q;
/// <summary>
/// Position on the r axis.
/// </summary>
[SerializeField]
public int R;
public float elevation;
/// <summary>
/// Initializes a new instance of the <see cref="Settworks.Hexagons.HexCoord"/> struct.
/// </summary>
/// <param name="q">Position on the q axis.</param>
/// <param name="r">Position on the r axis.</param>
public HexCoord(int q, int r)
{
this.Q = q;
this.R = r;
this.elevation=0;
Debug.Log("this code called");
}
/// <summary>
/// Position on the cubic z axis.
/// </summary>
/// <remarks>
/// The q,r coordinate system is derived from an x,y,z cubic system with the constraint that x + y + z = 0.
/// Where x = q and y = r, this property derives z as <c>-q-r</c>.
/// </remarks>
public int S
{
get { return -Q - R; }
}
/// <summary>
/// Offset x coordinate.
/// </summary>
/// <remarks>
/// Offset coordinates are a common alternative for hexagons, allowing pseudo-square grid operations.
/// Where y = r, this property represents the x coordinate as <c>q + r/2</c>.
/// </remarks>
public int O
{
get { return Q + (R >> 1); }
}
/// <summary>
/// Unity position of this hex.
/// </summary>
public Vector2 Position()
{
return Q * Q_XY + R * R_XY;
}
public Vector3 WorldPosition() {
float x = Position().x;
float y = 0; //could change to elevation??
float z = Position().y;
return new Vector3(x, y, z);
}
static readonly Vector2 Q_XY = new Vector2(SQRT3, 0);
static readonly Vector2 R_XY = new Vector2(SQRT3 / 2, 1.5f);
static readonly Vector2 X_QR = new Vector2(SQRT3 / 3, 0);
static readonly Vector2 Y_QR = new Vector2(-1 / 3f, 2 / 3f);
}