0
\$\begingroup\$

I am currently trying to recreate chess and the problem I am having is that I need to instantiate all of the pawns in a loop (I could write it out but it seems inefficient) and I need to be able to call a method from all of the pawns to look for a check (I'll probably use raycast but I haven't gotten to that yet). How can I go about calling the method that looks for checks from all of the instances of the pawn?

I'm pretty new to unity so please go easy on me if I said something dumb

\$\endgroup\$
5
  • \$\begingroup\$ The loop is efficient, you do not want to copy/ paste the same instantiate 8 times per side for each pawn. Raycasting here would be probably overkill (and how do you raycast the horse). Instead you would have your board on a grid and each figure can move in a direction. Do not think too much that you are over optimizing, get it working and if it is too slow, refactor it but not before (as long as your check function is not in Update() - no worry). Checking once after each move for all figures won't break a sweat. \$\endgroup\$
    – Zibelas
    Commented Feb 10, 2021 at 9:32
  • \$\begingroup\$ Hi, if I read your question correctly, you want to 'call a function that looks for a check' on all of your pawns? Don't you just want to 'look for a check' only with the piece you just moved? And if you do a move that puts you in 'check', before putting down your piece' simply not allow that move? (sorry if I misunderstood the question.) \$\endgroup\$
    – D.Kallan
    Commented Feb 10, 2021 at 9:42
  • \$\begingroup\$ @D.Kallan You have to check all of the pieces after every move because sometimes a piece would move out of the way of another piece that can now check the king. For example, if the king is on the same diagonal as a bishop but there is a pawn in the way the king isn't in check. Now if you move the pawn the diagonal is now open and the bishop puts the king in check. \$\endgroup\$
    – Yuval Amir
    Commented Feb 10, 2021 at 9:45
  • \$\begingroup\$ True, my bad. If you hold a collection of pieces on the board (per player), you can go through that and see if they check, right? You could also make it more smart probably, by checking what piece is potentially checking (but blocked by another piece) and when you move a piece, you check just those potential pieces instead of all of your pieces. Regardless, it shouldn't be that big of a performance hit I think? \$\endgroup\$
    – D.Kallan
    Commented Feb 10, 2021 at 9:49
  • 2
    \$\begingroup\$ When you want to create a game with mechanics which are rather abstract than physical - like chess - then I would really not recommend you to use MonoBehaviours to implement the mechanics. I would rather implement the mechanics in plain C# and then use Unity gameObjects to visualize them. \$\endgroup\$
    – Philipp
    Commented Feb 10, 2021 at 10:00

2 Answers 2

0
\$\begingroup\$

One thing you could do is give all the pieces of each player the same tag and then use GameObject[] whitePieces = GameObject.FindGameObjectsWithTag("white");. That gets you an array of gameObjects which you can iterate with a for-loop.

Now you need to determine the type of each piece. You could do that in a variety of ways. For example, you are likely going to put a different component on each piece. so you can use GetComponent<Pawn>() or GetComponent<Rook>() and see if you receive a non-null return value. Or maybe you just have one unified component ChessPiece which has a public field exposing its concrete type, so you could do something like if (piece.GetComponent<ChessPiece>().type == PAWN).

\$\endgroup\$
0
\$\begingroup\$

I need to instantiate all of the pawns in a loop...and I need to be able to call a method from all of the pawns

So, keep a reference to them in the loop where you instantiate them. That might look something like this:

public class ChessArmy : MonoBehaviour {
    [System.Serializable]
    public struct Prefabs {
        public ChessPiece king;
        public ChessPiece queen;
        public ChessPiece bishop;
        public ChessPiece knight;
        public ChessPiece rook;
        public ChessPiece pawn;
    }

    [SerializeField] Prefabs _prefabs;

    List<ChessPiece> _pieces = new List<ChessPiece>();

    void AddPiece(ChessPiece prefab, int row, int column) {
        var place = new Vector3(-3.5 + column, 0, -3.5 + row);
        var piece = Instantiate(prefab, place, Quaternion.identity);
        _pieces.Add(piece);
    }

    public void SpawnArmy(bool mirror) {
        int backRow = mirror ? 7 : 0;
        int frontRow = mirror ? 6 : 1;

        AddPiece(_prefabs.rook,   backRow, 0);
        AddPiece(_prefabs.knight, backRow, 1);
        AddPiece(_prefabs.bishop, backRow, 2);
        AddPiece(_prefabs.queen,  backRow, 3);
        AddPiece(_prefabs.king,   backRow, 4);
        AddPiece(_prefabs.bishop, backRow, 5);
        AddPiece(_prefabs.knight, backRow, 6);
        AddPiece(_prefabs.rook,   backRow, 7);

        for (int i = 0; i < 8; i++)
            AddPiece(_prefabs.pawn, frontRow, i);
    }

    public bool HasCheck(ChessBoard board, List<ChessPiece> checkers) {
        checkers.Clear();

        foreach (var piece in _pieces) {
            if (piece.HasCheck(board)) 
                checkers.Add(piece);
        }

        return checkers.Count > 0;
    }
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .