[UE] Multiplayer 10: Lobby 레벨 기본설정 및 변경하기
목차
Multiplayer 10: Lobby 레벨 기본설정 및 변경하기
Menu
Menu.h
더보기
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Interfaces/OnlineSessionInterface.h"//EOnJoinSessionCompleteResult 사용을 위한 헤더
#include "Menu.generated.h"
UCLASS()
class MULTIPLAYERSESSIONS_API UMenu : public UUserWidget
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
void MenuSetup(int32 NumberOfPublicConnections = 4, FString TypeOfMatch = FString(TEXT("FreeForAll")), FString LobbyPath = FString(TEXT("/Game/ThirdPerson/Maps/Lobby")));//접속할 수 있는 Player 숫자를 input으로 만들고 4를 기본값으로 설정한다. Lobby 레벨을 기본으로 설정한다.
protected:
virtual bool Initialize() override;
virtual void OnLevelRemovedFromWorld(ULevel* InLevel, UWorld* InWorld) override;//다른 Level로 이동하면 기존의 Level을 지우는 함수.
//
// Callbacks for the custom delegates on the MultiplayerSessionsSubsystem
// MultiplayerSessionsSubsystem.h의 Dynamic Delegate과 연결된다. Dynamic과 연결되는 경우 UFUNCTION()을 꼭 붙여야 한다. 붙이지 않으면 dynamic delegate과 연결되지 않는다.
UFUNCTION()
void OnCreateSession(bool bWasSuccessful);
void OnFindSessions(const TArray<FOnlineSessionSearchResult>& SessionResults, bool bWasSuccessful);
void OnJoinSession(EOnJoinSessionCompleteResult::Type Result);
UFUNCTION()
void OnDestroySession(bool bWasSuccessful);
UFUNCTION()
void OnStartSession(bool bWasSuccessful);
private:
//meta = (BindWidget)을 사용하면 BP의 Button Widget이 아래의 변수와 연결된다. 이 때 BP와 C++변수 이름은 일치하여야 한다.
UPROPERTY(meta = (BindWidget))
class UButton* HostButton;
UPROPERTY(meta = (BindWidget))
UButton* JoinButton;
UFUNCTION()
void HostButtonClicked();
UFUNCTION()
void JoinButtonClicked();
void MenuTearDown();
// The subsystem designed to handle all online session functionality
class UMultiplayerSessionsSubsystem* MultiplayerSessionsSubsystem;
int32 NumPublicConnections{ 4 };
FString MatchType{ TEXT("FreeForAll") };
FString PathToLobby{ TEXT("") };
};
void MenuSetup 함수에 매개변수 추가
- void MenuSetup(int32 NumberOfPublicConnections = 4, FString TypeOfMatch = FString(TEXT("FreeForAll")), FString LobbyPath = FString(TEXT("/Game/ThirdPerson/Maps/Lobby")));
- 접속할 수 있는 Player 숫자를 input으로 만들고 4를 기본값으로 설정한다. 입장하는 레벨 맵을 Lobby로 기본으로 설정한다.
Menu.cpp
더보기
#include "Menu.h"
#include "Components/Button.h"
#include "MultiplayerSessionsSubsystem.h"
#include "OnlineSessionSettings.h"
#include "OnlineSubsystem.h"
void UMenu::MenuSetup(int32 NumberOfPublicConnections, FString TypeOfMatch, FString LobbyPath)
{
PathToLobby = FString::Printf(TEXT("%s?listen"), *LobbyPath);
NumPublicConnections = 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 변수에 Subsystem을 리턴 값을 넣어준다.
MultiplayerSessionsSubsystem = GameInstance->GetSubsystem<UMultiplayerSessionsSubsystem>();
}
if (MultiplayerSessionsSubsystem)
{
//callback을 Bind해준다.
MultiplayerSessionsSubsystem->MultiplayerOnCreateSessionComplete.AddDynamic(this, &ThisClass::OnCreateSession);//Dynamic을 Bind하는 경우는 AddDynamic 사용.
MultiplayerSessionsSubsystem->MultiplayerOnFindSessionsComplete.AddUObject(this, &ThisClass::OnFindSessions);//Dynamic이 아닌 것을 Bind하는 경우는 AddUObject 사용.
MultiplayerSessionsSubsystem->MultiplayerOnJoinSessionComplete.AddUObject(this, &ThisClass::OnJoinSession);
MultiplayerSessionsSubsystem->MultiplayerOnDestroySessionComplete.AddDynamic(this, &ThisClass::OnDestroySession);
MultiplayerSessionsSubsystem->MultiplayerOnStartSessionComplete.AddDynamic(this, &ThisClass::OnStartSession);
}
}
bool UMenu::Initialize()
{
//Super버젼이 false면 false를 리턴한다.(=상위 클래스에서 Initialize 하는게 없으면 false를 리턴하여 Initialize()를 하지 않는다.)
if (!Super::Initialize())
{
return false;
}
if (HostButton)
{
//HostButton 클릭할 때 발생하는 이벤트를 Delegate로 연결해준다.
HostButton->OnClicked.AddDynamic(this, &ThisClass::HostButtonClicked);
}
if (JoinButton)
{
//JoinButton 클릭할 때 발생하는 이벤트를 Delegate로 연결해준다.
JoinButton->OnClicked.AddDynamic(this, &ThisClass::JoinButtonClicked);
}
return true;
}
void UMenu::OnLevelRemovedFromWorld(ULevel* InLevel, UWorld* InWorld)
{
MenuTearDown();//Widget을 뷰포트에서 지우고 input mode가 리셋된다.
Super::OnLevelRemovedFromWorld(InLevel, InWorld);
}
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");
World->ServerTravel(PathToLobby);
}
}
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;
}
for (auto Result : SessionResults)//변수로 받은 SessionResults배열을 순회하며 검색
{
FString SettingsValue;
Result.Session.SessionSettings.Get(FName("MatchType"), SettingsValue);
//SessionSettings의 결과값이 "MatchType"과 SetingsValue을 가지고 있는지 확인.
if (SettingsValue == MatchType)
{
MultiplayerSessionsSubsystem->JoinSession(Result);
return;
}
}
}
void UMenu::OnJoinSession(EOnJoinSessionCompleteResult::Type Result)
{
//IOnlineSubsystem 사용을 위해 위에 #include "OnlineSubsystem.h" 추가
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 (GEngine)
{
GEngine->AddOnScreenDebugMessage(
-1,
15.f,
FColor::Yellow,
FString(TEXT("Host Button Clicked"))
);
}
if (MultiplayerSessionsSubsystem)
{
MultiplayerSessionsSubsystem->CreateSession(NumPublicConnections, MatchType);//NumPublicConnections 숫자 크기까지 Players 접속 가능
UWorld* World = GetWorld();
}
}
void UMenu::JoinButtonClicked()
{
//디버깅 테스트
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(
-1,
15.f,
FColor::Yellow,
FString(TEXT("Join Button Clicked"))
);
}
if (MultiplayerSessionsSubsystem)
{
//Steam DevID의 숫자가 클수도 있으니 MaxSearchResults값을 10000으로 넉넉히 잡는다.
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);
}
}
}
void UMenu::MenuSetup(int32 NumberOfPublicConnections, FString TypeOfMatch, FString LobbyPath)
- PathToLobby = FString::Printf(TEXT("%s?listen"), *LobbyPath);
- if (World)
{
World->ServerTravel(PathToLobby);
}
ThirdPersonMap의 Level Blueprint 확인
cpp에서 작업한 Menu Setup이 업데이트되서 들어온다.
Package Project
다른 컴퓨터에서 .exe 파일 열기
'⭐ Unreal Engine > UE Multiplayer FPS TPS + ListenServer' 카테고리의 다른 글
[UE5] 플레이어 Role 머리 위에 띄우기 (0) | 2023.09.18 |
---|---|
[UE] Multiplayer 11: Menu Subsystem 수정하기 (0) | 2023.07.17 |
[UE] Multiplayer 9: 접속하는 플레이어 확인하기 (0) | 2023.07.17 |
[UE] Multiplayer 8: Menu에서 Session 참가(Join)하기 (0) | 2023.07.17 |
[UE] Multiplayer 7-2: Subsystem Delegate 연결하기 (0) | 2023.07.17 |
댓글
이 글 공유하기
다른 글
-
[UE5] 플레이어 Role 머리 위에 띄우기
[UE5] 플레이어 Role 머리 위에 띄우기
2023.09.18 -
[UE] Multiplayer 11: Menu Subsystem 수정하기
[UE] Multiplayer 11: Menu Subsystem 수정하기
2023.07.17 -
[UE] Multiplayer 9: 접속하는 플레이어 확인하기
[UE] Multiplayer 9: 접속하는 플레이어 확인하기
2023.07.17 -
[UE] Multiplayer 8: Menu에서 Session 참가(Join)하기
[UE] Multiplayer 8: Menu에서 Session 참가(Join)하기
2023.07.17