Christmas Crunch
A Cahotic Party Game
A Cahotic Party Game

Christmas Crunch is a chaotic, festive mix and match inspired by the frantic gameplay of Overcooked.
Device Management and Multiplayer Plugin
Unreal Engine’s native local multiplayer management lacks the flexibility to handle dynamic controller connections and disconnections and the rapid reassignment of players to gameplay entities (e.g., team management, slot reassignment). The goal was to create a centralized system that could be reused across projects without duplicating code in GameMode or PlayerController.
Technical Approach & Architecture
- Using a
UGameInstanceSubsystemto centralize functions and events throughout the entire game, as well as a map that links the equipment to the players in the game. - Implementation of the Unreal framework with controller connection events from
IPlatformInputDeviceMapper.
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayerConnected, FPlatformUserId, Platform);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayerDeConnected, FPlatformUserId, Platform);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayerReConnected, FPlatformUserId, Platform);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayerRemoved, FPlatformUserId, Platform);
void UCMSubsystem::OnConnectionChange(EInputDeviceConnectionState NewConnectionState, FPlatformUserId PlatformUserID,
FInputDeviceId InputDeviceID)
{
switch (NewConnectionState) {
case EInputDeviceConnectionState::Connected:
//Verifie si le joueur existe deja
if (ConnectedPlayers.Contains(PlatformUserID))
{
//Si le joueur existe, update l'identifant des controles
auto& Data = ConnectedPlayers[PlatformUserID].DeviceIds;
if (!Data.Contains(InputDeviceID))
{
Data.Add(InputDeviceID);
}
OnPlayerConnected.Broadcast(PlatformUserID);
}
else
{
//Verifie si un local player existe deja
if (APlayerController* PC = UGameplayStatics::GetPlayerControllerFromPlatformUser(GetWorld(), PlatformUserID))
{
//Ajoute dans la liste
FControllerData Data;
Data.DeviceIds.Add(InputDeviceID);
Data.Player = PC->GetLocalPlayer();
ConnectedPlayers.Add(PlatformUserID, Data);
//Restat le playe si pas de pawn si in game
}
else
{
//verifie si joueur max n'est pas atteind
if (ConnectedPlayers.Num() < UControllersSettings::Get()->MaxPlayer)
{
FControllerData Data;
Data.DeviceIds.Add(InputDeviceID);
ConnectedPlayers.Add(PlatformUserID, Data);
OnPlayerConnected.Broadcast(PlatformUserID);
break;
}
}
}
break;
}
}
