Foreach Board Game Movement Bug

To make it short I am really exhausted from trying to fix it, I am trying to create my own movement system. I have some white sprites as tiles for my player to move on with a distance of 3 between them and my player which is the black sprite. In the bottom right there is a controller to move the player, but you can only move in a direction if a tile lies there. But my code doesn’t work and only lets me go up at one specific tile, the one that lies at y = 0. Here is my code and a screenshot, I hope you can help me, I will go to sleep now .-.

![{
    Vector3 moveX = new Vector3(3.0f,0,0);
    Vector3 moveY = new Vector3(0,3.0f,0);

    GameObject[] tiles;

    public void MoveUp()
    {
        GameObject.Find("Player1").transform.position += moveY;
        CheckTiles();
    }

    public void MoveDown()
    {
        GameObject.Find("Player1").transform.position -= moveY;
        CheckTiles();
    }

    public void MoveLeft()
    {
        GameObject.Find("Player1").transform.position -= moveX;
        CheckTiles();
    }

    public void MoveRight()
    {
        GameObject.Find("Player1").transform.position += moveX;
        CheckTiles();
    }

    void Start()
    {
        tiles = GameObject.FindGameObjectsWithTag("tile");
        CheckTiles();
    }

    public void CheckTiles()
    {
        foreach (GameObject go in tiles)
        {
            if ((go.transform.position.y <= (GameObject.Find("Player1").transform.position.y + 4)) && (go.transform.position.y >= (GameObject.Find("Player1").transform.position.y + 2)))
            {
                GameObject.Find("MoveUp").GetComponent<Button>().interactable = true;
            }
            else
            {
                GameObject.Find("MoveUp").GetComponent<Button>().interactable = false;
            }
        }][1]

The problem is that you assign the value inside the foreach, meaning that you are in fact assigning true or false depending only on the last item of the foreach. What you want in fact is “If it’s true for at least one tile, I want it the button to be interactable”.

Something like this should work better:

	public void CheckTiles()
	{
		bool enableMoveUp = false;
		foreach (GameObject go in tiles)
		{
			if ((go.transform.position.y <= (GameObject.Find("Player1").transform.position.y + 4)) && (go.transform.position.y >= (GameObject.Find("Player1").transform.position.y + 2)))
			{
				enableMoveUp = true;
			}
		}
		GameObject.Find("MoveUp").GetComponent<Button>().interactable = enableMoveUp;
	}

Unrelated advice:

  • you should really try to avoid this “Find” function all the time. Can’t you have a Player attribute in your class, as you did for the tiles?
  • it would probably be more efficient and more intuitive to keep a table for your board, and compare indexes rather than world positions.