Touch to place coins on a board game dynamically

Hi,

I’m new to Unity and I want a little help with an approach to solve a problem. I’m building a board game in which user clicks on a board (Board is full of 36 numbers in square boxes. 3 columns and 12 rows) and I have to place coins one over the other at the touched number. Now the complex problem is that user can click on the junction between numbers. So if user clicks on the line between 2 numbers, or on a junction point between four numbers, I have to be able to detect it, place coins and send information that the coin was placed on 4 number junction/ 2 number junction etc. Please help me understand with an approach to this problem. The board table is a sprite.

I think you should setup an array of X, Y positions that represent the center of your square boxes.

Then you have to figure out when to register a click on a number and when to register a click on a line or junction. Let’s say your numbers are 1 unit apart (0x,0y is a square, 0,1 is a square, 1,0 is a square, 1,1 is a square, etc.), now you can find the closest square, 2nd closest square, 3rd closest square, 4th closest square to the user click by means of a for loop, looping through the array of x positions and y positions.

Then, if for example the click was at a distance of more than 0.3f away from the center of the closest square in the X or the Y (you’ll have to play with this value to find the sweet spot, but let’s just say that an offset of 0.3f in the y or 0.3f in the x is considered off the square, giving your square 0.6f in the x and 0.6f in the y directions to register a click), now you know that you are clicking on a line or junction.

Now if the click is more than 0.3f in the y and more than 0.3f in the x, you are at a junction, if it is only more than 0.3f in one direction, you are at a line. To find which line, you just need to know if the direction at which is more than 0.3f is more or less than the, let’s say the y direction. If it is more, than the line is above, if less, the line is below.

For finding the junction, it’s easy, you already know which 4 squares are closest, so it’s the junction between them.

I did something similar for a level editor in a 2d game a while back. I assume as you are using a sprite that the game is 2D.


To use this script, set your pivot point on your sprite to the bottom left and add a boxcollider2d to it. Then either put the script on the same object as the sprite or a different object and drag a reference to the sprite’s transform.


The script breaks the sprite up into a grid and places a prefab in the centre point of the nearest square where you click. You should be able to modify this for your needs.


using UnityEngine;

public class DetectGridClick : MonoBehaviour
{
    public Transform SpriteTransform;

    public GameObject Prefab;

    public int NoOfColums   = 3;
    public int NoOfRows     = 12;

    private Vector2 _gridSize;

    private float _xSpacing;
    private float _ySpacing;


    private float xGridPos;
    private float yGridPos;

    private void Start()
    {
        if (SpriteTransform == null)
            SpriteTransform = transform;

        var collider = GetComponent<BoxCollider2D>();

        _gridSize = collider.size;

        _xSpacing = _gridSize.x / NoOfColums;
        _ySpacing = _gridSize.y / NoOfRows;
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            //Get mouse click position
            var cilckPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);

            //Check mouse click with bounds
            if (CheckWithinBounds(cilckPos))
            {
                var spawnPos = GetSpawnPos();

                Instantiate(Prefab, spawnPos, Quaternion.identity);
            }
        }

    }

    public bool CheckWithinBounds(Vector3 worldPosition)
    {
        var localPosition = GetRelativePos(worldPosition);

        var localX = localPosition.x;
        var localY = localPosition.y;

        if (localX >= _gridSize.x)
            return false;
        if (localY > _gridSize.y)
            return false;
        if (localX < 0)
           return false;
        if (localY < 0)
           return false;

        xGridPos = GetIndexAlongAxis(localX, _xSpacing, NoOfColums);
        yGridPos = GetIndexAlongAxis(localY, _ySpacing, NoOfRows);

        return true;
    }

    private Vector2 GetRelativePos(Vector3 pos)
    {
        pos.x = Mathf.Abs(SpriteTransform.position.x - pos.x);
        pos.y = Mathf.Abs(SpriteTransform.position.y - pos.y);

        return pos;
    }

    private int GetIndexAlongAxis(float position, float spacing, int numberOfIncrements)
    {
        for (var i = 1; i <= numberOfIncrements; i++)
        {
            if (position >= spacing * (i - 1) && position < spacing * i)
            {
                return i;
            }
        }

        return 0;
    }

    private Vector3 GetSpawnPos()
    {
        var ret = Vector3.zero;

        ret.x = xGridPos * _xSpacing - (_xSpacing / 2);
        ret.y = yGridPos * _ySpacing - (_ySpacing / 2);

        return ret + SpriteTransform.position;
    }
}