Finding Objects' XY Positions in 2D Array Grid

I have a GridManager object in my scene that has script GridScript:

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

public class GridScript : MonoBehaviour
{
    public Sprite sprite;

    public float[,] grid;
    int vertical, horizontal, columns, rows;
    Camera cam;

    private float colorR, colorG, colorB;

    // Start is called before the first frame update
    void Start()
    {
        cam = Camera.main;

        vertical = (int)cam.orthographicSize;
        horizontal = vertical * (Screen.width / Screen.height);
        columns = horizontal * 2;
        rows = vertical * 2;
        grid = new float[columns, rows];

        for (int i = 0; i < columns; i++)
        {
            for (int j = 0; j < rows; j++)
            {
                colorR = Random.Range(0.0f, 1.0f);
                colorG = Random.Range(0.0f, 1.0f);
                colorB = Random.Range(0.0f, 1.0f);
                spawnTile(i, j, colorR, colorG, colorB);
            }
        }
    }

    private void spawnTile(int x, int y, float red, float green, float blue)
    {
        GameObject g = new GameObject("x: " + x + "y: " + y);
        g.transform.position = new Vector3(x - (horizontal - 0.5f), y - (vertical - 0.5f));

        var s = g.AddComponent<SpriteRenderer>();
        s.sprite = sprite;
        s.color = new Color(red, green, blue);
    }

    // Update is called once per frame
    void Update()
    {
       
    }
}

I made this script following a YouTube tutorial, and modified it a little bit to make the sprites (which existed just to test to see if the grid generation was working) multicolored instead of grayscale. Anyways, now that I have a grid setup I’d like to try and find other objects’ positions within this grid in terms of X and Y. The ultimate goal is to check from my player to see if obstacles are in a cell next to the player before trying to move the player. If there’s a non-passable object in the way, I’ll negate player movement in that direction. I was thinking I’d have a game object for ‘Objects’ (non-passable obstacles) where I draw my obstacles from a tilemap, but beyond that I’m not really sure where to start. Might someone be willing to help me figure out how to achieve this?

If you’re doing a grid, track your object positions directly in the grid coordinates and store references to what is in each cell, perhaps in a 2D array, or even in a Dictionary indexed by an XY struct of some kind, such as Vector2Int

Then you can always just ask what is at the next proposed grid position you want to move to.

For a full example of this, look in my Proximity Buttons project… search it for “grid” and try those scenes out.

proximity_buttons is presently hosted at these locations:

https://bitbucket.org/kurtdekker/proximity_buttons

https://github.com/kurtdekker/proximity_buttons

I can’t get that project to open in my Unity Editor for some reason…keeps hanging while importing assets. In any case, could you explain how I would go about tracking player position in the grid? Do I need to somehow convert transform position of my player object to x/y int’s within the script? If so, is it better to do it in the player movement script or on the grid script? Then I assume I’d have to also keep track of my obstacles’ positions in this same manner? Will Unity be able to tell what cells I’ve drawn tiles on within my Obstacles object? (As opposed to having new objects for every obstacle or something)

On a slightly separate note, I’ve noticed my grid fills up the full height of the camera (as expected), but not the full width, even though I did the whole vertical times the aspect ratio thing. Will my grid need to fill up just the camera/screen? Or will it have to fill up the entire map in the scene?

More so the point is that you needn’t do any conversions from world space to your grid space if you track the player’s position in the grid. You just check the grid indicies around the player.

Eg, if your player is in grid index (2, 2), then you only need to check indexes (1, 2) and (3, 2) for the cells left and right of the player, and (2, 1) and (2, 3) for the cells above and below.

Ideally you ‘move’ your player via adjusting it’s grid position, then convert that to a world position to move the player to.

As far as conversions go, it’s different for every grid system. Such as on things like where (0, 0) is (usually either top left, or bottom left), how large your tilemap cell size is (or is expected to be), and potentially if there’s any offset from world origin.

But generally it’s done by multiplying or dividing your position (grid or world) based on your cell size, then again by however many cells you have in your grid, potentially doing any offsets or x/y flipping and potentially extra work before that if you have a chunk system.

Ah I see, I need to be thinking of position in terms of the grid from the beginning, then convert to world position only when it’s time to actually execute the movement. So now my first questions are:

  1. How do I track the player’s grid position? Say for instance I initialize a cellx and celly for the player on game start as (0, 0); I guess I just make it so that input adds/subtracts 1 at a time for those values? I think I can edit what I already have to do that, if that is in fact the way to go. Assuming that’s the logic I should use, my next question is

  2. How do I get Unity to recognize what cells I’ve drawn obstacle tiles in? Then how do I check for those tiles for which that status is true from my player? Or rather, is it best to do all this from the GridManager object?

Thanks for the responses btw! I’m getting closer to the solution, I think I now grasp more of the general concept but not sure how to execute it in code.

As Kurt mentioned you can use something like Vector2Int to simply record this, or another struct of your own construction if you require any additional information.

Then when moving the player, I would - personally - only allow it to be moved via updating it’s grid position, after which it can position itself based on a conversion to world space.

That’s not up for Unity to handle, you have to construct this system yourself. You can of course use some of Unity’s existing tools, such as it’s Tilemap API (which I would do over instantiating individual game objects, as tile maps are more performant).

Though even then, if you are generating your own grid, you can hold onto this information and always check with that whenever you want to move the player, or any other interaction with the world. You can technically - and probably ought to be - handling most of this as purely data, and only have to update the visuals to match said data, what is known as a ‘model-view’ pattern.

I’ll upload a package I made about a year ago to demonstrate this for a ‘letter drop’ style game, but all the principles are here. It maintains a 2d array for the letters, handles movement via updating their grid position, then moving said tile to the appropriate position.

It should work on the latest 2021.3 LTS version, and only requires the Unity UI package.

9678755–1379849–2024-03-04 - WordDropExample.unitypackage (12.3 KB)

I’m guessing Unity is just trying to add a bunch of packages that you don’t need and it’s taking time to download all that noise and will ultimately finish if you let it go.

Extra unwanted packages in new projects (collab, testing, rider and other junk):

https://discussions.unity.com/t/846703/2

About the fastest way I have found to make a project and avoid all this noise is to create the project, then as soon as you see the files appear, FORCE-STOP (hard-kill) Unity (with the Activity Manager or Task Manager), then go hand-edit the Packages/manifest.json file as outlined in the above post, then reopen Unity.

Sometimes the package system gets borked from all this unnecessary churn and requires the package cache to be cleared:

https://stackoverflow.com/questions/53145919/unity3d-package-cache-errors/69779122

I recently found and binged a tutorial series on making a grid move system with script - surprisingly hard to find and more convoluted than expected, but it seemed like exactly what I was looking for except for one thing, just that they were setting up a pathfinding style movement system, whereas I want to use the arrow keys. The tutorial resulting in like 9 different scripts so I won’t post them all here, just two that are relevant to my next question.

Both of these scripts are on my Player object, which is a child of the tilemap for the scene.

Here’s the MapElement script:

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

public class MapElement : MonoBehaviour
{
    GridMap gridMap;
    public int x_pos;
    public int y_pos;

    void Start()
    {
        SetGrid();
        PlaceObjectOnGrid();
    }

    private void SetGrid()
    {
        gridMap = transform.parent.GetComponent<GridMap>();
    }

    private void PlaceObjectOnGrid()
    {
        Transform t = transform;
        Vector3 pos = t.position;
        x_pos = 3;
        y_pos = 3;

        //This debug log shows x_pos and y_pos both as 3, since they were just set
        Debug.Log("X Pos: " + x_pos + " Y Pos: " + y_pos);

        gridMap.SetCharacter(this, x_pos, y_pos);
    }


}

Here’s the CharacterControl script:

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


public class CharacterControl : MonoBehaviour
{
    private Vector2 movement;
    private float deadZone = 0.5f;
    private int inputx, inputy;

    //Test variables (what I think I will need)
    int cellx, celly, targetx, targety;
    bool moving = false;
    MapElement mapElement;

    private void Start()
    {
        mapElement = GetComponent<MapElement>();
    }

    private void OnMovement(InputValue value)
    {
        movement = value.Get<Vector2>();
    }

    [SerializeField] Tilemap targetTilemap;
    [SerializeField] GridManager gridManager;

    Character selectedCharacter;

    private void Update()
    {
        DirInput();

        if (inputx != 0 || inputy != 0)
        {
            moving = true;

            //Not pulling x_pos and y_pos correctly from mapElement?
            cellx = mapElement.x_pos;
            celly = mapElement.y_pos;

            targetx = cellx + inputx;
            targety = celly + inputy;

            //This first debug log is showing that x and y are initially 0
            Debug.Log("X Pos: " + cellx + " Y Pos: " + celly);
            //This debug log is showing the grid cells next to (0,0)
            Debug.Log("X Target: " + targetx + " Y Target: " + targety);
        }
    }

    private void DirInput()
    {
        //Get horizontal input as a -1 - 1
        if (movement.x > deadZone)
        {
            inputx = 1;
        }
        else if (movement.x < -deadZone)
        {
            inputx = -1;
        }
        else if (Mathf.Abs(movement.x) < deadZone)
        {
            inputx = 0;
        }

        //Get vertical input as a -1 - 1
        if (movement.y > deadZone)
        {
            inputy = 1;
        }
        else if (movement.y < -deadZone)
        {
            inputy = -1;
        }
        else if (Mathf.Abs(movement.y) < deadZone)
        {
            inputy = 0;
        }
    }
}

I’ve annotated where I think things are kind of going wrong. As far as I can tell, I’ve initialized the player to be on (3, 3) on the grid when the game launches. The debug message right after that prints (3, 3) as expected, but these values are for some reason not being pulled into the other script correctly before I calculate the target cell. How can I make sure those values are read properly?

Once I calculate the target cell, I’ll have to check to see if there are unpassable obstacles there…I have a couple of scriptable objects that basically label different tiles as different terrain types, which I’m sure will work fine when spawning the tiles through script. However, I’d love to still be able to use the tilemap brushes and stuff Unity has to build levels/maps. So how to I connect the tiles I paint on the tilemap (which is the parent of the player object if that matters) to the scripts I have in order to check for terrain type? Then if it’s the ‘unpassable’ terrain type I’d block the movement from happening.

EDIT: Solved the first part - the MapElement script was not on my player, I put it on the player and then I could drag and drop it into the other script in the inspector.

Ok, I condensed all my scripts so I just have a MasterPlayerScript that goes on the player object, and a MasterGridScript that goes on the grid object. The only thing in the grid script is setting grid width and height. This is what I have for my player script as of now:

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



public class MasterPlayerScript : MonoBehaviour
{
    private Vector2 movement;
    private float deadZone = 0.5f;
    private int inputx, inputy;

    private int initCellx, initCelly;

    //Test variables (what I think I will need)
    public int cellx, celly, targetx, targety;
    bool moving = false;
    int worldx, worldy, worldTargetx, worldTargety;
    Vector3Int origPos, targetPos;
    float moveSpeed = 0.8f;
    private Rigidbody2D rb;
    private Animator anim;
    private string currentState;
    [SerializeField] Tilemap obstacles;
    bool blockedHori, blockedVert;
    TileBase targetTile;
    MasterGridScript masterGridScript;
    [SerializeField] GameObject grid;
    int[,] playerPos;
    private int newx, newy;



    // Start is called before the first frame update
    void Start()
    {
        masterGridScript = grid.GetComponent<MasterGridScript>();

        anim = GetComponent<Animator>();

        SpawnObjectOnGrid();

        cellx = initCellx;
        celly = initCelly;

        for (int x = 0; x < masterGridScript.gridWidth; x++)
        {
            for (int y = 0; y < masterGridScript.gridHeight; y++)
            {
                if (cellx == x && celly == y)
                {
                    playerPos = new int[x, y];
                  
                }

            }
        }
    }

    // Update is called once per frame
    void Update()
    {
        DirInput();

        if (!moving)
        {
            if (inputx != 0 || inputy != 0)
            {
                PlayerCellMove(inputx, inputy);

                Debug.Log("Target X: " + targetx + " Target Y: " + targety);

                worldTargetx = targetx;
                worldTargety = targety;

                targetPos = new Vector3Int(worldTargetx, worldTargety, 0);

                StartCoroutine(Move(targetPos));
            }

            //Facing horizontally
            if (inputy == 0)
            {
                if (inputx == 1)
                {
                    ChangeAnimationState("WalkRight");
                }
                else if (inputx == -1)
                {
                    ChangeAnimationState("WalkLeft");
                }
            }

            //Facing vertically
            if (inputx == 0)
            {
                if (inputy == 1)
                {
                    ChangeAnimationState("WalkUp");
                }
                else if (inputy == -1)
                {
                    ChangeAnimationState("WalkDown");
                }
            }

            //Stopping animation when idle
            if (inputx == 0 && inputy == 0)
            {
                if (currentState == "WalkRight")
                {
                    ChangeAnimationState("IdleRight");
                }
                if (currentState == "WalkLeft")
                {
                    ChangeAnimationState("IdleLeft");
                }
                if (currentState == "WalkUp")
                {
                    ChangeAnimationState("IdleUp");
                }
                if (currentState == "WalkDown")
                {
                    ChangeAnimationState("IdleDown");
                }
            }

            //Preventing moonwalking
            if (currentState == "WalkRight" && inputx == -1)
            {
                ChangeAnimationState("WalkLeft");
            }
            if (currentState == "WalkLeft" && inputx == 1)
            {
                ChangeAnimationState("WalkRight");
            }
            if (currentState == "WalkUp" && inputy == -1)
            {
                ChangeAnimationState("WalkDown");
            }
            if (currentState == "WalkDown" && inputy == 1)
            {
                ChangeAnimationState("WalkUp");
            }
            if (currentState == "IdleRight" && inputx == -1)
            {
                ChangeAnimationState("WalkLeft");
            }
            if (currentState == "IdleLeft" && inputx == 1)
            {
                ChangeAnimationState("WalkRight");
            }
            if (currentState == "IdleUp" && inputy == -1)
            {
                ChangeAnimationState("WalkDown");
            }
            if (currentState == "IdleDown" && inputy == 1)
            {
                ChangeAnimationState("WalkUp");
            }
        }


    }

    private void OnMovement(InputValue value)
    {
        movement = value.Get<Vector2>();
    }

    void TargetCheck(Vector3Int posToCheck)
    {
        targetTile = obstacles.GetTile(posToCheck);

        //Debug.Log(targetTile);

        if (targetTile != null)
        {
            if (posToCheck.x != cellx)
            {
                blockedHori = true;
            } else { blockedHori = false; }
            if (posToCheck.y != celly)
            {
                blockedVert = true;
            } else { blockedVert = false; }

            Debug.Log("Blocked Horizontally: " + blockedHori + " Blocked Vertically: " + blockedVert);
        }
    }

    IEnumerator Move(Vector3Int newPos)
    {
        TargetCheck(newPos);

        if (blockedHori && blockedVert)
        {
            yield break;
        }

        moving = true;

        if (blockedHori)
        {
            newPos.x = worldx;
        }
        if (blockedVert)
        {
            newPos.y = worldy;
        }

        while ((newPos - transform.position).sqrMagnitude > Mathf.Epsilon)
        {
            transform.position = Vector3.MoveTowards(transform.position, newPos, moveSpeed * Time.fixedDeltaTime);

            yield return null;
        }

        transform.position = newPos;

        cellx = targetx;
        celly = targety;

        moving = false;
    }

    void ChangeAnimationState(string newState)
    {
        if (currentState == newState) return;

        anim.Play(newState);

        currentState = newState;
    }

    private void DirInput()
    {
        //Get horizontal input as a -1 - 1
        if (movement.x > deadZone)
        {
            inputx = 1;
        }
        else if (movement.x < -deadZone)
        {
            inputx = -1;
        }
        else if (Mathf.Abs(movement.x) < deadZone)
        {
            inputx = 0;
        }

        //Get vertical input as a -1 - 1
        if (movement.y > deadZone)
        {
            inputy = 1;
        }
        else if (movement.y < -deadZone)
        {
            inputy = -1;
        }
        else if (Mathf.Abs(movement.y) < deadZone)
        {
            inputy = 0;
        }
    }

    private void SpawnObjectOnGrid()
    {
        Transform t = transform;
        Vector3 pos = t.position;
        initCellx = (int)pos.x;
        initCelly = (int)pos.y;
    }

    public void PlayerCellMove(int deltax, int deltay)
    {
        newx = cellx + deltax;
        newy = celly + deltay;
        playerPos = new int[newx, newy];

        Debug.Log("Player Grid Target: (" + newx + ", " + newy + ")");

        for (int x = 0; x < masterGridScript.gridWidth; x++)
        {
            for (int y = 0; y < masterGridScript.gridHeight; y++)
            {
                if (playerPos == new int[x, y])
                {
                    targetx = x;
                    targety = y;
                }
            }
        }
      
        Debug.Log("To X: " + targetx + " To Y: " + targety);
    }

}

The problem I am now having is that somewhere between the two debugs in the PlayerCellMove function something goes wrong…the first debug there accurately returns newx and newy as the correct coordinates for each move. However the second debug returns targetx and targety both as 0; this results in my player immediately moving to (0, 0) upon receiving input, no matter where they start. After they reach (0, 0) they can’t move at all. I feel like I’m very close but I’m missing something crucial. At least it’s now cleaner/just one script to post lol

EDIT: Got it working - instead of using for loops I ended up just storing x and y grid positions as their own variables. For anyone who might come across this and is interested in the topic, here’s what I landed on:

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



public class MasterPlayerScript : MonoBehaviour
{
    //Variables related to input
    private Vector2 movement;
    private float deadZone = 0.5f;
    private int inputx, inputy;
    //Variables that read initial player position
    private int initCellx, initCelly;
    //Current and target cells' positions
    public int cellx, celly, targetx, targety;
    //Status of moving or not
    bool moving = false;
    //World position in terms of Transform coordinates
    int worldTargetx, worldTargety;
    //World position as a Vector3
    Vector3Int targetPos;
    //Adjustable player move speed
    float moveSpeed = 0.8f;
    //Variables related to animation
    private Animator anim;
    private string currentState;
    //Player sidling status (important for prevention of skipping openings in walls)
    private bool sidlingHori, sidlingVert;
    //Game object where non-passable obstacles are placed
    [SerializeField] Tilemap obstacles;
    //Status of being blocked by obstacles/edges horizontally, vertically, and diagonally
    bool blockedHori, blockedVert, blockedDiag;
    //Slots for getting tiles on target positions
    TileBase targetTileDiag, targetTileHori, targetTileVert;
    //Grid game object that holds grid dimensions
    MasterGridScript masterGridScript;
    [SerializeField] GameObject grid;

    // Start is called before the first frame update
    void Start()
    {
        //Script that holds grid dimensions
        masterGridScript = grid.GetComponent<MasterGridScript>();

        //Animator for player
        anim = GetComponent<Animator>();

        //Function that gets player's initial grid position
        SpawnObjectOnGrid();

        //Reads initial grid position and sets as current on launch
        cellx = initCellx;
        celly = initCelly;
    }

    // Update is called once per frame
    void Update()
    {
        //Script that converts input to -1, 0, or 1 for each axis
        DirInput();

        //If on the grid not moving or between steps
        if (!moving)
        {
            //If receiving input
            if (inputx != 0 || inputy != 0)
            {
                //Adjust target cell and world position
                targetx = cellx + inputx;
                targety = celly + inputy;

                worldTargetx = targetx;
                worldTargety = targety;

                targetPos = new Vector3Int(worldTargetx, worldTargety, 0);

                //Check to see if movement to target is possible
                CheckForEdges(targetx, targety);
                CheckForObstacles(worldTargetx, worldTargety);

                //If movement is not possible, what to do
                if (blockedHori)
                {
                    targetx = cellx;
                    if (targety != celly)
                    {
                        sidlingVert = true;
                        sidlingHori = false;
                    }
                }
                if (blockedVert)
                {
                    targety = celly;
                    if (targetx != cellx)
                    {
                        sidlingHori = true;
                        sidlingVert = false;
                    }
                }
                if (blockedDiag && !blockedHori && !blockedVert)
                {
                    if (sidlingHori)
                    {
                        targetx = cellx;
                        sidlingHori = false;
                    }
                    if (sidlingVert)
                    {
                        targety = celly;
                        sidlingVert = false;
                    }
                }

                //Update target world position
                worldTargetx = targetx;
                worldTargety = targety;

                targetPos = new Vector3Int(worldTargetx, worldTargety, 0);

                //Function to execute the movement
                StartCoroutine(Move(targetPos));
            }

            //Facing horizontally
            if (inputy == 0)
            {
                if (inputx == 1)
                {
                    ChangeAnimationState("WalkRight");
                }
                else if (inputx == -1)
                {
                    ChangeAnimationState("WalkLeft");
                }
            }

            //Facing vertically
            if (inputx == 0)
            {
                if (inputy == 1)
                {
                    ChangeAnimationState("WalkUp");
                }
                else if (inputy == -1)
                {
                    ChangeAnimationState("WalkDown");
                }
            }

            //Stopping animation when idle
            if (inputx == 0 && inputy == 0)
            {
                if (currentState == "WalkRight")
                {
                    ChangeAnimationState("IdleRight");
                }
                if (currentState == "WalkLeft")
                {
                    ChangeAnimationState("IdleLeft");
                }
                if (currentState == "WalkUp")
                {
                    ChangeAnimationState("IdleUp");
                }
                if (currentState == "WalkDown")
                {
                    ChangeAnimationState("IdleDown");
                }
            }

            //Preventing moonwalking
            if (currentState == "WalkRight" && inputx == -1)
            {
                ChangeAnimationState("WalkLeft");
            }
            if (currentState == "WalkLeft" && inputx == 1)
            {
                ChangeAnimationState("WalkRight");
            }
            if (currentState == "WalkUp" && inputy == -1)
            {
                ChangeAnimationState("WalkDown");
            }
            if (currentState == "WalkDown" && inputy == 1)
            {
                ChangeAnimationState("WalkUp");
            }
        }


    }

    private void OnMovement(InputValue value)
    {
        movement = value.Get<Vector2>();
    }

    IEnumerator Move(Vector3Int newPos)
    {
        moving = true;

        while ((newPos - transform.position).sqrMagnitude > Mathf.Epsilon)
        {
            transform.position = Vector3.MoveTowards(transform.position, newPos, moveSpeed * Time.fixedDeltaTime);

            yield return null;
        }

        transform.position = newPos;

        cellx = targetx;
        celly = targety;

        blockedHori = false;
        blockedVert = false;
        blockedDiag = false;

        moving = false;
    }

    void CheckForEdges(int tx, int ty)
    {
        if (!blockedHori)
        {
            if (tx < 0 || tx > masterGridScript.gridWidth)
            {
                blockedHori = true;
            }
        }

        if (!blockedVert)
        {
            if (ty < 0 || ty > masterGridScript.gridHeight)
            {
                blockedVert = true;
            }
        }
       
    }

    void CheckForObstacles(int tx, int ty)
    {
        // targetTile = obstacles.GetTile(target);

        targetTileHori = obstacles.GetTile(new Vector3Int(tx, celly, 0));
        targetTileVert = obstacles.GetTile(new Vector3Int(cellx, ty, 0));
        targetTileDiag = obstacles.GetTile(new Vector3Int(tx, ty, 0));

        if (!blockedHori && targetTileHori != null)
        {
            blockedHori = true;
        }
        if (!blockedVert && targetTileVert != null)
        {
            blockedVert = true;
        }
        if (!blockedDiag && targetTileDiag != null)
        {
            blockedDiag = true;
        }
    }

    void ChangeAnimationState(string newState)
    {
        if (currentState == newState) return;

        anim.Play(newState);

        currentState = newState;
    }

    private void DirInput()
    {
        //Get horizontal input as a -1, 0, or 1
        if (movement.x > deadZone)
        {
            inputx = 1;
        }
        else if (movement.x < -deadZone)
        {
            inputx = -1;
        }
        else if (Mathf.Abs(movement.x) < deadZone)
        {
            inputx = 0;
        }

        //Get vertical input as a -1, 0, or 1
        if (movement.y > deadZone)
        {
            inputy = 1;
        }
        else if (movement.y < -deadZone)
        {
            inputy = -1;
        }
        else if (Mathf.Abs(movement.y) < deadZone)
        {
            inputy = 0;
        }
    }

    private void SpawnObjectOnGrid()
    {
        Transform t = transform;
        Vector3 pos = t.position;
        initCellx = (int)pos.x;
        initCelly = (int)pos.y;
    }

}