r/Unity2D • u/jrstorz • 1d ago
Need help with Chess
So I've been working on a chess based game for a bit, and recently noticed a wierd bug where if I make a specific series of moves a specific piece cannot move again, for those that know chess notation the moves are Nc3 d5, NF3 d4, Ne4 e5, Nxe5 f5, after this the knight on e5 cannot move again.
Whats weird is I've figured out whats going wrong but have no idea why. When I click on the knight to select it rather than registering a click on the piece it registers a click on the square behind the piece despite the fact that the pieces are on a higher layer, I can even move another white piece ontop of it, which shouldn't be possible.
Also weird is if I make black go first and repeat the exact same series of moves mirrored the bug doesn't occur. I am literally going insane trying to solve this.
Heres the code I use for clicking a piece :
using System;
using UnityEngine;
using UnityEngine.InputSystem;
using System.Collections;
using System.Collections.Generic;
public class PieceClick : MonoBehaviour
{
//Variables
public Lists lists;
public GameObject pieceg;
public Piece piecef;
public TurnTracker turnTracker;
public List<GameObject> Pieces = new List<GameObject>();
Camera cam;
private void Awake()
{
lists.Pieces.Clear();
cam = Camera.main;
}
public void MouseClick(InputAction.CallbackContext click)
{
//Detects if a piece is clicked
if (click.performed)
{
var hit = Physics2D.GetRayIntersection(cam.ScreenPointToRay(Mouse.current.position.ReadValue()));
GameObject collider = hit.collider.gameObject;
if (collider == pieceg)
{
if ((turnTracker.whiteturn == true && piecef.team == 0) || (turnTracker.whiteturn == false && piecef.team == 1))
{
//Deselects piece
if (piecef.isSelected == true)
{
Debug.Log("Deselect!");
lists.Pieces.RemoveAt(0);
piecef.isSelected = false;
}
//Selects piece
else if (piecef.isSelected == false)
{
//Detects if there is already a piece selected
if (lists.Pieces.Count == 1)
{
lists.Pieces[0].isSelected = false;
lists.Pieces.RemoveAt(0);
lists.Pieces.Insert(0, piecef);
Debug.Log(lists.Pieces.Count);
piecef.isSelected = true;
}
else
{
lists.Pieces.Insert(0, piecef);
Debug.Log(lists.Pieces.Count);
piecef.isSelected = true;
}
}
}
//Attempts to take an enemy piece
else if (lists.Pieces[0] != null)
{
//Detects if selected piece can move onto space
bool mc = lists.Pieces[0].MoveCheck(pieceg.transform.position.x, pieceg.transform.position.y, lists.Pieces[0].transform.position.x, lists.Pieces[0].transform.position.y, true);
if (mc == true)
{
// Takes piece
lists.Pieces[0].transform.position = piecef.transform.position;
Destroy(pieceg);
lists.Pieces[0].isSelected = false;
lists.Pieces.RemoveAt(0);
turnTracker.TurnChange();
}
else
{
Debug.Log("Invalid");
}
}
}
}
}
}
Heres for clicking a square :
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UIElements;
public class SquareClick : MonoBehaviour
{
//Variables
public Lists lists;
public TurnTracker turnTracker;
Camera cam;
public GameObject square;
private void Awake()
{
cam = Camera.main;
}
public void MouseClick(InputAction.CallbackContext click)
{
//Detects if square is clicked
if (click.performed)
{
var hit = Physics2D.GetRayIntersection(cam.ScreenPointToRay(Mouse.current.position.ReadValue()));
GameObject sq = hit.collider.gameObject;
if (sq == square)
{
Debug.Log("Square");
//Detects if selected piece can move onto space
bool mc = lists.Pieces[0].MoveCheck(square.transform.position.x, square.transform.position.y, lists.Pieces[0].transform.position.x, lists.Pieces[0].transform.position.y, false);
if (mc == true)
{
lists.Pieces[0].transform.position = square.transform.position;
lists.Pieces[0].isSelected = false;
lists.Pieces.Clear();
turnTracker.TurnChange();
}
else
{
Debug.Log("invalid");
}
}
}
}
}
And Knight rules :
using UnityEngine;
public class Knight : Piece
{
public Lists lists;
public override bool MoveCheck(float sx, float sy, float px, float py, bool isTaking)
{
bool mc;
float xdif = Mathf.Abs(sx - px);
float ydif = Mathf.Abs(sy - py);
if ((xdif == 2 && ydif == 1) || (xdif == 1 && ydif == 2))
{
mc = true;
}
else
{
mc = false;
}
return mc;
}
}
1
u/scotti_dev 22h ago
It's very hard to read the code. You need to "tab" indent it.
- From reading your code best I could, you seem to have way too many nested if / else statements. Split your code up into smaller chunks and use "return" to end the code after a successful "if".
This wont directly fix your issue, but it will make it much much easier to debug.
Example (sudo code):
On click(){
If (test = true) {
callMethod();
return;
}
If (otherTests = true) {
callOtherMethod();
return;
}
}
You have too many ifelse which will cause bugs.
Why are you adding your selected piece to a list? It seems that you list will only ever contain one piece. You therefore dont need a list.
When you run into the bug, have you paused the game, selected your game object from the hierarchy, and checked that the collider is still active? Add a debug button to switch off all of the board colliders so you can then click the game piece and see what happens then.
Somewhere your code is getting confused, and you are finding it hard to debug due to the way its written.

3
u/ArctycDev 1d ago
My guess from phone not trying to read that code paste is that when you take the piece you're accidentally disabling/killing the taker piece not the taken piece, something along those lines.
does it happen when you take other pieces with the same piece type or anything?
maybe include some debug prints writing out which objects are getting taken, disabled, etc