Im attempting to make a match 3 puzzle style game similiar to puzzles and dragons
the issue is when i move to quickly it can sometimes force one tile into anothers spot
grid manager and scriptable object based grid
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using TMPro;
using UnityEngine;
using UnityEngine.UIElements;
public class TestGridManager : MonoBehaviour
{
public GridData grid;
private GameObject selectedTile;
private GameObject TransparentTile;
private Vector2Int lastGridPosition;
private Vector2Int currentGridPosition;
// Start is called before the first frame update
void Start()
{
grid.Initialize();
FillGrid();
Debug.Log("test2");
}
void FillGrid()
{
for (int y = 0; y < grid.height; y++)
{
for (int x = 0; x < grid.width; x++)
{
Vector3 parentPosition = transform.position;
grid.SetTileType(x, y, Random.Range(0, grid.tilePrefabs.Length));
Vector3 localPosition = new Vector3(x * grid.tileSize, y * grid.tileSize, 0);
Vector3 worldPosition = parentPosition + localPosition;
GameObject tile = Instantiate(grid.tilePrefabs[grid.GetTileType(x,y)], worldPosition, Quaternion.identity, transform);
}
}
}
void Update()
{
HandleInput();
}
void HandleInput()
{
//grab tile,set nearest grid positon,
//leave transparent tile at nearest grid position
OnTileClick();
//set nearest grid position,constrain to grid,swap tile logic, leave transparent tile at nearest grid position
OnTileDrag();
//remove after image,snap visual to nearest gridposition, handle matches
OnTileRelease();
//refill board
//refillboard
}
void OnTileClick()
{
// if theres nothing in hand onclick we try to grab a tile
if(selectedTile == null)
{
TryGrabTile();
}
}
void TryGrabTile()
{
if (Input.GetMouseButtonDown(0))
{
Vector3 mouseClickPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Collider2D hitCollider = Physics2D.OverlapPoint(mouseClickPosition);
if (hitCollider != null)
{
selectedTile = hitCollider.gameObject;
SetTileTransparency(selectedTile,0.5f);
SetCurrentGridPosition(selectedTile.transform.position);
lastGridPosition = currentGridPosition;
FollowMouse(selectedTile);
Vector3 tes = GetWorldPosition(currentGridPosition);
Debug.Log($"worldPosition is{tes}");
}
}
}
void OnTileDrag()
{
if (selectedTile != null)
{
FollowMouse(selectedTile);
SetCurrentGridPosition(selectedTile.transform.position);
if (IsAdjacent(lastGridPosition, currentGridPosition))
{
// Check if the target grid position is not occupied
if (!grid.IsTileOccupied(currentGridPosition.x, currentGridPosition.y))
{
GameObject tileToSwap = GetTileAtPosition(currentGridPosition);
if (tileToSwap != null && tileToSwap != selectedTile)
{
MoveTile(tileToSwap);
}
}
}
}
}
void SetTileTransparency(GameObject tile,float amount)
{
TransparentTile= tile;
SpriteRenderer renderer = TransparentTile.GetComponent<SpriteRenderer>();
if (renderer != null)
{
Color color = renderer.color;
color.a = amount; // Set alpha to make it semi-transparent
renderer.color = color;
}
}
void SetCurrentGridPosition(Vector3 worldPosition)
{
if (selectedTile != null)
{
Vector3 localPosition = transform.InverseTransformPoint(worldPosition);
int x = Mathf.RoundToInt(localPosition.x / grid.tileSize);
int y = Mathf.RoundToInt(localPosition.y / grid.tileSize);
Vector2Int newClosestGridPosition = new Vector2Int(x, y);
Vector3 test = GetWorldPosition(lastGridPosition);
if (newClosestGridPosition != currentGridPosition)
{
lastGridPosition = currentGridPosition;
currentGridPosition = newClosestGridPosition;
Debug.Log($"The last grid position was {test}, the nearest is: {currentGridPosition}");
}
}
}
bool IsAdjacent(Vector2Int pos1, Vector2Int pos2)
{
return (Mathf.Abs(pos1.x - pos2.x) == 1 && pos1.y == pos2.y) || (Mathf.Abs(pos1.y - pos2.y) == 1 && pos1.x == pos2.x);
}
GameObject GetTileAtPosition(Vector2Int gridPosition)
{
Vector3 worldPosition = GetWorldPosition(gridPosition);
Collider2D hitCollider = Physics2D.OverlapPoint(worldPosition);
return hitCollider != null ? hitCollider.gameObject : null;
}
void OnTileRelease()
{
if (Input.GetMouseButtonUp(0) && selectedTile !=null)
{
SnapToGrid(selectedTile, currentGridPosition);
SetTileTransparency(selectedTile, 1);
selectedTile = null;
}
}
void MoveTile(GameObject Tile)
{
float step = 20 * Time.deltaTime;
Vector3 targetGridPostion = GetWorldPosition(lastGridPosition);
// move the tile to the last grid position animation wise
Tile.transform.position = targetGridPostion;
// update its location in the grid
// snap it
}
Vector3 GetWorldPosition(Vector2Int gridPosition)
{
return transform.TransformPoint(new Vector3(gridPosition.x * grid.tileSize, gridPosition.y * grid.tileSize, 0));
}
void SnapToGrid(GameObject tile,Vector2Int SnapPosition)
{
//Vector2Int gridPosition = GetGridPosition(tile.transform.position);
//convert the grids position to a relative position in the world and move the tile there
Vector3 snappedPosition = GetWorldPosition(SnapPosition);
tile.transform.position = snappedPosition;
}
void FollowMouse(GameObject obj)
{
Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePosition.z = obj.transform.position.z; // Maintain the original z position
// Calculate the grid boundaries based on the parent's position and scale
float minX = transform.position.x;
float maxX = transform.position.x + (grid.width-1)*grid.tileSize* transform.localScale.x;
float minY = transform.position.y;
float maxY = transform.position.y +(grid.height -1) * grid.tileSize * transform.localScale.y;
// Clamp the mouse position to the grid boundaries
mousePosition.x = Mathf.Clamp(mousePosition.x, minX, maxX);
mousePosition.y = Mathf.Clamp(mousePosition.y, minY, maxY);
obj.transform.position = mousePosition;
}
}
using UnityEngine;
[CreateAssetMenu(fileName = "New Grid", menuName = "Grid/Grid Data", order = 1)]
public class GridData : ScriptableObject
{
public int width;
public int height;
public float tileSize;
public GameObject[] tilePrefabs;
private int[,] gridData;
public void Initialize()
{
gridData = new int[height, width];
}
public bool IsTileOccupied(int x, int y)
{
if (IsValidPosition(x, y))
{
return gridData[y, x] != 0;
}
return true;
}
public int GetTileType(int x, int y)
{
if (IsValidPosition(x, y))
{
return gridData[y, x];
}
return -1; // Invalid type
}
public void SetTileType(int x, int y, int type)
{
if (IsValidPosition(x, y))
{
gridData[y, x] = type;
}
}
public bool IsValidPosition(int x, int y)
{
return x >= 0 && x < width && y >= 0 && y < height;
}
}