본문 바로가기
언리얼엔진 개발/Network

[UnrealEngine5] 네트워크 게임 만들기 What the box(2) 세션 생성

by yeni_0224 2023. 5. 4.
728x90
반응형

Lan연결 방식으로 다른 컴퓨터와 연결해줄것이다.

네트워크는 정답이 없다고 한다. 그래서 사실 수업시간에 배웠던 내용을 바탕으로 복습하며 프로젝트를 만들어보려했지만 똑같이 적용이 안되는 이 아름다운 마직 덕분에 너무나 즐거웠다.... :)(눈물)

기본 Lan연결이 되도록 네트워크를 설정하였다. steam이 켜져있으면 다른 컴퓨터와 연결이 안될것이다

일단 steam이 꺼져있는지, 로그인되어있는지 확인해보자

 

게임 인스턴스를 만들어준다

방 정보(플레이어 이름, 수, 게임시간) 이런 것들을 구조체에 담아 서버에 보내줄것이다.

#pragma once

#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "Interfaces/OnlineSessionInterface.h"
#include "WTBoxGameInstance.generated.h"

/**
 * 
 */
USTRUCT()
struct FSessionInfo
{
	GENERATED_BODY()
	FString roomName;
	int32 currentPlayers;
	int32 maxPlayers;
	int32 gamePlayTime;
	int32 ping;
	int32 index;
};
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSearchResult, FSessionInfo, sessionInfo);

UCLASS()
class WHATTHEBOXPROJECT_API UWTBoxGameInstance : public UGameInstance
{
	GENERATED_BODY()

public:
	UWTBoxGameInstance();

	virtual void Init() override;
	FOnSearchResult searchResultDele;
	UPROPERTY(EditAnywhere)
	TSubclassOf<class USessionSlotWidget> sessionSlot;
	IOnlineSessionPtr wtbSessionInterface;
	FName sessionID;
	TSharedPtr<FOnlineSessionSearch> sessionSearch;

	FSessionInfo sessionSearchInfo;

	//세션이 나타날 최대 갯수
	UPROPERTY(EditDefaultsOnly, Category = GameSettings)
	int32 maxSearchCount = 20;

	class UEnteranceWidget* enteranceWidget;
    
public:
	void CreatewtboxSession(FString roomName, int32 playerCount, int32 matchDurations);
	void CreateMySessionServer(bool bIsSuccess);
	
	UFUNCTION()
	void OnCreateSessionComplete(FName sessionName, bool bIsSuccess);

	//세션찾기
	void FindwtbSessions();
	void OnFindSessionComplete(bool bWasSuccessful);

	void JoinwtbSessions(int32 sessionIndex);
	void OnJoinSessionComplete(FName sessionName, EOnJoinSessionCompleteResult::Type joinResult);

};

이 프로젝트를 하면서 느낀건 정말 정말 이름을 제발제발 꼭꼭 너무 너무 잘지어야한다. 네트워크 내용 자체도 어려웠지만

이름 때문에 더 많이 헷갈렸던 것 같다.

#include "WTBoxGameInstance.h"
#include "OnlineSubsystem.h"
#include "OnlineSessionSettings.h"
#include "TimerActor.h"

UWTBoxGameInstance::UWTBoxGameInstance()
{
}

void UWTBoxGameInstance::Init()
{
	Super::Init();

	IOnlineSubsystem* subsys = IOnlineSubsystem::Get();
	if(subsys)
	{
		wtbSessionInterface = subsys->GetSessionInterface();
		if(wtbSessionInterface)
		{
			wtbSessionInterface->OnCreateSessionCompleteDelegates.AddUObject(this, &UWTBoxGameInstance::OnCreateSessionComplete);
			wtbSessionInterface->OnFindSessionsCompleteDelegates.AddUObject(this, &UWTBoxGameInstance::OnFindSessionComplete);
			wtbSessionInterface->OnJoinSessionCompleteDelegates.AddUObject(this, &UWTBoxGameInstance::OnJoinSessionComplete);
		}		
	}
}

생성자에는 아무것도 적지 않았지만 일단 있으면 좋다고 했다

이번 프로젝트에서는 델리게이트를 정말 많이 사용했던 것 같다..

void UWTBoxGameInstance::CreatewtboxSession(FString roomName, int32 playerCount, int32 matchDurations)
{
	if(wtbSessionInterface != nullptr)
	{
		FOnlineSessionSettings sessionsettings;
		sessionsettings.bAllowInvites = true;
		sessionsettings.bAllowJoinInProgress = true;
		sessionsettings.bAllowJoinViaPresence = true;
		sessionsettings.bIsDedicated = false;
		sessionsettings.bIsLANMatch = IOnlineSubsystem::Get()->GetSubsystemName() == "NULL" ? true : false;
		sessionsettings.NumPublicConnections = playerCount;
		sessionsettings.bShouldAdvertise = true;
		sessionsettings.Set(FName("KEY_RoomName"), roomName, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
		sessionsettings.bShouldAdvertise = true;
		wtbSessionInterface->CreateSession(0, sessionID, sessionsettings);
	}	
}

플레이어들이 세션을 검색할 때 어떻게 검색되도록 할지 설정해주는 중이다. Dedicated Server를 사용하지 않을 것이라고 해줘야한다.

생각보다 꽤 많은걸 설정해줘야하지만, 하나하나 이해하고 알아가는 것도 좋지만 일단 외우는 것도 좋다.

void UWTBoxGameInstance::OnCreateSessionComplete(FName sessionName, bool bIsSuccess)
{
	FString result = bIsSuccess ? TEXT("Create Success wtbox Session") : TEXT("Failed Create wtboxSession");

	if(bIsSuccess)
	{
		GetWorld()->ServerTravel("/Game/KHJContents/Maps/KHJTestMap?Listen");
	}
}

일단 로그가 찍히도록 출력해주는 것이고, 세션을 찾는데 성공했다면, 리슨서버를 이용해서 이 맵에 들어가겠다는 것이다.

void UWTBoxGameInstance::OnFindSessionComplete(bool bWasSuccessful)
{
	if (bWasSuccessful)
	{
		TArray<FOnlineSessionSearchResult> searchResults = sessionSearch->SearchResults;

		for (int32 i = 0; i < searchResults.Num(); i++)
		{
			FSessionInfo searchSessionInfo;
			FString roomName;
			searchResults[i].Session.SessionSettings.Get(FName("KEY_RoomName"), roomName);
			searchSessionInfo.roomName = roomName;
			searchSessionInfo.gamePlayTime = GetWorld()->GetDeltaSeconds();
			searchSessionInfo.maxPlayers = searchResults[i].Session.SessionSettings.NumPublicConnections;
			searchSessionInfo.currentPlayers = searchSessionInfo.maxPlayers - searchResults[i].Session.NumOpenPublicConnections;
			searchSessionInfo.ping = searchResults[i].PingInMs;
			searchSessionInfo.index = i;
			searchResultDele.Broadcast(searchSessionInfo);
		}
	}
}

인덱스가 꼬일 수도 있기 때문에 인덱스 번호를 지정해주는 것이 중요하다.

void UWTBoxGameInstance::FindwtbSessions()
{
	sessionSearch = MakeShareable(new FOnlineSessionSearch());
	sessionSearch->bIsLanQuery = IOnlineSubsystem::Get()->GetSubsystemName() == "NULL";
	sessionSearch->MaxSearchResults = maxSearchCount;
	sessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);
	wtbSessionInterface->FindSessions(0, sessionSearch.ToSharedRef());
}

void UWTBoxGameInstance::JoinwtbSessions(int32 sessionIndex)
{
	FOnlineSessionSearchResult selectedSession = sessionSearch->SearchResults[sessionIndex];

	wtbSessionInterface->JoinSession(0, sessionID, selectedSession);
}

void UWTBoxGameInstance::OnJoinSessionComplete(FName sessionName, EOnJoinSessionCompleteResult::Type joinResult)
{
	FString joinAddress;
	wtbSessionInterface->GetResolvedConnectString(sessionName, joinAddress);

	if (APlayerController* pc = GetWorld()->GetFirstPlayerController())
	{
		pc->ClientTravel(joinAddress, ETravelType::TRAVEL_Absolute);
	}
}

void UWTBoxGameInstance::CreateMySessionServer(bool bIsSuccess)
{
	FString result = bIsSuccess ? TEXT("Create WTBox Game Session") : TEXT("Daaaang...");
	if(bIsSuccess)
	{
		GetWorld()->ServerTravel("/Game/KHJContents/Maps/KHJTestMap?Listen");		
	}
}

이번 네트워크 프로젝트를 통해서 가장 재미있었던것은 삼항 연산자를 사용하는 것이다. 재미붙여서 프로그래머스 문제 풀 때도 삼항연산자식을 사용해서 풀은 적도 있다. 그 때다! 삼항연산자가 내 프로그래머스 풀이에 등장한게

 

게임 서버 인스턴스 작업과정은 이름이 비슷한 함수도 많고, 새롭게 등장하는 함수들도 많아서 상당히 어려웠다. 

728x90
반응형