[UE] Multiplayer 5: Plugin: Plugin 만들기, Menu 생성하기
온라인에서 Player들이 접근할 수 있게 만드는 Plugin을 만들것이다. 기존에 구현했던것과 달리 Plugin을 만들어 사용하면 관리가 용이하다. 기존에 했던 작업을 분리할 수 있는 Plugin을 만들고 좀 더 고도화 해보자.
목차
Plugin 만들기
Plugin 만들기
새로운 Plugin 생성
새로 만든 Plugin에 OnlineSubsystem, OnlineSubsystemSteam 플러그인 정보 기입 - MultiplayerSessions.uplugin
MultiplayerSessions.uplugin
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "MultiplayerSessions",
"Description": "Online Multiplayer Sessions",
"Category": "Other",
"CreatedBy": "SW",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": true,
"IsBetaVersion": false,
"IsExperimentalVersion": false,
"Installed": false,
"Modules": [
{
"Name": "MultiplayerSessions",
"Type": "Runtime",
"LoadingPhase": "Default"
}
],
"Plugins": [
{
"Name": "OnlineSubsystem",
"Enabled": true
},
{
"Name": "OnlineSubsystemSteam",
"Enabled": true
}
]
}
새로 만든 Plugin에 OnlineSubsystem, OnlineSubsystemSteam 플러그인 정보 기입 - MultiplayerSessions.Build.cs
MultiplayerSessions.Build.cs
// Copyright Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
public class MultiplayerSessions : ModuleRules
{
public MultiplayerSessions(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.AddRange(
new string[] {
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[] {
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"OnlineSubsystem",
"OnlineSubsystemSteam",
// ... add other public dependencies that you statically link with here ...
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
// ... add private dependencies that you statically link with here ...
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
}
}
"OnlineSubsystem", "OnlineSubsystemSteam" 추가하기
Plugin 기본 기능 추가하기
GameInstanceSubsystem으로부터 상속받는 클래스 만들기
GameInstance를 부모로 가지는 클래스를 만들면 MultiplayerSession의 기능들을 포함할 수 있기 때문에 문제가 될 수 있다.
그래서 GameInstance를 상속받는 대신, GameInstanceSubsystem으로부터상속받는 새로운 클래스를 만들어 사용할 것이다.
https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/Subsystems/
위 링크 언리얼 공식문서의 Reasons to Use Subsystems 참조.
- Engine classes의 overriding을 피하기 위해 사용 등등.
Game Instance | Game Instance Subsystem |
- Game 생성 시 Spawn 된다. - Game이 종료될 때까지 소멸되지 않는다. (=Game 종료 시 소멸) - 레벨 간 이동해도 계속해서 존재한다. |
- Game Instance가 생성 된 후에 생성된다. - Game Instance 종료 시 소멸되고 Garbage Collector에서 처리된다. |
게임에서 레벨을 이동하는 경우(=던전 입장, 마을 이동 등등)가 빈번히 발생한다. 또한 FPS 게임의 경우, 한 게임이 끝나고 다시 게임이 시작되는 경우가 빈번히 발생한다.
그렇게 때문에 Game이 종료될 때까지 소멸하지 않는 Game Instance보다 Game Instance Subsytem을 사용하는 것이 더 유리하다. Game Instance Subsystem을 사용하면 엔진 클래스 오버라이드를 피할 수 있고 코드의 재사용성을 높일 수 있다.
MultiplayerSessionsSubsystem 생성
New C++ class - GameInstanceSubsystem - MultiplayerSessionsSubsystem 생성
MultiplayerSessionsSubsystem.h
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "Interfaces/OnlineSessionInterface.h"
#include "MultiplayerSessionsSubsystem.generated.h"
UCLASS()
class MULTIPLAYERSESSIONS_API UMultiplayerSessionsSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
UMultiplayerSessionsSubsystem();
//
// To handle session functionality. The Menu class will call these
//
void CreateSession(int32 NumPublicConnections, FString MatchType);
void FindSessions(int32 MaxSearchResults);
void JoinSession(const FOnlineSessionSearchResult& SessionResult);
void DestroySession();
void StartSession();
protected:
// Internal callbacks for the delegates we'll add to the Online Session Interface delegate list.
// 아래의 함수들은 이 클래스 밖에서 콜하지 않는다.
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;
//
// To add to the Online Session Interface delegate list.
// We'll bind our MultiplayerSessionsSubsystem internal callbacks to these.
//
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"
UMultiplayerSessionsSubsystem::UMultiplayerSessionsSubsystem(): //Delegate을 만들어 On~함수에 연결한다.
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();//SessionInterface 변수에 IOnlineSubsystem의 SessionInterface 정보를 담는다.
}
}
void UMultiplayerSessionsSubsystem::CreateSession(int32 NumPublicConnections, FString MatchType)
{
}
void UMultiplayerSessionsSubsystem::FindSessions(int32 MaxSearchResults)
{
}
void UMultiplayerSessionsSubsystem::JoinSession(const FOnlineSessionSearchResult& SessionResult)
{
}
void UMultiplayerSessionsSubsystem::DestroySession()
{
}
void UMultiplayerSessionsSubsystem::StartSession()
{
}
void UMultiplayerSessionsSubsystem::OnCreateSessionComplete(FName SessionName, bool bWasSuccessful)
{
}
void UMultiplayerSessionsSubsystem::OnFindSessionsComplete(bool bWasSuccessful)
{
}
void UMultiplayerSessionsSubsystem::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
{
}
void UMultiplayerSessionsSubsystem::OnDestroySessionComplete(FName SessionName, bool bWasSuccessful)
{
}
void UMultiplayerSessionsSubsystem::OnStartSessionComplete(FName SessionName, bool bWasSuccessful)
{
}
MultiplayerSessions.Build.cs
MultiplayerSessions.Build.cs
using UnrealBuildTool;
public class MultiplayerSessions : ModuleRules
{
public MultiplayerSessions(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.AddRange(
new string[] {
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[] {
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"OnlineSubsystem",
"OnlineSubsystemSteam",
"UMG",
"Slate",
"SlateCore"
// ... add other public dependencies that you statically link with here ...
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
// ... add private dependencies that you statically link with here ...
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
}
}
"UMG", "Slate", "SlateCore" 추가
Menu 생성
New C++ class - UserWidget - Menu 생성
Menu.h
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Menu.generated.h"
UCLASS()
class MULTIPLAYERSESSIONS_API UMenu : public UUserWidget
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
void MenuSetup();
};
Menu.cpp
#include "Menu.h"
void UMenu::MenuSetup()
{
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);
}
}
}
WBP_Menu
우클릭 - User Interface - Widget Blueprint - WBP_Menu 생성
Canvas Panel
- Button 2개와 버튼 안에 Text 추가.
Widget 확인을 위해 Level Blueprint에 Widget을 생성하여 테스트한다.
실행화면
'⭐ Unreal Engine > UE Multiplayer FPS TPS + ListenServer' 카테고리의 다른 글
[UE] Multiplayer 7-1: Session 만들기 (0) | 2023.07.17 |
---|---|
[UE] Multiplayer 6: Button Callbacks 만들기, SubSystem 접근하기 (0) | 2023.07.17 |
[UE] Multiplayer 4: Session 들어가기 (0) | 2023.07.15 |
[UE] Multiplayer 3: Session 생성하기 (0) | 2023.07.15 |
[UE] Multiplayer 2: Online Subsystem Steam (0) | 2023.07.15 |
댓글
이 글 공유하기
다른 글
-
[UE] Multiplayer 7-1: Session 만들기
[UE] Multiplayer 7-1: Session 만들기
2023.07.17 -
[UE] Multiplayer 6: Button Callbacks 만들기, SubSystem 접근하기
[UE] Multiplayer 6: Button Callbacks 만들기, SubSystem 접근하기
2023.07.17 -
[UE] Multiplayer 4: Session 들어가기
[UE] Multiplayer 4: Session 들어가기
2023.07.15 -
[UE] Multiplayer 3: Session 생성하기
[UE] Multiplayer 3: Session 생성하기
2023.07.15