1

I want to instantiate GameObjects(specifically hexagonal tiles) at the hexagonalCoodinates(hexcoordinates). For this I wrote a custom coordinate system. But I found out that unity doesn't accept anything other than Vector3 or transform. How do I make it do that? Or is there a easier way to do this?

This is the method to generate the gameObjects

private void TouchCell(Vector3 point)//This method instantiates cubes
    {
        point = transform.InverseTransformPoint(point);
         HexCoordinates coordinates = HexCoordinates.FromPosition(point);
        
        Instantiate(cubes, coordinates, Quaternion.identity);//<-The coordinate variable here is a hex coordinate.
        Debug.Log("Touched at:" + coordinates);
    }

And This is the Hex coordinate generator:

public struct HexCoordinates
{
    public int X { get; private set; }
    public int Z { get; private set; }
    public int Y { get
        {
            return -X - Z;
        } }
    public HexCoordinates(int x,int z)
    {
        X = x;
        Z = z;
    }
    public static HexCoordinates FromOffsetCoordinates(int x,int z)
    {
        return new HexCoordinates(x-z/2, z);
    }
    public override string ToString()
    {
        return "("+X.ToString()+","+Y.ToString()+","+Z.ToString()+")";
    }
    public string ToStringOnSeperateLines()
    {
        return X.ToString() + "\n" +Y.ToString()+ "\n" + Z.ToString();
    }

    public static HexCoordinates FromPosition(Vector3 point)//This converts the Vector3 to Hex coords
    {
       float x = point.x / (HexMetrics.InnerRadius * 2f);
        float y = -x;
        float offset = point.z / (HexMetrics.OuterRadius * 3f);
        x -= offset;
        y -= offset;
        int iX = Mathf.RoundToInt(x);
        int iY = Mathf.RoundToInt(y);
        int iZ = Mathf.RoundToInt(-x - y);
        if (iX + iY + iZ != 0)
        {
            float dX = Mathf.Abs(x-iX);
            float dY = Mathf.Abs(y - iY);
            float dZ = Mathf.Abs(-x-y-iZ);
            if(dX>dY&&dX>dZ)
            {
                iX = -iY - iZ;
            }
            else if(dZ>dY)
            {
                iZ = -iX - iY;
            }
        }
       return new HexCoordinates(iX,iZ);
   }
}
1
  • @Ruzihm I need to place the object at the center of the face of the generated hexagon(like minecraft but with hexagon). So using that Vector3 point doesn't solve the purpose. Commented Apr 25, 2021 at 7:15

2 Answers 2

0

Just convert from your HexCoordinates to Vector3 using any way:

  • create method for HexCoordinates, something like public Vector3 ToVector3() {...}
  • create implicit operator for implicit cast to Vector3
public struct HexCoordinates
{
    public int X { get; private set; }
    public int Z { get; private set; }
    public int Y => -X - Z;

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

    public static implicit operator Vector3(HexCoordinates coords)
    {
        Vector3 result = // convert to Vector3
        // Vector3 result = ToVector3() -- or like this for code reuse
        return result;
    }

    public Vector3 ToVector3()
    {
        Vector3 result = //convert to Vector3
        return result;
    }
}
  

And then you can extend Unity's Object class and add overloading for Instantiate() method that will accept HexCoordinates, convert to Vector3 and call Instantiate()

public static class ObjectExtension
{
    public static void Instantiate(this Object obj, Object origin, HexCoordinates coords, Quaternion q)
    {
        Vector3 position = coords.ToVector3();
        obj.Instantiate(origin, position, q);
    }
}

Also if you create implicit cast for your HexCoordinates to Vector3 you don't need to create overloading for Instantiate() method because converting will be implicitly

Sign up to request clarification or add additional context in comments.

1 Comment

While correct, this isn't super helpful... very much a "step 1 draw a circle step 2 draw the rest of the owl`
0

You are using using catlike coding's code. (This would have been helpful to mention in the question ;) ). In part 3 of the tutorial featuring this hex coordinate system, you can see how they would do something like below, accessing a hex inside of an array by calculating an index:

    public HexCell GetCell (Vector3 position) {
        position = transform.InverseTransformPoint(position);
        HexCoordinates coordinates = HexCoordinates.FromPosition(position);
        int index = coordinates.X + coordinates.Z * width + coordinates.Z / 2;
        return cells[index];
    }

So, since a HexCell has a transform.position, you can use that to get its center (making sure you don't access out of bounds):

    private void TouchCell(Vector3 point)
    {
        point = transform.InverseTransformPoint(point);
        HexCoordinates coordinates = HexCoordinates.FromPosition(point);
        int index = coordinates.X + coordinates.Z * width + coordinates.Z / 2;

        if (index >=0 && index < cells.Length)
        {
            Vector3 worldPos = cells[index].transform.position;        
            Instantiate(cubes, worldPos, Quaternion.identity);

            Debug.Log("Touched at:" + coordinates);
        }
    }

Better yet, it may be worthwhile to make a method to retrieve this index, for the sake of code reuse:

    private bool IsValidCellIndex(Vector3 point, out int index)
    {
        point = transform.InverseTransformPoint(point);
        HexCoordinates coordinates = HexCoordinates.FromPosition(point);
        index = coordinates.X + coordinates.Z * width + coordinates.Z / 2;

        return index >=0 && index < cells.Length;
    }

    private void TouchCell(Vector3 point)
    {
        if (IsValidCellIndex(point, out int index))
        {
            Vector3 worldPos = cells[index].transform.position;        
            Instantiate(cubes, worldPos, Quaternion.identity);

            Debug.Log("Touched at:" + worldPos);
        }
    }

Or, just use GetCell as the tutorial does :)

2 Comments

Thanks :).I did figure it out. and that is exactly how I did it
@LionCatDevStudio Was there something that turned out to be bad about this answer? I just got notified it lost accepted status. I can edit it to improve it if so.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.