# 【定义新委托类型】
定义委托的宏例子
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMutiplayerOnCreateSessionComplete, bool, bWasSuccessful);
有 DYNAMIC 则表示可以被Blueprint蓝图脚本调用和绑定。
没有 DYNAMIC 则表示只能在C++代码中使用。
有 MULTICAST 则表示可以绑定多个回调函数,且可以通过委托对象的Broadcast()方法触发。
没有 MULTICAST 则表示只能绑定一个回调函数,并且只能通过委托对象的Execute()方法触发。
# 使用示例
- 定义委托类型
- 定义委托实例
MultiplayerSessionsSubsystem.h
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "Interfaces/OnlineSessionInterface.h"
#include "MultiplayerSessionsSubsystem.generated.h"
//
// 为Menu类定义我们自己的委托类型
//
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMutiplayerOnCreateSessionComplete, bool, bWasSuccessful);
DECLARE_MULTICAST_DELEGATE_TwoParams(FMultiplayerOnFindSessionsComplete, const TArray<FOnlineSessionSearchResult>& SessionResults, bool bWasSuccessful);
DECLARE_MULTICAST_DELEGATE_OneParam(FMultiplayerOnJoinSessionComplete, EOnJoinSessionCompleteResult::Type Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMutiplayerOnDestroySessionComplete, bool, bWasSuccessful);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMutiplayerOnStartSessionComplete, bool, bWasSuccessful);
/**
*
*/
UCLASS()
class MULTIPLAYERSESSIONS_API UMultiplayerSessionsSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
UMultiplayerSessionsSubsystem();
void CreateSession(int32 NumPublicConnections, FString MatchType);
void FindSessions(int32 MaxSearchResults);
void JoinSession(const FOnlineSessionSearchResult& SessionResult);
void DestroySession();
void StartSession();
//
// 为Menu类定义我们自己的委托实例
//
FMutiplayerOnCreateSessionComplete MutiplayerOnCreateSessionComplete;
FMultiplayerOnFindSessionsComplete MultiplayerOnFindSessionsComplete;
FMultiplayerOnJoinSessionComplete MultiplayerOnJoinSessionComplete;
FMutiplayerOnDestroySessionComplete MutiplayerOnDestroySessionComplete;
FMutiplayerOnStartSessionComplete MutiplayerOnStartSessionComplete;
protected:
void OnCreateSessionComplete(FName SessionName,bool bWasSuccessful);
void OnFindSessionsComplete(bool bWasSuccessful);
void OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result);
void OnDestroySessionComplete(FName SessionName, bool bWasSuccessful);
void OnStartSessionComplete(FName SessionName, bool bWasSuccessful);
private:
IOnlineSessionPtr SessionInterface;
TSharedPtr<FOnlineSessionSettings> LastSessionSettings;
TSharedPtr<FOnlineSessionSearch> LastSessionSearch;
FOnCreateSessionCompleteDelegate CreateSessionCompleteDelegate;
FDelegateHandle CreateSessionCompleteDelegateHandle;
FOnFindSessionsCompleteDelegate FindSessionsCompleteDelegate;
FDelegateHandle FindSessionsCompleteDelegateHandle;
FOnJoinSessionCompleteDelegate JoinSessionCompleteDelegate;
FDelegateHandle JoinSessionCompleteDelegateHandle;
FOnDestroySessionCompleteDelegate DestroySessionCompleteDelegate;
FDelegateHandle DestroySessionCompleteDelegateHandle;
FOnStartSessionCompleteDelegate StartSessionCompleteDelegate;
FDelegateHandle StartSessionCompleteDelegateHandle;
};
对自定义委托进行广播。
MultiplayerSessionsSubsystem.cpp
#include "MultiplayerSessionsSubsystem.h"
#include <OnlineSubsystem.h>
#include "OnlineSessionSettings.h"
#include <Online/OnlineSessionNames.h>
UMultiplayerSessionsSubsystem::UMultiplayerSessionsSubsystem():
CreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this,&ThisClass::OnCreateSessionComplete)),
FindSessionsCompleteDelegate(FOnFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnFindSessionsComplete)),
JoinSessionCompleteDelegate(FOnJoinSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnJoinSessionComplete)),
DestroySessionCompleteDelegate(FOnDestroySessionCompleteDelegate::CreateUObject(this, &ThisClass::OnDestroySessionComplete)),
StartSessionCompleteDelegate(FOnStartSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnStartSessionComplete))
{
IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get();
if (Subsystem)
{
SessionInterface = Subsystem->GetSessionInterface();
}
}
void UMultiplayerSessionsSubsystem::CreateSession(int32 NumPublicConnections, FString MatchType)
{
if (!SessionInterface.IsValid())
{
return;
}
auto ExistingSession = SessionInterface->GetNamedSession(NAME_GameSession);
if (ExistingSession != nullptr)
{
SessionInterface->DestroySession(NAME_GameSession);
}
CreateSessionCompleteDelegateHandle = SessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate);
LastSessionSettings = MakeShareable(new FOnlineSessionSettings());
bool bIsLAN = false;
if (IOnlineSubsystem::Get()->GetSubsystemName() == "NULL")
{
bIsLAN = true;
}
LastSessionSettings->bIsLANMatch = bIsLAN;
LastSessionSettings->NumPublicConnections = NumPublicConnections;
LastSessionSettings->bAllowJoinInProgress = true;
LastSessionSettings->bAllowJoinViaPresence = true;
LastSessionSettings->bShouldAdvertise = true;
LastSessionSettings->bUsesPresence = true;
LastSessionSettings->bUseLobbiesIfAvailable = true;
LastSessionSettings->Set(FName("MatchType"), MatchType, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
bool bCresteSuccess = SessionInterface->CreateSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, *LastSessionSettings);
if (!bCresteSuccess)
{
SessionInterface->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegateHandle);
// 广播我们的自定义委托
MutiplayerOnCreateSessionComplete.Broadcast(false);
}
}
void UMultiplayerSessionsSubsystem::FindSessions(int32 MaxSearchResults)
{
if (!SessionInterface.IsValid())
{
return;
}
bool bIsLAN = false;
if (IOnlineSubsystem::Get()->GetSubsystemName() == "NULL")
{
bIsLAN = true;
}
FindSessionsCompleteDelegateHandle = SessionInterface->AddOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegate);
LastSessionSearch = MakeShareable(new FOnlineSessionSearch());
LastSessionSearch->MaxSearchResults = MaxSearchResults;
LastSessionSearch->bIsLanQuery = bIsLAN;
LastSessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);
const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
bool isFindSucc = SessionInterface->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(), LastSessionSearch.ToSharedRef());
if (!isFindSucc)
{
SessionInterface->ClearOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegateHandle);
// 广播我们的自定义委托
MultiplayerOnFindSessionsComplete.Broadcast(TArray<FOnlineSessionSearchResult>(), false);
}
}
void UMultiplayerSessionsSubsystem::JoinSession(const FOnlineSessionSearchResult& SessionResult)
{
if (!SessionInterface.IsValid())
{
MultiplayerOnJoinSessionComplete.Broadcast(EOnJoinSessionCompleteResult::UnknownError);
return;
}
JoinSessionCompleteDelegateHandle = SessionInterface->AddOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegate);
const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
if (!SessionInterface->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, SessionResult))
{
SessionInterface->ClearOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegateHandle);
// 广播我们的自定义委托
MultiplayerOnJoinSessionComplete.Broadcast(EOnJoinSessionCompleteResult::UnknownError);
}
}
void UMultiplayerSessionsSubsystem::DestroySession()
{
}
void UMultiplayerSessionsSubsystem::StartSession()
{
}
void UMultiplayerSessionsSubsystem::OnCreateSessionComplete(FName SessionName, bool bWasSuccessful)
{
if (SessionInterface)
{
SessionInterface->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegateHandle);
}
// 广播我们的自定义委托
MutiplayerOnCreateSessionComplete.Broadcast(bWasSuccessful);
}
void UMultiplayerSessionsSubsystem::OnFindSessionsComplete(bool bWasSuccessful)
{
if (SessionInterface)
{
SessionInterface->ClearOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegateHandle);
}
if (LastSessionSearch->SearchResults.Num() <= 0)
{
// 广播我们的自定义委托
MultiplayerOnFindSessionsComplete.Broadcast(TArray<FOnlineSessionSearchResult>(), false);
return;
}
MultiplayerOnFindSessionsComplete.Broadcast(LastSessionSearch->SearchResults, bWasSuccessful);
}
void UMultiplayerSessionsSubsystem::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
{
if (SessionInterface)
{
SessionInterface->ClearOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegateHandle);
}
// 广播我们的自定义委托
MultiplayerOnJoinSessionComplete.Broadcast(Result);
}
void UMultiplayerSessionsSubsystem::OnDestroySessionComplete(FName SessionName, bool bWasSuccessful)
{
}
void UMultiplayerSessionsSubsystem::OnStartSessionComplete(FName SessionName, bool bWasSuccessful)
{
}
在业务类进行绑定委托函数。
Menu.cpp
#include "Menu.h"
#include "Components/Button.h"
#include "MultiplayerSessionsSubsystem.h"
#include "OnlineSessionSettings.h"
#include <OnlineSubsystem.h>
#include "Interfaces/OnlineSessionInterface.h"
void UMenu::MenuSetup(int32 NumberOfPublicConnections, FString TypeOfMatch)
{
NumberPublicConnections = NumberOfPublicConnections;
MatchType = TypeOfMatch;
AddToViewport();
SetVisibility(ESlateVisibility::Visible);
bIsFocusable = true;
UWorld* World = GetWorld();
if (World)
{
APlayerController* PlayerController = World->GetFirstPlayerController();
if (PlayerController)
{
FInputModeUIOnly InputModeData;
InputModeData.SetWidgetToFocus(TakeWidget());
InputModeData.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);
PlayerController->SetInputMode(InputModeData);
PlayerController->SetShowMouseCursor(true);
}
}
UGameInstance* GameInstance = GetGameInstance();
if (GameInstance)
{
MultiplayerSessionsSubsystem = GameInstance->GetSubsystem<UMultiplayerSessionsSubsystem>();
}
if (MultiplayerSessionsSubsystem)
{
// 绑定委托函数
MultiplayerSessionsSubsystem->MutiplayerOnCreateSessionComplete.AddDynamic(this,&ThisClass::OnCreateSession);
MultiplayerSessionsSubsystem->MultiplayerOnFindSessionsComplete.AddUObject(this, &ThisClass::OnFindSessions);
MultiplayerSessionsSubsystem->MultiplayerOnJoinSessionComplete.AddUObject(this, &ThisClass::OnJoinSession);
MultiplayerSessionsSubsystem->MutiplayerOnDestroySessionComplete.AddDynamic(this, &ThisClass::OnDestroySession);
MultiplayerSessionsSubsystem->MutiplayerOnStartSessionComplete.AddDynamic(this, &ThisClass::OnStartSession);
}
}
bool UMenu::Initialize()
{
if (!Super::Initialize())
{
return false;
}
if (HostButton)
{
HostButton->OnClicked.AddDynamic(this, &ThisClass::HostButtonClicked);
}
if (JoinButton)
{
JoinButton->OnClicked.AddDynamic(this, &ThisClass::JoinButtonClicked);
}
return true;
}
void UMenu::NativeDestruct()
{
MenuTearDown();
}
void UMenu::OnCreateSession(bool bWasSuccessful)
{
if (bWasSuccessful)
{
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(
-1,
15.f,
FColor::Yellow,
FString(TEXT("Session Created Successfully!"))
);
}
UWorld* World = GetWorld();
if (World)
{
World->ServerTravel("/Game/ThirdPerson/Maps/Lobby?listen");
}
}
else
{
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(
-1,
15.f,
FColor::Red,
FString(TEXT("Failed to create session!"))
);
}
}
}
void UMenu::OnFindSessions(const TArray<FOnlineSessionSearchResult>& SessionResults, bool bWasSuccessful)
{
if (MultiplayerSessionsSubsystem == nullptr)
{
return;
}
int32 num = SessionResults.Num();
if (GEngine && bWasSuccessful)
{
GEngine->AddOnScreenDebugMessage(
-1,
15.f,
FColor::Yellow,
FString(TEXT("OnFindSessions Successful"))
);
}
for (auto Result : SessionResults)
{
FString SettingsValue;
Result.Session.SessionSettings.Get(FName("MatchType"), SettingsValue);
if (SettingsValue == MatchType)
{
MultiplayerSessionsSubsystem->JoinSession(Result);
return;
}
}
}
void UMenu::OnJoinSession(EOnJoinSessionCompleteResult::Type Result)
{
IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get();
if (Subsystem)
{
IOnlineSessionPtr SessionInterface = Subsystem->GetSessionInterface();
if (SessionInterface.IsValid())
{
FString Address;
SessionInterface->GetResolvedConnectString(NAME_GameSession, Address);
APlayerController* PlayerController = GetGameInstance()->GetFirstLocalPlayerController();
if (PlayerController)
{
PlayerController->ClientTravel(Address, ETravelType::TRAVEL_Absolute);
}
}
}
}
void UMenu::OnDestroySession(bool bWasSuccessful)
{
}
void UMenu::OnStartSession(bool bWasSuccessful)
{
}
void UMenu::HostButtonClicked()
{
if (MultiplayerSessionsSubsystem)
{
MultiplayerSessionsSubsystem->CreateSession(NumberPublicConnections,MatchType);
}
}
void UMenu::JoinButtonClicked()
{
if (MultiplayerSessionsSubsystem)
{
MultiplayerSessionsSubsystem->FindSessions(10000);
}
}
void UMenu::MenuTearDown()
{
RemoveFromParent();
UWorld* World = GetWorld();
if (World)
{
APlayerController* PlayerController = World->GetFirstPlayerController();
if (PlayerController)
{
FInputModeGameOnly InputModeData;
PlayerController->SetInputMode(InputModeData);
PlayerController->SetShowMouseCursor(false);
}
}
}