LoadSensePro is a production-ready loading screen system for Unreal Engine 5 that provides async UMG rendering, multiplayer synchronization, group travel system, and comprehensive Blueprint integration.
Current Version: 1.2.1
UAsyncLoadingScreenRendererLoadMapWithScreen() and LoadMapByDataAsset() for seamless transitionsbUseTrueAsyncRendering setting for non-blocking UIRegisterSyncActor() and IsMultiplayerSyncEnabled()UGroupTravelSystemBlueprintCallable functionsULoadingScreenDataAssetPlugins folder// In your GameMode or GameInstance
#include "System/LoadingScreenSubsystem"
// Get the subsystem
ULoadingScreenSubsystem* LoadingSubsystem = GetGameInstance()->GetSubsystem<ULoadingScreenSubsystem>();
// Configure minimum loading time
LoadingSubsystem->SetMinimumLoadingTime(2.0f);
// Load a map with a loading screen widget class
LoadingSubsystem->LoadMapWithScreen(TEXT("NextLevel"), MyLoadingWidgetClass);
// Load a map using a data asset
ULoadingScreenDataAsset* LoadScreenData = LoadObject<ULoadingScreenDataAsset>(nullptr, TEXT("/Game/LoadingScreens/MyLoadScreen.MyLoadScreen"));
LoadingSubsystem->LoadMapByDataAsset(LoadScreenData);
// Show loading screen without level transition (for long operations)
LoadingSubsystem->ShowStandaloneLoadingScreenByDataAsset(LoadScreenAsset);
// Update progress manually
LoadingSubsystem->UpdateStandaloneProgress(0.5f, TEXT("Processing assets..."));
// Update status text without changing progress
LoadingSubsystem->SetStandaloneStatus(TEXT("Finalizing setup..."));
// Hide when done
LoadingSubsystem->HideStandaloneLoadingScreen();
// Check if loading screen is active
if (LoadingSubsystem->IsLoadingScreenActive())
{
ELoadingScreenState CurrentState = LoadingSubsystem->GetCurrentState();
// Handle current state (Inactive, Loading, WaitingForLevel, etc.)
}
// Check if standalone mode is active
if (LoadingSubsystem->IsStandaloneLoadingScreenActive())
{
// Update progress for standalone loading
}
// Check if multiplayer sync is available
if (LoadingSubsystem->IsMultiplayerSyncEnabled())
{
// Register actors that need to participate in loading synchronization
LoadingSubsystem->RegisterSyncActor(MyGameMode);
LoadingSubsystem->RegisterSyncActor(MyCustomSyncActor);
// Get current client sync status
TArray<FClientSyncStatus> ClientStatuses = LoadingSubsystem->GetClientSyncStatus();
for (const FClientSyncStatus& Status : ClientStatuses)
{
UE_LOG(LogTemp, Log, TEXT("Client %s: Ready=%s"),
*Status.ClientId, Status.bIsReady ? TEXT("Yes") : TEXT("No"));
}
// Force client synchronization with timeout override
LoadingSubsystem->ForceClientSync(10.0f); // 10 second timeout
// Check if all clients are ready
if (LoadingSubsystem->AreAllClientsReady())
{
UE_LOG(LogTemp, Log, TEXT("All clients are ready for loading!"));
}
}
// Method 1: Using the simplified interface through LoadingScreenSubsystem
APlayerController* LeaderPC = GetFirstLocalPlayerController();
ULoadingScreenDataAsset* GroupLoadScreen = LoadObject<ULoadingScreenDataAsset>(nullptr, TEXT("/Game/LoadingScreens/GroupLoadScreen.GroupLoadScreen"));
// Initialize group travel with parameters
bool bSuccess = LoadingSubsystem->InitializeGroupTravel(LeaderPC, TEXT("BossLevel"), GroupLoadScreen, 4, 2);
// Quick start (even more simplified)
LoadingSubsystem->QuickStartGroupTravel(TEXT("NextLevel"), GroupLoadScreen);
// Method 2: Using the Group Travel System directly
UGroupTravelSystem* GroupTravel = LoadingSubsystem->GetGroupTravelSystem();
// Create detailed configuration
FGroupTravelConfig Config;
Config.TargetMapName = TEXT("BossLevel");
Config.GroupLoadingScreen = GroupLoadScreen;
Config.MaxGroupSize = 8;
Config.MinGroupSize = 2;
Config.ConfirmationTimeout = 30.0f;
Config.ReadyTimeout = 60.0f;
Config.bRequireAllMembers = true;
Config.bAllowLateJoiners = false;
// Initialize group travel
if (GroupTravel->InitializeGroupTravel(LeaderPC, Config))
{
// Add players to group
GroupTravel->AddPlayerToGroup(Player2Controller, true); // Requires confirmation
GroupTravel->AddPlayerToGroup(Player3Controller, false); // Auto-confirm
// Start the travel process (players must confirm first)
GroupTravel->StartGroupTravel();
// Or force start immediately
// GroupTravel->ForceStartGroupTravel();
}
// In your class constructor or BeginPlay
ULoadingScreenSubsystem* LoadingSubsystem = GetGameInstance()->GetSubsystem<ULoadingScreenSubsystem>();
// Bind to loading screen events
LoadingSubsystem->OnLoadingScreenStateChanged.AddDynamic(this, &AMyGameMode::OnLoadingScreenStateChanged);
LoadingSubsystem->OnMapLoadingComplete.AddDynamic(this, &AMyGameMode::OnMapLoadingComplete);
LoadingSubsystem->OnMapLoadingProgress.AddDynamic(this, &AMyGameMode::OnMapLoadingProgress);
// Bind to multiplayer events
LoadingSubsystem->OnClientSyncStatusChanged.AddDynamic(this, &AMyGameMode::OnClientSyncStatusChanged);
LoadingSubsystem->OnAllClientsReady.AddDynamic(this, &AMyGameMode::OnAllClientsReady);
// Bind to group travel events
UGroupTravelSystem* GroupTravel = LoadingSubsystem->GetGroupTravelSystem();
GroupTravel->OnGroupTravelStateChanged.AddDynamic(this, &AMyGameMode::OnGroupTravelStateChanged);
GroupTravel->OnGroupMemberJoined.AddDynamic(this, &AMyGameMode::OnGroupMemberJoined);
void LoadMapWithScreen(const FString& MapName, TSubclassOf<UUserWidget> LoadingWidgetClass)
void LoadMapByDataAsset(ULoadingScreenDataAsset* LoadingScreenData)
void ShowStandaloneLoadingScreen(TSubclassOf<UUserWidget> LoadingWidgetClass)
void ShowStandaloneLoadingScreenByDataAsset(ULoadingScreenDataAsset* LoadingScreenData)
void HideStandaloneLoadingScreen()
void ForceStopLoadingScreen()
void UpdateStandaloneProgress(float Progress, const FString& StatusText = TEXT("Processing..."))
void SetStandaloneStatus(const FString& StatusText, float Progress = -1.0f)
bool IsStandaloneLoadingScreenActive() const
bool IsLoadingScreenActive() const
ELoadingScreenState GetCurrentState() const
void SetMinimumLoadingTime(float MinTime)
void RegisterSyncActor(AActor* SyncActor)
void UnregisterSyncActor(AActor* SyncActor)
bool AreAllClientsReady() const
void ForceClientSync(float TimeoutOverride = -1.0f)
TArray<FClientSyncStatus> GetClientSyncStatus() const
bool IsMultiplayerSyncEnabled() const
void SetClientReady(const FString& ClientId, bool bReady)
int32 GetRequiredClientCount() const
UGroupTravelSystem* GetGroupTravelSystem() const
bool InitializeGroupTravel(APlayerController* GroupLeader, const FString& MapName, ULoadingScreenDataAsset* GroupLoadingScreen = nullptr, int32 MaxGroupSize = 4, int32 MinGroupSize = 1)
void QuickStartGroupTravel(const FString& MapName, ULoadingScreenDataAsset* GroupLoadingScreen = nullptr)
FOnLoadingScreenStateChanged OnLoadingScreenStateChanged
FOnMapLoadingComplete OnMapLoadingComplete
FOnMapLoadingProgress OnMapLoadingProgress
FOnStandaloneStatusChanged OnStandaloneStatusChanged
FOnClientSyncStatusChanged OnClientSyncStatusChanged
FOnAllClientsReady OnAllClientsReady
FOnClientSyncTimeout OnClientSyncTimeout
bool InitializeGroupTravel(APlayerController* GroupLeader, const FGroupTravelConfig& TravelConfig)
bool AddPlayerToGroup(APlayerController* PlayerController, bool bRequireConfirmation = true)
bool RemovePlayerFromGroup(APlayerController* PlayerController)
void InvitePlayersToGroup(const TArray<APlayerController*>& PlayerControllers, const FString& InvitationMessage = TEXT(""))
bool StartGroupTravel()
bool ConfirmPlayerParticipation(APlayerController* PlayerController)
bool SetPlayerReady(APlayerController* PlayerController)
bool ForceStartGroupTravel()
void CancelGroupTravel(const FString& CancellationReason = TEXT("Travel cancelled"))
EGroupTravelState GetGroupTravelState() const
TArray<FGroupMemberInfo> GetGroupMembers() const
FGroupMemberInfo GetGroupLeader() const
bool AreAllMembersConfirmed() const
bool AreAllMembersReady() const
int32 GetGroupSize() const
bool IsGroupTravelActive() const
FOnGroupTravelStateChanged OnGroupTravelStateChanged
FOnGroupMemberJoined OnGroupMemberJoined
FOnGroupMemberLeft OnGroupMemberLeft
FOnGroupMemberConfirmed OnGroupMemberConfirmed
FOnGroupMemberReady OnGroupMemberReady
FOnGroupTravelStarted OnGroupTravelStarted
FOnGroupTravelCompleted OnGroupTravelCompleted
FOnGroupTravelFailed OnGroupTravelFailed
enum class ELoadingScreenState : uint8
{
Inactive, // No loading screen active
Loading, // Loading screen is showing
WaitingForLevel, // Waiting for level to load
WaitingForClients, // Waiting for multiplayer clients
Finishing // Loading completion phase
};
enum class EGroupTravelState : uint8
{
Inactive, // No group travel in progress
FormingGroup, // Forming group for travel
WaitingForConfirm, // Waiting for all group members to confirm
PreparingTravel, // Group confirmed, preparing to travel
TravelInProgress, // Travel in progress with loading screens
SynchronizingArrival // Synchronizing arrival on destination
};
struct FClientSyncStatus
{
FString ClientId; // Unique client identifier
bool bIsReady = false; // Whether client is ready
float LastUpdateTime = 0.0f; // Last update timestamp
FString PlayerName; // Player display name
};
struct FGroupMemberInfo
{
FString PlayerId; // Player's unique identifier
FString PlayerName; // Player's display name
bool bHasConfirmed = false; // Whether player has confirmed travel
bool bIsReady = false; // Whether player is ready for travel
float ConnectionQuality = 1.0f; // Player's connection quality
float LastUpdateTime = 0.0f; // Last update time
};
struct FGroupTravelConfig
{
FString TargetMapName; // Target map for group travel
ULoadingScreenDataAsset* GroupLoadingScreen; // Loading screen data for group travel
int32 MaxGroupSize = 8; // Maximum group size
int32 MinGroupSize = 2; // Minimum group size to proceed
float ConfirmationTimeout = 30.0f; // Time to wait for confirmations
float ReadyTimeout = 60.0f; // Time to wait for all members to be ready
bool bRequireAllMembers = true; // Whether to wait for all members or proceed with majority
bool bAllowLateJoiners = false; // Allow members to join during travel preparation
};
DefaultLoadingScreenDataAsset - Default loading screen data assetMinimumLoadingTime - Minimum time loading screen is shown (default: 2.0f)LevelCheckInterval - How often to check if level is loaded (default: 0.1f)GracePeriodAfterLoad - Extra time after level load before hiding (default: 0.5f)bPreloadImages - Whether to preload loading screen images (default: true)bUseAsyncLoading - Use async loading system (default: true)bUseTrueAsyncRendering - Use true async rendering (default: true)ClientSyncTimeout - Timeout for client synchronization (default: 30.0f)bRequireAllClientsReady - Require all clients to be ready (default: true)MinimumPlayersRequired - Minimum players for multiplayer sync (default: 1)ClientSyncCheckInterval - How often to check client sync (default: 0.5f)bEnableMultiplayerSync - Enable multiplayer synchronization (default: true)Problem: “Could not find definition for module” or build fails when adding LoadSensePro
Solution: Ensure OnlineSubsystemUtils is set as optional/disabled in the plugin configuration for single-player projects. LoadSensePro now has optional networking dependencies.
Problem: LoadMapWithScreen or LoadMapByDataAsset doesn’t show loading screen
Solutions:
MinimumLoadingTime is set appropriately (default: 2.0f)bUseAsyncLoading and bUseTrueAsyncRendering are enabledProblem: Standalone loading screen doesn’t update progress
Solutions:
IsStandaloneLoadingScreenActive() to verify standalone mode is activeUpdateStandaloneProgress() with values between 0.0 and 1.0SetStandaloneStatus() for status-only updatesHideStandaloneLoadingScreen() when finishedProblem: Players not synchronizing properly or IsMultiplayerSyncEnabled() returns false
Solutions:
bEnableMultiplayerSync is enabled in subsystem settingsGetClientSyncStatus() to debug individual client statesForceClientSync() with appropriate timeout if neededProblem: Group travel initialization fails or players don’t join
Solutions:
FGroupTravelConfig has valid settings (check MinGroupSize <= MaxGroupSize)ValidateGroupConfiguration() returns trueGetGroupTravelState() to debug current stateValidatePlayerForGroup() checks// In game console or during development
showlog // Show console output
stat game // Show game performance stats
// Enable detailed logging
ULoadingScreenSubsystem* LoadingSubsystem = GetGameInstance()->GetSubsystem<ULoadingScreenSubsystem>();
// Check current state
ELoadingScreenState State = LoadingSubsystem->GetCurrentState();
UE_LOG(LogTemp, Log, TEXT("Current loading state: %d"), (int32)State);
// Check multiplayer sync
bool bMultiplayerEnabled = LoadingSubsystem->IsMultiplayerSyncEnabled();
TArray<FClientSyncStatus> ClientStatuses = LoadingSubsystem->GetClientSyncStatus();
UE_LOG(LogTemp, Log, TEXT("Multiplayer enabled: %s, Clients: %d"),
bMultiplayerEnabled ? TEXT("Yes") : TEXT("No"), ClientStatuses.Num());
// Check group travel
UGroupTravelSystem* GroupTravel = LoadingSubsystem->GetGroupTravelSystem();
EGroupTravelState TravelState = GroupTravel->GetGroupTravelState();
TArray<FGroupMemberInfo> Members = GroupTravel->GetGroupMembers();
UE_LOG(LogTemp, Log, TEXT("Group travel state: %d, Members: %d"),
(int32)TravelState, Members.Num());
bUseAsyncLoading and bUseTrueAsyncRendering enabled for smooth performanceClientSyncTimeout and MinimumLoadingTime based on your contentClientSyncCheckInterval to balance responsiveness with network trafficConfirmationTimeout and ReadyTimeout based on your game’s loading timesMinimumPlayersRequiredbRequireAllMembers setting appropriately for your game designThis documentation is based on LoadSensePro v1.1.7 source code and includes only validated, existing functionality. For the latest updates and community support, visit our Discord server.