목차

     

     


     

     

    Session 생성하기

     


     

     

    MultiplayerCharacter

     

    MultiplayerCharacter.h

    더보기

     

    #pragma once
    #include "CoreMinimal.h"
    #include "GameFramework/Character.h"
    #include "Interfaces/OnlineSessionInterface.h"
    #include "MultiplayerCharacter.generated.h"
    
    UCLASS(config=Game)
    class AMultiplayerCharacter : public ACharacter
    {
    	GENERATED_BODY()
    
    	/** Camera boom positioning the camera behind the character */
    	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
    	class USpringArmComponent* CameraBoom;
    
    	/** Follow camera */
    	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
    	class UCameraComponent* FollowCamera;
    public:
    	AMultiplayerCharacter();
    
    	/** Base turn rate, in deg/sec. Other scaling may affect final turn rate. */
    	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Input)
    	float TurnRateGamepad;
    
    protected:
    
    	/** Called for forwards/backward input */
    	void MoveForward(float Value);
    
    	/** Called for side to side input */
    	void MoveRight(float Value);
    
    	/** 
    	 * Called via input to turn at a given rate. 
    	 * @param Rate	This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
    	 */
    	void TurnAtRate(float Rate);
    
    	/**
    	 * Called via input to turn look up/down at a given rate. 
    	 * @param Rate	This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
    	 */
    	void LookUpAtRate(float Rate);
    
    	/** Handler for when a touch input begins. */
    	void TouchStarted(ETouchIndex::Type FingerIndex, FVector Location);
    
    	/** Handler for when a touch input stops. */
    	void TouchStopped(ETouchIndex::Type FingerIndex, FVector Location);
    
    protected:
    	// APawn interface
    	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
    	// End of APawn interface
    
    public:
    	/** Returns CameraBoom subobject **/
    	FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }
    	/** Returns FollowCamera subobject **/
    	FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }
    
    public:
    	//Pointer to the online session interface
    	IOnlineSessionPtr OnlineSessionInterface;
    
    protected:
    	UFUNCTION(BlueprintCallable)
    	void CreateGameSession();
    
    	void OnCreateSessionComplete(FName SessionName, bool bWasSuccessful);
    
    private:
    
    	FOnCreateSessionCompleteDelegate CreateSessionCompleteDelegate;
    };

    헤더 추가

    • #include "Interfaces/OnlineSessionInterface.h"

     

    변수 추가

    • IOnlineSessionPtr OnlineSessionInterface;
      • online session interface를 가리키는 포인터 변수
    • FOnCreateSessionCompleteDelegate CreateSessionCompleteDelegate;

     

    함수 추가

    • UFUNCTION(BlueprintCallable)
      void CreateGameSession();
    • void OnCreateSessionComplete(FName SessionName, bool bWasSuccessful);

     

     

     

    MultiplayerCharacter.cpp

    더보기
    #include "MultiplayerCharacter.h"
    #include "Camera/CameraComponent.h"
    #include "Components/CapsuleComponent.h"
    #include "Components/InputComponent.h"
    #include "GameFramework/CharacterMovementComponent.h"
    #include "GameFramework/Controller.h"
    #include "GameFramework/SpringArmComponent.h"
    #include "OnlineSubsystem.h"
    #include "OnlineSessionSettings.h"
    
    //////////////////////////////////////////////////////////////////////////
    // AMultiplayerCharacter
    
    AMultiplayerCharacter::AMultiplayerCharacter()
    	: CreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnCreateSessionComplete))
    {
    	// Set size for collision capsule
    	GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);
    
    	// set our turn rate for input
    	TurnRateGamepad = 50.f;
    
    	// Don't rotate when the controller rotates. Let that just affect the camera.
    	bUseControllerRotationPitch = false;
    	bUseControllerRotationYaw = false;
    	bUseControllerRotationRoll = false;
    
    	// Configure character movement
    	GetCharacterMovement()->bOrientRotationToMovement = true; // Character moves in the direction of input...	
    	GetCharacterMovement()->RotationRate = FRotator(0.0f, 500.0f, 0.0f); // ...at this rotation rate
    
    	// Note: For faster iteration times these variables, and many more, can be tweaked in the Character Blueprint
    	// instead of recompiling to adjust them
    	GetCharacterMovement()->JumpZVelocity = 700.f;
    	GetCharacterMovement()->AirControl = 0.35f;
    	GetCharacterMovement()->MaxWalkSpeed = 500.f;
    	GetCharacterMovement()->MinAnalogWalkSpeed = 20.f;
    	GetCharacterMovement()->BrakingDecelerationWalking = 2000.f;
    
    	// Create a camera boom (pulls in towards the player if there is a collision)
    	CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
    	CameraBoom->SetupAttachment(RootComponent);
    	CameraBoom->TargetArmLength = 400.0f; // The camera follows at this distance behind the character	
    	CameraBoom->bUsePawnControlRotation = true; // Rotate the arm based on the controller
    
    	// Create a follow camera
    	FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
    	FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation
    	FollowCamera->bUsePawnControlRotation = false; // Camera does not rotate relative to arm
    
    	// Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character) 
    	// are set in the derived blueprint asset named ThirdPersonCharacter (to avoid direct content references in C++)
    
    	IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get();
    	if (OnlineSubsystem)
    	{
    		OnlineSessionInterface = OnlineSubsystem->GetSessionInterface();
    
    		if (GEngine)
    		{
    			GEngine->AddOnScreenDebugMessage(
    				-1,
    				15.0f,
    				FColor::Blue,
    				FString::Printf(TEXT("I found SubSystem %s"), *OnlineSubsystem->GetSubsystemName().ToString())
    			);
    		}
    	}
    }
    
    //////////////////////////////////////////////////////////////////////////
    // Input
    
    void AMultiplayerCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
    {
    	// Set up gameplay key bindings
    	check(PlayerInputComponent);
    	PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
    	PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);
    
    	PlayerInputComponent->BindAxis("Move Forward / Backward", this, &AMultiplayerCharacter::MoveForward);
    	PlayerInputComponent->BindAxis("Move Right / Left", this, &AMultiplayerCharacter::MoveRight);
    
    	// We have 2 versions of the rotation bindings to handle different kinds of devices differently
    	// "turn" handles devices that provide an absolute delta, such as a mouse.
    	// "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
    	PlayerInputComponent->BindAxis("Turn Right / Left Mouse", this, &APawn::AddControllerYawInput);
    	PlayerInputComponent->BindAxis("Turn Right / Left Gamepad", this, &AMultiplayerCharacter::TurnAtRate);
    	PlayerInputComponent->BindAxis("Look Up / Down Mouse", this, &APawn::AddControllerPitchInput);
    	PlayerInputComponent->BindAxis("Look Up / Down Gamepad", this, &AMultiplayerCharacter::LookUpAtRate);
    
    	// handle touch devices
    	PlayerInputComponent->BindTouch(IE_Pressed, this, &AMultiplayerCharacter::TouchStarted);
    	PlayerInputComponent->BindTouch(IE_Released, this, &AMultiplayerCharacter::TouchStopped);
    }
    
    void AMultiplayerCharacter::CreateGameSession()
    {
    	// 1번 키를 눌렀을 때 콜 된다. BP_ThirdPersonCharacter에서 1번 키를 누르면 콜 되게 해줬다.
    
    	if (false == OnlineSessionInterface.IsValid())
    	{	//OnlineSessionInterface가 유효하지 않다면 리턴.
    		return;
    	}
    
    	auto ExistingSession = OnlineSessionInterface->GetNamedSession(NAME_GameSession);
    	if (ExistingSession != nullptr)
    	{
    		OnlineSessionInterface->DestroySession(NAME_GameSession);//Session을 끝낸다.
    	}
    
    	//Delegate 연결
    	OnlineSessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate);
    
    	TSharedPtr<FOnlineSessionSettings> SessionSettings = MakeShareable(new FOnlineSessionSettings());
    	SessionSettings->bIsLANMatch = false;//Internet으로 연결할 것이므로 LANMatch를 사용하지 않는다.
    	SessionSettings->NumPublicConnections = 4;//4명의 Players까지 접속이 가능하게 설정.
    	SessionSettings->bAllowJoinInProgress = true;//Session이 실행중일 때 Player들이 원할 때 들어올 수 있음
    	SessionSettings->bAllowJoinViaPresence = true;//Steam 기준에서 같은 region에 있는 Player들만 들어올 수 있게 설정.
    	SessionSettings->bShouldAdvertise = true;//Steam에서 Advertise가 가능하여 사람들이 찾아 들어올 수 있게 한다.
    	SessionSettings->bUsesPresence = true;//같은 region에서 session을 찾을 수 있게 해준다.
    	
    	OnlineSessionInterface->CreateSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, *SessionSettings);//위의 SessionSettings를 만족하는 Session을 생성한다.
    }
    
    void AMultiplayerCharacter::OnCreateSessionComplete(FName SessionName, bool bWasSuccessful)
    {
    	//Session 생성이 성공한 경우
    	if (bWasSuccessful)
    	{
    		if (GEngine)
    		{
    			GEngine->AddOnScreenDebugMessage(
    				-1,
    				15.0f,
    				FColor::Blue,
    				FString::Printf(TEXT("Created session: %s"), *SessionName.ToString())
    			);
    		}
    		//Lobby라는 Level 맵을 띄운다.
    		UWorld* World = GetWorld();
    		if (World)
    		{
    			World->ServerTravel(FString("/Game/ThirdPerson/Maps/Lobby?listen"));
    		}
    	}
    	//Session 생성이 실패한 경우
    	else
    	{
    		if (GEngine)
    		{
    			GEngine->AddOnScreenDebugMessage(
    				-1,
    				15.f,
    				FColor::Red,
    				FString(TEXT("Failed to create session!"))
    			);
    		}
    	}
    }
    
    void AMultiplayerCharacter::TouchStarted(ETouchIndex::Type FingerIndex, FVector Location)
    {
    	Jump();
    }
    
    void AMultiplayerCharacter::TouchStopped(ETouchIndex::Type FingerIndex, FVector Location)
    {
    	StopJumping();
    }
    
    void AMultiplayerCharacter::TurnAtRate(float Rate)
    {
    	// calculate delta for this frame from the rate information
    	AddControllerYawInput(Rate * TurnRateGamepad * GetWorld()->GetDeltaSeconds());
    }
    
    void AMultiplayerCharacter::LookUpAtRate(float Rate)
    {
    	// calculate delta for this frame from the rate information
    	AddControllerPitchInput(Rate * TurnRateGamepad * GetWorld()->GetDeltaSeconds());
    }
    
    void AMultiplayerCharacter::MoveForward(float Value)
    {
    	if ((Controller != nullptr) && (Value != 0.0f))
    	{
    		// find out which way is forward
    		const FRotator Rotation = Controller->GetControlRotation();
    		const FRotator YawRotation(0, Rotation.Yaw, 0);
    
    		// get forward vector
    		const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
    		AddMovementInput(Direction, Value);
    	}
    }
    
    void AMultiplayerCharacter::MoveRight(float Value)
    {
    	if ( (Controller != nullptr) && (Value != 0.0f) )
    	{
    		// find out which way is right
    		const FRotator Rotation = Controller->GetControlRotation();
    		const FRotator YawRotation(0, Rotation.Yaw, 0);
    	
    		// get right vector 
    		const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
    		// add movement in that direction
    		AddMovementInput(Direction, Value);
    	}
    }

    헤더 추가

    • #include "OnlineSessionSettings.h"

     

    AMultiplayerCharacter::AMultiplayerCharacter()

    • Delegate 연결
      • : CreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnCreateSessionComplete))

     

    함수 정의

    • void AMultiplayerCharacter::CreateGameSession()
    • void AMultiplayerCharacter::OnCreateSessionComplete(FName SessionName, bool bWasSuccessful)

     


     

     

    BP_ThirdPersonCharacter

     

     


     

     

    Package Project

     

     

     


     

     

    .exe 실행화면

     

    실행하면 좌측 상단에

    I found SubSystem Steam

    이라는 Debug Message가 출력된다.

     

    1번을 누르면

    Created session: GameSession

    이 출력된다.

     


     

     

     

     

    Session이 검색되게 만들어주기

     

     


     

    MultiplayerCharacter

     

    MultiplayerCharacter.h

    더보기
    #pragma once
    
    #include "CoreMinimal.h"
    #include "GameFramework/Character.h"
    #include "Interfaces/OnlineSessionInterface.h"
    #include "MultiplayerCharacter.generated.h"
    
    UCLASS(config=Game)
    class AMultiplayerCharacter : public ACharacter
    {
    	GENERATED_BODY()
    
    	/** Camera boom positioning the camera behind the character */
    	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
    	class USpringArmComponent* CameraBoom;
    
    	/** Follow camera */
    	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
    	class UCameraComponent* FollowCamera;
    public:
    	AMultiplayerCharacter();
    
    	/** Base turn rate, in deg/sec. Other scaling may affect final turn rate. */
    	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Input)
    	float TurnRateGamepad;
    
    protected:
    
    	/** Called for forwards/backward input */
    	void MoveForward(float Value);
    
    	/** Called for side to side input */
    	void MoveRight(float Value);
    
    	/** 
    	 * Called via input to turn at a given rate. 
    	 * @param Rate	This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
    	 */
    	void TurnAtRate(float Rate);
    
    	/**
    	 * Called via input to turn look up/down at a given rate. 
    	 * @param Rate	This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
    	 */
    	void LookUpAtRate(float Rate);
    
    	/** Handler for when a touch input begins. */
    	void TouchStarted(ETouchIndex::Type FingerIndex, FVector Location);
    
    	/** Handler for when a touch input stops. */
    	void TouchStopped(ETouchIndex::Type FingerIndex, FVector Location);
    
    protected:
    	// APawn interface
    	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
    	// End of APawn interface
    
    public:
    	/** Returns CameraBoom subobject **/
    	FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }
    	/** Returns FollowCamera subobject **/
    	FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }
    
    public:
    	//Pointer to the online session interface. online session interface를 가리키는 포인터 변수
    	IOnlineSessionPtr OnlineSessionInterface;
    
    protected:
    	UFUNCTION(BlueprintCallable)
    	void CreateGameSession();
    
    	UFUNCTION(BlueprintCallable)
    	void JoinGameSession();
    
    	void OnCreateSessionComplete(FName SessionName, bool bWasSuccessful);
    	void OnFindSessionsComplete(bool bWasSuccessful);
    
    private:
    	//Delegate 변수들
    	FOnCreateSessionCompleteDelegate CreateSessionCompleteDelegate;
    	FOnFindSessionsCompleteDelegate FindSessionsCompleteDelegate;
    	TSharedPtr<FOnlineSessionSearch> SessionSearch;
    	FOnJoinSessionCompleteDelegate JoinSessionCompleteDelegate;
    };

    함수 추가

    • UFUNCTION(BlueprintCallable)
      void JoinGameSession();
    • void OnFindSessionsComplete(bool bWasSuccessful);

     

    Delegate 변수 추가

    • FOnFindSessionsCompleteDelegate FindSessionsCompleteDelegate;    
    • TSharedPtr<FOnlineSessionSearch> SessionSearch;
    • FOnJoinSessionCompleteDelegate JoinSessionCompleteDelegate;

     

     

     

    MultiplayerCharacter.cpp

    더보기
    #include "MultiplayerCharacter.h"
    #include "Camera/CameraComponent.h"
    #include "Components/CapsuleComponent.h"
    #include "Components/InputComponent.h"
    #include "GameFramework/CharacterMovementComponent.h"
    #include "GameFramework/Controller.h"
    #include "GameFramework/SpringArmComponent.h"
    #include "OnlineSubsystem.h"
    #include "OnlineSessionSettings.h"
    
    //////////////////////////////////////////////////////////////////////////
    // AMultiplayerCharacter
    
    AMultiplayerCharacter::AMultiplayerCharacter() :
    	CreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnCreateSessionComplete)),
    	FindSessionsCompleteDelegate(FOnFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnFindSessionsComplete))
    {
    	// Set size for collision capsule
    	GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);
    
    	// set our turn rate for input
    	TurnRateGamepad = 50.f;
    
    	// Don't rotate when the controller rotates. Let that just affect the camera.
    	bUseControllerRotationPitch = false;
    	bUseControllerRotationYaw = false;
    	bUseControllerRotationRoll = false;
    
    	// Configure character movement
    	GetCharacterMovement()->bOrientRotationToMovement = true; // Character moves in the direction of input...	
    	GetCharacterMovement()->RotationRate = FRotator(0.0f, 500.0f, 0.0f); // ...at this rotation rate
    
    	// Note: For faster iteration times these variables, and many more, can be tweaked in the Character Blueprint
    	// instead of recompiling to adjust them
    	GetCharacterMovement()->JumpZVelocity = 700.f;
    	GetCharacterMovement()->AirControl = 0.35f;
    	GetCharacterMovement()->MaxWalkSpeed = 500.f;
    	GetCharacterMovement()->MinAnalogWalkSpeed = 20.f;
    	GetCharacterMovement()->BrakingDecelerationWalking = 2000.f;
    
    	// Create a camera boom (pulls in towards the player if there is a collision)
    	CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
    	CameraBoom->SetupAttachment(RootComponent);
    	CameraBoom->TargetArmLength = 400.0f; // The camera follows at this distance behind the character	
    	CameraBoom->bUsePawnControlRotation = true; // Rotate the arm based on the controller
    
    	// Create a follow camera
    	FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
    	FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation
    	FollowCamera->bUsePawnControlRotation = false; // Camera does not rotate relative to arm
    
    	// Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character) 
    	// are set in the derived blueprint asset named ThirdPersonCharacter (to avoid direct content references in C++)
    
    	IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get();
    	if (OnlineSubsystem)
    	{
    		OnlineSessionInterface = OnlineSubsystem->GetSessionInterface();
    
    		if (GEngine)
    		{
    			GEngine->AddOnScreenDebugMessage(
    				-1,
    				15.0f,
    				FColor::Blue,
    				FString::Printf(TEXT("I found SubSystem %s"), *OnlineSubsystem->GetSubsystemName().ToString())
    			);
    		}
    	}
    }
    
    //////////////////////////////////////////////////////////////////////////
    // Input
    
    void AMultiplayerCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
    {
    	// Set up gameplay key bindings
    	check(PlayerInputComponent);
    	PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
    	PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);
    
    	PlayerInputComponent->BindAxis("Move Forward / Backward", this, &AMultiplayerCharacter::MoveForward);
    	PlayerInputComponent->BindAxis("Move Right / Left", this, &AMultiplayerCharacter::MoveRight);
    
    	// We have 2 versions of the rotation bindings to handle different kinds of devices differently
    	// "turn" handles devices that provide an absolute delta, such as a mouse.
    	// "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
    	PlayerInputComponent->BindAxis("Turn Right / Left Mouse", this, &APawn::AddControllerYawInput);
    	PlayerInputComponent->BindAxis("Turn Right / Left Gamepad", this, &AMultiplayerCharacter::TurnAtRate);
    	PlayerInputComponent->BindAxis("Look Up / Down Mouse", this, &APawn::AddControllerPitchInput);
    	PlayerInputComponent->BindAxis("Look Up / Down Gamepad", this, &AMultiplayerCharacter::LookUpAtRate);
    
    	// handle touch devices
    	PlayerInputComponent->BindTouch(IE_Pressed, this, &AMultiplayerCharacter::TouchStarted);
    	PlayerInputComponent->BindTouch(IE_Released, this, &AMultiplayerCharacter::TouchStopped);
    }
    
    void AMultiplayerCharacter::CreateGameSession()
    {
    	// 1번 키를 눌렀을 때 콜 된다. BP_ThirdPersonCharacter에서 1번 키를 누르면 콜 되게 해줬다.
    
    	if (false == OnlineSessionInterface.IsValid())
    	{	//OnlineSessionInterface가 유효하지 않다면 리턴.
    		return;
    	}
    
    	auto ExistingSession = OnlineSessionInterface->GetNamedSession(NAME_GameSession);
    	if (ExistingSession != nullptr)
    	{
    		OnlineSessionInterface->DestroySession(NAME_GameSession);//Session을 끝낸다.
    	}
    
    	//Delegate 연결
    	OnlineSessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate);
    
    	TSharedPtr<FOnlineSessionSettings> SessionSettings = MakeShareable(new FOnlineSessionSettings());
    	SessionSettings->bIsLANMatch = false;//Internet으로 연결할 것이므로 LANMatch를 사용하지 않는다.
    	SessionSettings->NumPublicConnections = 4;//4명의 Players까지 접속이 가능하게 설정.
    	SessionSettings->bAllowJoinInProgress = true;//Session이 실행중일 때 Player들이 원할 때 들어올 수 있음
    	SessionSettings->bAllowJoinViaPresence = true;//Steam 기준에서 같은 region에 있는 Player들만 들어올 수 있게 설정.
    	SessionSettings->bShouldAdvertise = true;//Steam에서 Advertise가 가능하여 사람들이 찾아 들어올 수 있게 한다.
    	SessionSettings->bUsesPresence = true;//같은 region에서 session을 찾을 수 있게 해준다.
    	
    	SessionSettings->bUseLobbiesIfAvailable = true;//Session을 찾기 힘들때 사용하는 세팅.
    	const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
    	OnlineSessionInterface->CreateSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, *SessionSettings);//위의 SessionSettings를 만족하는 Session을 생성한다.
    }
    
    void AMultiplayerCharacter::JoinGameSession()
    {
    	//Game Sessions 찾기
    	if (false == OnlineSessionInterface.IsValid())
    	{
    		return;
    	}
    
    	//OnlineSessionInterface에 FindSessionsCompleteDelegate을 연결시킨다.
    	OnlineSessionInterface->AddOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegate);
    
    	SessionSearch = MakeShareable(new FOnlineSessionSearch());
    	SessionSearch->MaxSearchResults = 10000;//DevID 찾기 최대 개수.
    	SessionSearch->bIsLanQuery = false;//LAN을 사용하지 않으므로 false 설정.
    	SessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);//The query to use for finding matching servers. set조건에 만족하는 서버들을 찾는다.
    
    	const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
    	OnlineSessionInterface->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(), SessionSearch.ToSharedRef());
    }
    
    void AMultiplayerCharacter::OnCreateSessionComplete(FName SessionName, bool bWasSuccessful)
    {
    	//Session 생성이 성공한 경우
    	if (bWasSuccessful)
    	{
    		if (GEngine)
    		{
    			GEngine->AddOnScreenDebugMessage(
    				-1,
    				15.0f,
    				FColor::Blue,
    				FString::Printf(TEXT("Created session: %s"), *SessionName.ToString())
    			);
    		}
    		//Lobby라는 Level 맵을 띄운다.
    		UWorld* World = GetWorld();
    		if (World)
    		{
    			World->ServerTravel(FString("/Game/ThirdPerson/Maps/Lobby?listen"));
    		}
    	}
    	//Session 생성이 실패한 경우
    	else
    	{
    		if (GEngine)
    		{
    			GEngine->AddOnScreenDebugMessage(
    				-1,
    				15.f,
    				FColor::Red,
    				FString(TEXT("Failed to create session!"))
    			);
    		}
    	}
    }
    
    void AMultiplayerCharacter::OnFindSessionsComplete(bool bWasSuccessful)
    {
    	if (false == OnlineSessionInterface.IsValid())
    	{
    		return;
    	}
    
    	//SearchResults를 for문으로 순회
    	for (auto Result : SessionSearch->SearchResults)
    	{
    		FString Id = Result.GetSessionIdStr();
    		FString User = Result.Session.OwningUserName;
            
    		if (GEngine)
    		{
    			GEngine->AddOnScreenDebugMessage(
    				-1,
    				15.f,
    				FColor::Cyan,
    				FString::Printf(TEXT("Id: %s, User: %s"), *Id, *User)
    			);
    		}
    	}
    }
    
    void AMultiplayerCharacter::TouchStarted(ETouchIndex::Type FingerIndex, FVector Location)
    {
    	Jump();
    }
    
    void AMultiplayerCharacter::TouchStopped(ETouchIndex::Type FingerIndex, FVector Location)
    {
    	StopJumping();
    }
    
    void AMultiplayerCharacter::TurnAtRate(float Rate)
    {
    	// calculate delta for this frame from the rate information
    	AddControllerYawInput(Rate * TurnRateGamepad * GetWorld()->GetDeltaSeconds());
    }
    
    void AMultiplayerCharacter::LookUpAtRate(float Rate)
    {
    	// calculate delta for this frame from the rate information
    	AddControllerPitchInput(Rate * TurnRateGamepad * GetWorld()->GetDeltaSeconds());
    }
    
    void AMultiplayerCharacter::MoveForward(float Value)
    {
    	if ((Controller != nullptr) && (Value != 0.0f))
    	{
    		// find out which way is forward
    		const FRotator Rotation = Controller->GetControlRotation();
    		const FRotator YawRotation(0, Rotation.Yaw, 0);
    
    		// get forward vector
    		const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
    		AddMovementInput(Direction, Value);
    	}
    }
    
    void AMultiplayerCharacter::MoveRight(float Value)
    {
    	if ( (Controller != nullptr) && (Value != 0.0f) )
    	{
    		// find out which way is right
    		const FRotator Rotation = Controller->GetControlRotation();
    		const FRotator YawRotation(0, Rotation.Yaw, 0);
    	
    		// get right vector 
    		const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
    		// add movement in that direction
    		AddMovementInput(Direction, Value);
    	}
    }

    AMultiplayerCharacter::AMultiplayerCharacter()

    • Delegate 연결
      • : FindSessionsCompleteDelegate(FOnFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnFindSessionsComplete))

     

    함수 정의

    • void AMultiplayerCharacter::JoinGameSession()
    • void AMultiplayerCharacter::OnFindSessionsComplete(bool bWasSuccessful)

     


     

    BP_ThirdPersonCharacter

     

     

     


     

    Package Project

     

     

     


     

     

    Steam - region 확인하기 & 설정하기

     

     


     

     

    실행화면

     

    다른 컴퓨터에서 Project Package 한 .exe 파일을 실행한 화면.