1
\$\begingroup\$

I'm trying to get a 2d tilemap rendering but somethings not clicking with me about the 2d coordinates...

Here's my basic tilemap class -

public class Map : MonoBehaviour {
public Transform tilePrefab;

public int mapWidth;
public int mapHeight;
public Transform[,] map;

// Use this for initialization
void Start () {
    map = new Transform[mapWidth, mapHeight];

    for (int y = 0; y < mapHeight; y++)
    {
        for (int x = 0; x < mapWidth; x++)
        {
            Transform tile = Instantiate(tilePrefab, new Vector3 (x, y, 0), Quaternion.identity) as Transform;
            tile.parent = transform;
            map[x, y] = tile;
        }
    }
}

But this is rendering the tilemap from the origin - enter image description here

I want that tilemap to be dynamically centered on the camera like - enter image description here

What I can't seem to work out is how to dynamically work out the coordinates to move that tilemap so that it's centered in the camera after it has been created?

Any additional help, or pointers to some decent resources would be much appreciated, cheers.

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

you can make prefabs child of another object.so when you move parent , childs move along parent.then place it center of your scene.

 clone.transform.parent = newEmptyGameObject.transform;

create empty Transform as spawnPoint

    if (spawnPoint != null)
        newEmptyGameObject.transform.position = spawnPoint.position;

enter image description here

I wrote a quick sample, the grid is always centered to the spawn position. You can adjust the following:

  • number of objects in x and y direction, just like you already had it
  • distance between objects in x and y direction (seperately)
  • assign a transform which provides the spawn position, if it's null, the grid will stay at the world origin

enter image description here

Looks a bit confusing, but just to get an idea...

using UnityEngine;
using System.Collections.Generic;

public class GridManager : MonoBehaviour
{
    public int GridWidth;
    public int GridHeight;
    [Range(0,5)]
    public int distanceX;
    [Range(0,5)]
    public int distanceY;
    public Transform spawnPoint;
    public GameObject myPrefab;
    public List<GameObject> list = new List<GameObject>();

    void Start()
    {
        CreateGrid();
    }

    public void CreateGrid()
    {
        GameObject newEmptyGameObject = new GameObject("Grid");
        // following line is probably not neccessary
        newEmptyGameObject.transform.position = Vector3.zero;

        // some math to find the most left and bottom offset
        float offsetLeft = (-GridWidth / 2f) * distanceX + distanceX / 2f;
        float offsetBottom = (-GridHeight / 2f) * distanceY + distanceY / 2f;
        // set it as first spawn position (z=1 because you had it in your script)
        Vector3 nextPosition = new Vector3(offsetLeft, offsetBottom, 1f);

        for (int y = 0; y < GridHeight; y++)
        {
            for (int x = 0; x < GridWidth; x++)
            {
                GameObject clone = Instantiate(myPrefab, nextPosition, Quaternion.identity) as GameObject;
                clone.transform.parent = newEmptyGameObject.transform;
                // add to list
                list.Add(clone);

                // add x distance
                nextPosition.x += distanceX;
            }
            // reset x position and add y distance
            nextPosition.x = offsetLeft;
            nextPosition.y += distanceY;
        }
        // move the whole grid to the spawnPoint, if there is one
        if (spawnPoint != null)
            newEmptyGameObject.transform.position = spawnPoint.position;
    }
}

here you can change color of prefabs:

using UnityEngine;
using System.Collections;

public class Gem : MonoBehaviour
{
    private Color[] Colors = new Color[4] { Color.red, Color.blue, Color.green, Color.yellow };
    public int index;

    void Awake()
    {
        index = Random.Range(0, Colors.Length);
        var spriteRenderer = GetComponent<SpriteRenderer>();
        spriteRenderer.color = Colors[index];
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ Hey thanks for that, after looking at your offsetLeft/offsetBottom it's started to make sense. I've got a nicely aligned tileset now thanks :D \$\endgroup\$
    – Marklar
    Commented Dec 6, 2016 at 4:48
0
\$\begingroup\$

Looks like you've already gotten an answer, but here's a solution I implemented. My problem was similar to yours: I was procedurally generating a grid/tile-based level and I needed to center it in my camera view (at least with respect the y-axis). I actually created my grid such that it'd be centered already rather than creating the grid and moving all of the objects.

The code could definitely be improved: I've got a couple of "magic numbers" in there, and I've hard-coded things that should be programmatically determined. I'm definitely neither a C# nor Unity pro.

Another note: I also generate my level room-by-room and stitch them together, generating more level as (and if) the player progresses. Those influenced my solution a bit, but might not be relevant for your needs.

The currentSpace calculation in Start() begins in the top-left of the camera's field of view, leaving a little bit of space for UI elements. The currentSpace recalculations in PlaceRoom() for positioning to fill each column in one row in the inner loop, each start of a row in the middle loop, and the starting row and column for the room in the outermost loop.

Here's my relevant code:

void Start () {

    ...

    mainCam = GetComponent<Camera> ();
    sceneHeight = 2 * mainCam.orthographicSize;
    sceneWidth = sceneHeight*mainCam.aspect;
    blockSize = 0.16f;
    uiOffset = blockSize * 2;

    // currentSpace is how we tell where to put the blocks; we initialize it
    // like so to align it with the camera field-of-view
    currentSpace = new Vector2( -1*sceneWidth/2 + blockSize/2, 
        sceneHeight/2 - blockSize/2 - uiOffset );

    // Generate first x rooms
    ...

    for (int r = 0; r < nInitialRoom; r++) {
        PlaceRoom (lvl [r]);
    }
}

And:

void PlaceRoom( Room room ){
        int nRow = room.Height ();
        int nCol = room.Length ();
        SpaceType st = SpaceType.emptySpace;
        Vector2 roomStartSpace = currentSpace;

        for (int r = 0; r < nRow; r++ ){
            for (int c = 0; c < nCol; c++ ){
                st = (SpaceType)room.room[r, c];
                switch (st) {

                case SpaceType.blockSpace:
                    Instantiate (blockSpace, currentSpace, Quaternion.identity);
                    break;

                ...

                default:
                    break;
                }
                currentSpace = currentSpace + new Vector2(blockSize,0f);
            }
            currentSpace = new Vector2 (roomStartSpace.x, currentSpace.y - blockSize);
        }

        currentSpace = roomStartSpace + new Vector2 (blockSize * nCol, 0.0f);
    }
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .