Tilemap Grid issue

Hey guys. so I have an interesting issue that I can’t seem to fix here.

Everything was working fine with my player spawning in and camera bounds set properly, then I moved my grid to a new area because the UI canvas was blocking it’s view.

Now my player nor camera load in where they are supposed to and it acts like my grid is in the old spot and I’ve checked everything out and I have no idea what else to do, so I figured I’d check in here.

It looks like it’s not updating the tilemap bounds even though it’s scripted and I’ve compressed the tilemap.

Hi, could you share more details of the Grid/Tilemap component and screenshots of the issues you are facing? Thanks!

So sorry for the delay, completely forgot about this. I never initially moved the parent object, I only moved the child objects. So I’m not sure if that’s what caused the issue.

If you can reproduce this issue and share more details about it, do let us know! Thanks!

So basically what happens is when I move the parent grid Unity is not setting the new tilemap bounds.

Even if I was to create a new grid in a different place it still acts like the bounds are in the old area.

I also use a camera controller that locks onto my player and my player has a setbounds script attached

public void SetBounds(Vector3 botLeft, Vector3 topRight)
    {
        bottomLeftLimit = botLeft + new Vector3(.5f, 1f, 0f);
        topRightLimit = topRight + new Vector3(-.5f,-1f, 0f);
    }

Camera Controller Script

void Start()
    {
        instance = this;

        //target = PlayerController.instance.transform;
        target = FindObjectOfType<PlayerController>().transform;

        halfHeight = Camera.main.orthographicSize;
        halfWidth = halfHeight * Camera.main.aspect;

        theMap.CompressBounds();
        bottomLeftLimit = theMap.localBounds.min + new Vector3 (halfWidth, halfHeight, 0f);
        topRightLimit = theMap.localBounds.max + new Vector3 (-halfWidth, -halfHeight, 0f);

        PlayerController.instance.SetBounds(theMap.localBounds.min, theMap.localBounds.max);
    }

    // LateUpdate is called once per frame after Update
    void LateUpdate()
    {
        transform.position = new Vector3(target.position.x, target.position.y, transform.position.z);

        //Keep the camera inside the bounds
        transform.position = new Vector3(Mathf.Clamp(transform.position.x, bottomLeftLimit.x, topRightLimit.x), Mathf.Clamp(transform.position.y, bottomLeftLimit.y, topRightLimit.y), transform.position.z);

        if(!musicStarted)
        {
            musicStarted = true;
            AudioManager.instance.PlayMusic(musicToPlay);
        }
    }

Tilemap.localBounds is in the local-space of the Tilemap GameObject (Unity - Scripting API: Tilemaps.Tilemap.localBounds). You will need to convert it to world-space if you are not tracking positions relative to the Tilemap GameObject.

Ah, thank you for the reply.

I’m guessing I need to use LocalToWorld? Still kinda new to scripting so just need a point in the right direction please :slight_smile:

Yes, you can use Tilemap.LocalToWorld to convert each point in the bounds to world-space.

I don’t understand why I can’t get it to work. No idea what I’m missing.

I can change it to LocalToWorld, but I get an error with it saying that it’s a method which is not valid in the given context.

Would it be possible to share the error as well as the code block here? You should be able to use LocalToWorld for your Tilemap component “theMap”.

public Tilemap theMap
Well I tried changing this

bottomLeftLimit = theMap.localBounds.min + new Vector3 (halfWidth, halfHeight, 0f);
topRightLimit = theMap.localBounds.max + new Vector3 (-halfWidth, -halfHeight, 0f);

To this

bottomLeftLimit = theMap.LocalToWorld.min + new Vector3 (halfWidth, halfHeight, 0f);
topRightLimit = theMap.LocalToWorld.max + new Vector3 (-halfWidth, -halfHeight, 0f);

I get this error here.
GridLayout.LocalToWorld(Vector3)’ is a method, which is not valid in the given context

Ah, I see. You should be using Tilemap.LocalToWorld to convert a coordinate from local to world space, for example:

bottomLeftLimit = theMap.LocalToWorld(theMap.localBounds.min) + new Vector3 (halfWidth, halfHeight, 0f);

Ok, it works, but I’m still getting an issue. Here’s what the camera does now as it doesn’t follow him. The white box is the camera, it just jumps from area to area instead of smoothly following
https://gyazo.com/b73aa969f7a08ef769c2b647f8ef599f

Camera Controller script

theMap.CompressBounds();
bottomLeftLimit = theMap.LocalToWorld(theMap.localBounds.min) + new Vector3(halfWidth, halfHeight, 0f);
topRightLimit = theMap.LocalToWorld(theMap.localBounds.min) + new Vector3 (-halfWidth, -halfHeight, 0f);

PlayerController.instance.SetBounds(theMap.localBounds.min, theMap.localBounds.max);

Player Controller script.

public void SetBounds(Vector3 botLeft, Vector3 topRight)
{
bottomLeftLimit = botLeft + new Vector3(.5f, 1f, 0f);
topRightLimit = topRight + new Vector3(-.5f,-1f, 0f);
}

Are these both right still?

Could you share how you are moving the camera?

You may want to add debug Inspectors for your Camera and Player Controllers to see if the values are updated correctly as you move your Player character.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;

public class CameraController : MonoBehaviour
{
public static CameraController instance;
public Transform target;

public Tilemap theMap;
private Vector3 bottomLeftLimit;
private Vector3 topRightLimit;

private float halfHeight;
private float halfWidth;

public int musicToPlay;
private bool musicStarted;

// Start is called before the first frame update
void Start()
{
instance = this;

//target = PlayerController.instance.transform;
target = FindObjectOfType<PlayerController>().transform;

halfHeight = Camera.main.orthographicSize;
halfWidth = halfHeight * Camera.main.aspect;

theMap.CompressBounds();
bottomLeftLimit = theMap.LocalToWorld(theMap.localBounds.min) + new Vector3(halfWidth, halfHeight, 0f);
topRightLimit = theMap.LocalToWorld(theMap.localBounds.min) + new Vector3 (-halfWidth, -halfHeight, 0f);

PlayerController.instance.SetBounds(theMap.localBounds.min, theMap.localBounds.max);
}

// LateUpdate is called once per frame after Update
void LateUpdate()
{
transform.position = new Vector3(target.position.x, target.position.y, transform.position.z);

//Keep the camera inside the bounds
transform.position = new Vector3(Mathf.Clamp(transform.position.x, bottomLeftLimit.x, topRightLimit.x), Mathf.Clamp(transform.position.y, bottomLeftLimit.y, topRightLimit.y), transform.position.z);

if(!musicStarted)
{
musicStarted = true;
AudioManager.instance.PlayMusic(musicToPlay);
}
}
}

I can definitely hook up some Debug lines and see what’s going on as well.

Sounds good!

topRightLimit = theMap.LocalToWorld(theMap.localBounds.min) + new Vector3 (-halfWidth, -halfHeight, 0f);

I guess the topRightLimit should be the maximum bounds of your Tilemap?

Yep! those are the max limits corner to corner

Do you guys have any idea why this could be doing this? If I never move the tilemap’s grid or child grids it’s perfectly fine. But the minute I move any of those things it breaks.

It works fine with the localBounds before moving the grid as well.

As mentioned, adding Debug lines or a Debug inspector will help a lot to figure out the issue. The items you would need to check when you move the grids are: are the bottomLeftLimit and topRightLimit values correct, are the bounds of your PlayerController updated correctly and is the Camera’s position clamped correctly?