이전 포스팅
지난번 포스팅에서 세션의 동작 순서를 아래와 같다고 설명하였다.
Server
ClICK HOST ->(Session Settings) CREATE SESSION -> OPEN LOBBY
Client
CLICK JOIN ->(Search Settings) FIND SESSIONS -> (Pick a Valid Session) JOIN SESSION ->(Get the address) CLIENT TRAVEL
여기서 지난번 포스팅에서 구현한 부분은 Server에서의 CREATE SESSION까지였고, 이번 포스팅에서는 Open Lobby부터 Client의 마지막부분까지 다뤄보겠습니다.
멤버 함수 및 변수 갱신
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "Interfaces/OnlineSessionInterface.h"
#include "MenuSystemCharacter.generated.h"
UCLASS(config=Game)
class AMenuSystemCharacter : public ACharacter
{
GENERATED_BODY()
...
public:
// 온라인 세션 인터페이스 포인터
IOnlineSessionPtr m_OnlineSessionInterface;
protected:
UFUNCTION(BlueprintCallable)
void CreateGameSession();
UFUNCTION(BlueprintCallable)
void JoinGameSession();
// callback함수
void OnCreateSessionComplete(FName SessionName, bool bWasSuccessful);
// callback함수
void OnFindSessionsComplete(bool bWasSuccessful);
// Join이 되었는지에 관한 결과값이 Result에 저장
void OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result);
private:
FOnCreateSessionCompleteDelegate m_CreateSessionCompleteDelegate;
FOnFindSessionsCompleteDelegate m_FindSessionsCompleteDelegate;
TSharedPtr<FOnlineSessionSearch> m_SessionSearch;
FOnJoinSessionCompleteDelegate m_JoinSessionCompleteDelegate;
};
CallbackFunc
AMenuSystemCharacter::AMenuSystemCharacter() :
m_CreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnCreateSessionComplete)),
m_FindSessionsCompleteDelegate(FOnFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnFindSessionsComplete)),
m_JoinSessionCompleteDelegate(FOnJoinSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnJoinSessionComplete))
1. OPEN LOBBY
이전 포스팅에서 CreateSEssionComplete콜백함수를 m_CreateSessionCompleteDelegate에 등록해놨습니다.
해당 콜백함수는 세션을 생성했을때 동작되는 콜백함수로 세션 생성에 성공했다면 ServerTravel함수를 이용하여 Lobby Level을 리슨서버로 여는 코드를 추가해줍니다.
void AMenuSystemCharacter::OnCreateSessionComplete(FName SessionName, bool bWasSuccessful)
{
if (bWasSuccessful)
{
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(
-1,
15.f,
FColor::Blue,
FString::Printf(TEXT("Created session : %s"), *SessionName.ToString())
);
}
UWorld* World = GetWorld();
if (World)
{
World->ServerTravel(FString("/Game/ThirdPerson/Maps/Lobby?listen"));
}
}
else
{
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(
-1,
15.f,
FColor::Red,
FString(TEXT("Failed to create session!"))
);
}
}
}
2. CLICK JOIN
1. 인터페이스의 Find델리게이트리스트에 m_FIndSessionsCompleteDelegate를 저장
2. 탐색할 세션의 정보를 설정
3. 탐색할 세션의 정보를 토대로 세션을 찾고 세션을 찾으면 콜백함수 호출
void AMenuSystemCharacter::JoinGameSession()
{
// 게임 세션을 찾는다
// 인터페이스의 데이터가 유효하지 않다면 리턴
if (!m_OnlineSessionInterface.IsValid())
{
return;
}
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(
-1,
15.f,
FColor::Blue,
FString(TEXT("JoinGameSession() Success"))
);
}
// 델리게이트리스트에 델리게이트 저장
m_OnlineSessionInterface->AddOnFindSessionsCompleteDelegate_Handle(m_FindSessionsCompleteDelegate);
m_SessionSearch = MakeShareable(new FOnlineSessionSearch());
// 세션을 찾을 개수?
m_SessionSearch->MaxSearchResults = 10000;
// LAN을 사용하지 않기떄문에 false
m_SessionSearch->bIsLanQuery = false;
// 매칭 서버를 찾기 위한 쿼리
// Find 세션을 호출하고 세션 검색을 전달하면 쿼리 세팅을 설정해서 우리가 찾는 세션을 사용하도록 함?
m_SessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);
// 로컬 플레이어를 얻어와 넷ID를 얻을 수 있다.
const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
// 세션을 호출하고 세션이 완료되면 응답으로 콜백함수를 호출 요청
m_OnlineSessionInterface->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(), m_SessionSearch.ToSharedRef());
}
3. FIND SESSIONS
FindSessions를 하게되면 해당 세션에 대한 결과(정보)가 m_SessionSearch->SearchResults에 저장이된다.세션을 성공적으로 찾았다면 Join하기위해 JoinDelegateList에 m_JoinSessionCompleteDelegate 저장 이후 Join 진행JoinSession이 완료되면 Callback함수 호출
void AMenuSystemCharacter::OnFindSessionsComplete(bool bWasSuccessful)
{
// 인터페이스가 유효한지
if (!m_OnlineSessionInterface.IsValid())
return;
for (auto Result : m_SessionSearch->SearchResults)
{
// 세션 ID 문자열을 해당 함수로 얻을 수 있다.
FString Id = Result.GetSessionIdStr();
FString User = Result.Session.OwningUserName;
FString MatchType;
// 위에서 저장한 MatchType의 키값으로 저장된 Value값을 MatchType이란 FString변수에 저장
Result.Session.SessionSettings.Get(FName("MatchType"), MatchType);
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(
-1,
15.f,
FColor::Cyan,
FString::Printf(TEXT("Id : %s, User : %s"), *Id, *User)
);
}
// IP주소를 얻어내려면 세션에 참여해야한다
// 세션이 맞을경우 아래의 if문에 들어감
if (MatchType == FString("FreeForAll"))
{
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(
-1,
15.f,
FColor::Cyan,
FString::Printf(TEXT("Joining Match Type : %s"), *MatchType)
);
}
m_OnlineSessionInterface->AddOnJoinSessionCompleteDelegate_Handle(m_JoinSessionCompleteDelegate);
// JoinSession 호출
const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
// 세션을 호출하고 세션이 완료되면 응답으로 콜백함수를 호출 요청
m_OnlineSessionInterface->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, Result);
}
}
}
4. JOIN SESSION / CLIENT TRAVEL
세션의 IP를 얻어와 서버에 입장하는 구간
1. InterFace의 GetResolvedConnectString 함수를 이용하여 세션의 IP주소를 얻어온다.
2. 플레이어 컨트롤러를 얻어와 ClientTravel를 이용해 서버에 입장.
void AMenuSystemCharacter::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
{
if (!m_OnlineSessionInterface.IsValid())
return;
// 세션의 IP주소를 얻어온다.
// 세션에 등록된 IP주소를 얻어오기 때문에 IP주소를 직접 알아내서 적을 필요가없다.
FString Address;
if (m_OnlineSessionInterface->GetResolvedConnectString(NAME_GameSession, Address))
{
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(
-1,
15.f,
FColor::Yellow,
FString::Printf(TEXT("Connect string : %s"), *Address)
);
}
APlayerController* PlayerController = GetGameInstance()->GetFirstLocalPlayerController();
if (PlayerController)
{
PlayerController->ClientTravel(Address, ETravelType::TRAVEL_Absolute);
}
}
}
결과
'언리얼5' 카테고리의 다른 글
[UE5 Multiplayer Shooting-6] UE5 IK_Rig_Retargeting | IK 릭 리타겟팅 (2) | 2023.07.30 |
---|---|
[UE5 Multiplayer Shooting-5] UE 멀티 플레이어 플러그인 생성 03 (8) | 2023.07.29 |
[UE5 Multiplayer Shooting-3] UE 멀티 플레이어 플러그인 생성 01 (0) | 2023.07.25 |
[UE5 Multiplayer Shooting-2] UE LAN을 활용한 멀티플레이 (0) | 2023.07.25 |
[UE5 Multiplayer Shooting-1] UE 멀티플레이 서버 모델에 대해서 (0) | 2023.07.25 |
댓글