Devlog5. Turn Management


Managing Turns in a Multiplayer Board Game

Introduction

While developing the multiplayer board game Dice & Domination, we faced specific challenges unique to online environments. Unlike local board games that run on a single device, multiplayer games must maintain a consistent and synchronized state across all connected clients.

Problems I Encountered

  1. Without a strict ownership system, multiple players could attempt to interact with the board at the same time—for example, two players rolling the dice simultaneously or trying to buy the same property.
  2. Turn synchronization proved difficult. If each client tracked turn order independently, players could easily fall out of sync.

Solution

To address these challenges, we implemented a Player ID-based management system. Every player in a room is assigned a unique Player ID by Photon. This ID acts as the single source of truth for controlling dice rolls, resource transactions, board movements, and event triggers. During gameplay, only the player whose ID matches the current turn is allowed to interact with the board.

The TurnManager is created to manage turns across all players. It is only active in Board Mode and is not needed in Arena Mode. It uses Player IDs to track whose turn it is

Workflow Overview

When a player's turn begins, TurnManager notifies their BoardPlayer to enable movement. Then, all other players remain in a waiting state and cannot act. Once the active player completes their actions, the turn automatically switches to the next player.

Implementation

After game starts, it  initializes player names and the UI list, and refreshes the current turn display. When a dice finishes rolling, Dice_OnDiceLanded() is triggered. If the player is not eliminated and it’s their turn, the End Turn button becomes intractable. It means players can only end their turn after completing their dice action, not randomly in the middle of a roll.


End turn button not interactable(left), interactable(right)

Ending a turn is managed by the EndTurn() method . If the game is not paused and the local player owns the current turn, it calculates the next alive player by skipping eliminated ones. It then calls RPC_SetTurn() via Photon RPC to update the turn index across all clients.


The RPC_SetTurn() method sets the new active player, increments the round counter if necessary, and checks for maximum rounds to handle game over conditions. Once the turn changes, the TransferTurnTo() method assigns dice ownership to the next player and resets the dice, ensuring that only the correct player can roll next.


When a player leaves the room, it will automatically updates the player list, releases any tiles owned by the leaving player, and reassigns the dice to a valid active player.  Also if a player is eliminated, they are skipped in future turn rotations. If the eliminated player is the local player, their turn ends immediately and the game proceeds to the next player.



Passing turn and skipping eliminated players

Design Patterns

  • Mediator: TurnManager coordinates between DiceManager, BoardPlayer, UI updates, and player ownership transfer without direct dependencies between them.
  • State: Each player alternates between active and waiting states during turn progression.

Gameplay Demonstration

Turn switching among 4 players

 UI and turn order are automatically updated when a player leaves the room

Button UI

Final Outcome

During this phase, I completed the core systems for player movement, dice rolling, and turn management. Based on multiple multiplayer tests, the core functionalities performed as expected. Players could only act during their turn, dice results were identical across clients, and movement were synchronized.

Reference

Gerenated button UI. Source: ChatGPT 

Leave a comment

Log in with itch.io to leave a comment.