I am totally new to Photon or networking of any sort, so please forgive me if I’m just being stupid lol
So, I have a chess game that’s just supposed to be 2 players max, I’m designing it for a client. I seem to have everything working up until the game starts. So I attached photonviews to everything that is supposed to be synced, I have it joining a room at start when you select a player, and if the current room’s player count is more than 1, it activates the "player 2 joined " text. This works, and then it calls an RPC from the photon view, to use this method,
[PunRPC]
public void ChangeScene(int sceneName)
{
PhotonNetwork.LoadLevel(sceneName);
}
This appears to work, as it loads the scene on both players. The network manager is set to not destroy on scene change, and I can confirm it’s still present in the heirarchy. It loads both scenes for both players, and even successfully disables the computer player, which is set to disable if the player count is more than 1 in the room(same method that enables/disables the text).
But then when I move a piece, it does not sync anything up between players. Like I said, I have photon views on everything, and a photonview transfrom that is set to sync position on the chess pieces, but it doesn’t move the pieces, or even properly change the players turn. Am I supposed to put RPCs on every single method that I want synced? Because if so I think I would need a huge amount of RPCs lol. I could be wrong, but I thought putting a photonview on the chess board, which handles all the movement and everything, would be enough to sync players.
Or is it perhaps somehow joining them to unique scenes? I am testing it out by building it and then running it in the editor. I just tested it out, started the game in the build, and the start game RPC was successfully called in the editor…
Edit: Here’s my board script, if anybody could give me some advice on what I might need to synchronize manually, I would appreciate it… I’m totally new to networking, and no matter how much I read on it everything just flies over my head lol. It does appear to be joining the same room, but it’s spawning one piece for every player, even though I set it to only initiate the board if the board hadn’t been initiated, also it’s not properly changing their sprites… The movement does seem to be syncing though, although, there is an extra piece under every piece.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
public class Board : MonoBehaviourPunCallbacks
{
[SerializeField]
int boardSize = 8;
public Vector2[,] boardGrid;
public ChessPiece[,] pieces;
[SerializeField]
Transform chessPieceContainer;
[SerializeField]
float spaceBetweenPieces = 1;
[SerializeField]
GameObject chessPiece, capturedChessPiece;
TeamColor currentTeam, onePlayerTeam, computerTeam;
ChessPiece selectedPiece;
Vector2 mousePos;
Camera cam;
[SerializeField]
GameObject highlighter, movementBox;
List<GameObject> boxes;
SpeechBubble bubble;
[SerializeField]
RectTransform[] onePlayerPiecesGraveyard, twoPlayerPiecesGraveyard;
int numCapturedWhite, numCapturedBlack;
bool gameOver, blackKingDown,blackQueenDown, firstpawnBlack,firstPawnWhite, enemyTurn, boardInitiated;
private void Awake()
{
bubble = FindObjectOfType<SpeechBubble>();
boxes = new List<GameObject>();
cam = Camera.main;
currentTeam = TeamColor.White;
boardGrid = new Vector2[boardSize, boardSize];
pieces = new ChessPiece[boardSize,boardSize];
if (!boardInitiated)
{
InitiateBoard();
}
onePlayerTeam = GameManager.team;
if (onePlayerTeam == TeamColor.Black)
{
computerTeam = TeamColor.White;
if (GameManager.isSinglePlayer)
{
StartCoroutine(ComputerTurn());
}
bubble.SpeechBubbleDisplay(13);
}
else
{
bubble.SpeechBubbleDisplay(12);
computerTeam = TeamColor.Black;
}
}
void InitiateBoard()
{
boardInitiated = true;
for (int x = 0; x < boardGrid.GetLength(0); x++)
{
for (int y = 0; y < boardGrid.GetLength(1); y++)
{
boardGrid[x, y] = new Vector3(chessPieceContainer.position.x + x * spaceBetweenPieces, chessPieceContainer.position.y + y * spaceBetweenPieces,0);
if (y < 2 || y > 5)
{
GameObject spawnedPiece = PhotonNetwork.Instantiate("Prefabs/Piece", boardGrid[x,y],transform.rotation);
pieces[x, y] = spawnedPiece.GetComponent<ChessPiece>();
pieces[x, y].posOnBoard = new Vector2Int(x, y);
}
}
}
CheckAllLegalMoves();
}
private void Update()
{
if(selectedPiece == null && highlighter.activeInHierarchy)
{
highlighter.SetActive(false);
}
if (Input.GetMouseButtonDown(0))
{
OnMouse();
}
}
void OnMouse()
{
mousePos = Input.mousePosition;
RemoveSelectionBoxes();
if (!gameOver)
{
if (onePlayerTeam == currentTeam)
{
if (CheckIfCoordsAreOnGrid(mousePos))
{
if (GetPieceAtCoords(mousePos) != null && selectedPiece == null && pieces[CheckGridPosAtCoords(mousePos).x, CheckGridPosAtCoords(mousePos).y].team == currentTeam)
{
Vector2Int pieceToSelectIndex = CheckGridPosAtCoords(mousePos);
SelectPiece(pieces[pieceToSelectIndex.x, pieceToSelectIndex.y]);
}
else if (selectedPiece != null)
{
if (pieces[CheckGridPosAtCoords(mousePos).x, CheckGridPosAtCoords(mousePos).y] == null)
{
MovePiece(CheckGridPosAtCoords(mousePos), selectedPiece);
}
else if (GetPieceAtCoords(mousePos).team == selectedPiece.team)
{
SelectPiece(GetPieceAtCoords(mousePos));
}
else if (selectedPiece != null)
{
CapturePiece(GetPieceAtCoords(mousePos));
}
}
}
}
}
}
void SwitchActiveTeam()
{
if(currentTeam == computerTeam)
{
currentTeam = onePlayerTeam;
}
else
{
currentTeam = computerTeam;
}
}
ChessPiece GetPieceAtCoords(Vector2 coords)
{
return pieces[CheckGridPosAtCoords(coords).x, CheckGridPosAtCoords(coords).y];
}
Vector2Int CheckGridPosAtCoords(Vector2 coords)
{
float distance = 2;
Vector2Int pieceInd = Vector2Int.one * -1;
for (int x = 0; x < boardGrid.GetLength(0); x++)
{
for (int y = 0; y < boardGrid.GetLength(1); y++)
{
if (Vector2.Distance(cam.ScreenToWorldPoint(coords), boardGrid[x, y]) < distance)
{
distance = Vector2.Distance(cam.ScreenToWorldPoint(coords), boardGrid[x, y]);
pieceInd = new Vector2Int(x, y);
}
}
}if(pieceInd == Vector2Int.one * -1)
{
RemoveSelectionBoxes();
print("Something when wrong in selecting?");
}
return new Vector2Int(pieceInd.x,pieceInd.y);
}
void CheckAllLegalMoves()
{
for (int i = 0; i < pieces.GetLength(0); i++)
{
for (int j = 0; j < pieces.GetLength(1); j++)
{
if (pieces[i, j] != null)
{
pieces[i, j].CalculateLegalMoves();
}
}
}
}
void MovePiece(Vector2Int pos, ChessPiece pieceToMove)
{
if (pieces[pos.x, pos.y] == null && pieceToMove.legalMoves.Contains(pos))
{
Vector2Int previousPos = pieceToMove.posOnBoard;
if (pieceToMove.firstMove)
{
pieceToMove.firstMove = false;
}
pieces[previousPos.x, previousPos.y] = null;
pieceToMove.posOnBoard = pos;
pieceToMove.transform.position = boardGrid[pos.x,pos.y];
pieces[pos.x,pos.y] = pieceToMove;
DeselectPiece();
StartNewTurn();
}else if(pieces[pos.x, pos.y] != null && pieces[pos.x, pos.y].team != selectedPiece.team)
{
CapturePiece(pieces[pos.x, pos.y]);
}
else if(!selectedPiece.legalMoves.Contains(pos))
{
print("Something when wrong in moving?");
}
}
void CapturePiece(ChessPiece pieceToCapture)
{
Vector2Int posToMoveTo = Vector2Int.zero;
if(pieceToCapture.team == TeamColor.White)
{
ChessPieceEvent(pieceToCapture.pieceIndex,pieceToCapture.GetComponent<SpriteRenderer>().sprite);
}
else
{
ChessPieceEvent(pieceToCapture.pieceIndex + 6, pieceToCapture.GetComponent<SpriteRenderer>().sprite);
}
for (int x = 0; x < pieces.GetLength(0); x++)
{
for (int y = 0; y < pieces.GetLength(1); y++)
{
if(pieces[x,y] == pieceToCapture)
{
posToMoveTo = pieces[x, y].posOnBoard;
pieces[x, y] = null;
Destroy(pieceToCapture.gameObject);
}
}
}
Destroy(pieceToCapture.gameObject);
MovePiece(posToMoveTo,selectedPiece);
}
public int PosX(Vector2Int coords)
{
return CheckGridPosAtCoords(coords).x;
}
public int PosY(Vector2Int coords)
{
return CheckGridPosAtCoords(coords).y;
}
public void SelectPiece(ChessPiece piece)
{
if(selectedPiece == null)
{
RemoveSelectionBoxes();
}
selectedPiece = piece;
HighlightSelectedPiece();
for (int i = 0; i < selectedPiece.legalMoves.Count; i++)
{
boxes.Add(Instantiate(movementBox, boardGrid[selectedPiece.legalMoves[i].x, selectedPiece.legalMoves[i].y], transform.rotation));
}
}
void HighlightSelectedPiece()
{
highlighter.SetActive(true);
highlighter.transform.position = selectedPiece.transform.position;
}
public void DeselectPiece()
{
selectedPiece = null;
RemoveSelectionBoxes();
}
void RemoveSelectionBoxes()
{
for (int i = 0; i < boxes.Count; i++)
{
Destroy(boxes[i]);
}
}
public bool CheckIfArrayIsOutOfBounds(Vector2Int pos)
{
return pos.x > -1 && pos.x < 8 && pos.y > -1 && pos.y < 8;
}
public bool CheckIfCoordsAreOnGrid(Vector2 coords)
{
float distance = 2;
Vector2Int pieceInd = Vector2Int.one * -1;
for (int x = 0; x < boardGrid.GetLength(0); x++)
{
for (int y = 0; y < boardGrid.GetLength(1); y++)
{
if (Vector2.Distance(cam.ScreenToWorldPoint(coords), boardGrid[x, y]) < distance)
{
distance = Vector2.Distance(cam.ScreenToWorldPoint(coords), boardGrid[x, y]);
pieceInd = new Vector2Int(x, y);
return true;
}
}
}
if (pieceInd == Vector2Int.one * -1)
{
return false;
}
return false;
}
void StartNewTurn()
{
SwitchActiveTeam();
for (int i = 0; i < pieces.GetLength(0); i++)
{
for (int j = 0; j < pieces.GetLength(1); j++)
{
if(pieces[i,j] != null)
{
pieces[i, j].CalculateLegalMoves();
}
}
}
if(currentTeam != onePlayerTeam && !enemyTurn && GameManager.isSinglePlayer)
{
StopAllCoroutines();
StartCoroutine(ComputerTurn());
}
}
IEnumerator ComputerTurn()
{
if (!gameOver)
{
enemyTurn = true;
float random = UnityEngine.Random.Range(1f, 5f);
yield return new WaitForSeconds(random);
CheckAllLegalMoves();
ComputerRandomMove();
enemyTurn = false;
}
}
public void ComputerRandomMove()
{
ChessPiece pieceToMove = GetRandomPieceOfTeam();
int highestNumber = 1;
for (int i = 0; i < 500; i++)
{
pieceToMove = GetRandomPieceOfTeam();
if ( pieceToMove.legalMoves.Count > 0)
{
break;
}
highestNumber = i + 1;
}
bool moving = false; ;
List<Vector2Int> moves = new List<Vector2Int>();
for (int i = 0; i < pieceToMove.legalMoves.Count; i++)
{
moves.Add(pieceToMove.legalMoves[i]);
if(pieces[pieceToMove.legalMoves[i].x, pieceToMove.legalMoves[i].y] != null)
{
SelectPiece(pieceToMove);
moving = true;
CapturePiece(pieces[pieceToMove.legalMoves[i].x, pieceToMove.legalMoves[i].y]);
break;
}
}
if (!moving)
{
int random = UnityEngine.Random.Range(0, moves.Count);
SelectPiece(pieceToMove);
MovePiece(pieceToMove.legalMoves[random], selectedPiece);
}
}
ChessPiece GetRandomPieceOfTeam()
{
List<ChessPiece> piecesToCycle = new List<ChessPiece>();
for (int i = 0; i < pieces.GetLength(0); i++)
{
for (int j = 0; j < pieces.GetLength(1); j++)
{
if (pieces[i, j] != null && pieces[i, j].team != onePlayerTeam)
{
piecesToCycle.Add(pieces[i, j]);
}
}
}
int random = UnityEngine.Random.Range(0, piecesToCycle.Count);
return piecesToCycle[random];
}
void ChessPieceEvent(int pieceIndex, Sprite sprite)
{
if (pieceIndex < 5) {
numCapturedWhite++;
GameObject deadPiece = Instantiate(Resources.Load("Prefabs/CapturedPiece") as GameObject,onePlayerPiecesGraveyard[numCapturedWhite % 2]);
deadPiece.GetComponent<Image>().sprite = sprite;
if(pieceIndex == 0)
{
EndGame(TeamColor.Black);
}
}
else
{
numCapturedBlack++;
GameObject deadPiece = Instantiate(Resources.Load("Prefabs/CapturedPiece") as GameObject, twoPlayerPiecesGraveyard[numCapturedBlack % 2]);
deadPiece.GetComponent<Image>().sprite = sprite;
if(pieceIndex == 6)
{
print("King died?");
blackKingDown = true;
}
if(pieceIndex == 11)
{
blackQueenDown = true;
}
if(blackKingDown && blackQueenDown)
{
EndGame(TeamColor.White);
}
}
bubble.SpeechBubbleDisplay(pieceIndex);
}
public void EndGame(TeamColor victor)
{
print("Game over, man");
gameOver = true;
}
}
