목차

     

     


     

     

     

     

     

     

    프로젝트 생성 + Plugin: Online Subsystem Steam 등록하기 

     


     

    프로젝트 생성

     

     

     

     

     


     

    Plugin 설치하기  -  Online Subsystem Steam 설치

     

     


     

     

    Multiplayer.Build.cs - Plugin인 OnlineSubsystemSteam과 OnlineSubsystem을 연결한다.

     

    Multiplayer.Build.cs

    using UnrealBuildTool;
    
    public class Multiplayer : ModuleRules
    {
    	public Multiplayer(ReadOnlyTargetRules Target) : base(Target)
    	{
    		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
    
    		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "OnlineSubsystemSteam", "OnlineSubsystem" });
    	}
    }

     

    "OnlineSubsystemSteam", "OnlineSubsystem"  추가

     


     

     

    DefaultGame.ini 에 코드 추가하기

     

    코드 추가하기

    [/Script/Engine.GameSession]
    MaxPlayers=100

     

     

     


     

     

     

    DefaultEngine.ini

     

    https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/Online/Steam/

     

    Online Subsystem Steam

    An overview of Online Subsystem Steam, including how to set up your project for distribution on Valve's Steam platform.

    docs.unrealengine.com

    End Result 섹션 참조

     

     

    DefaultEngine.ini

    [/Script/Engine.GameEngine]
    +NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
    
    [OnlineSubsystem]
    DefaultPlatformService=Steam
    
    [OnlineSubsystemSteam]
    bEnabled=true
    SteamDevAppId=480
    
    ; If using Sessions
    ; bInitServerOnClient=true
    
    [/Script/OnlineSubsystemSteam.SteamNetDriver]
    NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection"

     

    SteamDevAppId=480는 Steam 예시 프로젝트인 "Space War"이다. 이것으로 테스팅하면 된다.

     

    위의 코드를 복사하여 DefaultEngine.ini 코드 아래 부분에 붙여넣기 해준다. 

     

     

     

    ※ 참고: Steam에서 DevID = 480Spacewar

     

     

     

     

    DefaultEngine.ini

    [/Script/EngineSettings.GameMapsSettings]
    GameDefaultMap=/Game/ThirdPerson/Maps/ThirdPersonMap.ThirdPersonMap
    EditorStartupMap=/Game/ThirdPerson/Maps/ThirdPersonMap.ThirdPersonMap
    GlobalDefaultGameMode="/Script/Multiplayer.MultiplayerGameMode"
    
    [/Script/IOSRuntimeSettings.IOSRuntimeSettings]
    MinimumiOSVersion=IOS_14
    
    [/Script/Engine.RendererSettings]
    r.Shadow.Virtual.Enable=1
    r.Mobile.EnableNoPrecomputedLightingCSMShader=1
    
    
    r.GenerateMeshDistanceFields=True
    
    r.DynamicGlobalIlluminationMethod=1
    
    r.ReflectionMethod=1
    
    [/Script/HardwareTargeting.HardwareTargetingSettings]
    TargetedHardwareClass=Desktop
    AppliedTargetedHardwareClass=Desktop
    DefaultGraphicsPerformance=Maximum
    AppliedDefaultGraphicsPerformance=Maximum
    
    [/Script/WindowsTargetPlatform.WindowsTargetSettings]
    DefaultGraphicsRHI=DefaultGraphicsRHI_DX12
    
    [/Script/Engine.Engine]
    +ActiveGameNameRedirects=(OldGameName="TP_ThirdPerson",NewGameName="/Script/Multiplayer")
    +ActiveGameNameRedirects=(OldGameName="/Script/TP_ThirdPerson",NewGameName="/Script/Multiplayer")
    +ActiveClassRedirects=(OldClassName="TP_ThirdPersonGameMode",NewClassName="MultiplayerGameMode")
    +ActiveClassRedirects=(OldClassName="TP_ThirdPersonCharacter",NewClassName="MultiplayerCharacter")
    
    [/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings]
    bEnablePlugin=True
    bAllowNetworkConnection=True
    SecurityToken=0EE075DC4E9840DD7FB23B839AD4B854
    bIncludeInShipping=False
    bAllowExternalStartInShipping=False
    bCompileAFSProject=False
    bUseCompression=False
    bLogFiles=False
    bReportStats=False
    ConnectionType=USBOnly
    bUseManualIPAddress=False
    ManualIPAddress=
    
    [/Script/Engine.GameEngine]
    +NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
    
    [OnlineSubsystem]
    DefaultPlatformService=Steam
    
    [OnlineSubsystemSteam]
    bEnabled=true
    SteamDevAppId=480
    bInitServerOnClient=true
    
    [/Script/OnlineSubsystemSteam.SteamNetDriver]
    NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection"

    bInitServerOnClient=true 를 안 해주면 정상적으로 Package가 안 될 수도 있다. 

     

     

     

     

     

    Generate Visual Studio project files 클릭

     


     

     

     

     

    Online Subsystem에 접근하기

     

     


     

     

    MultiplayerCharacter

     

    MultiplayerCharacter.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "GameFramework/Character.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
    	TSharedPtr<class IOnlineSession, ESPMode::ThreadSafe> OnlineSessionInterface;
    };

    변수 추가

    • TSharedPtr<class IOnlineSession, ESPMode::ThreadSafe> OnlineSessionInterface;
      • online session interface를 가리키는 포인터

     

     

     

    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 "Interfaces/OnlineSessionInterface.h"
    
    //////////////////////////////////////////////////////////////////////////
    // AMultiplayerCharacter
    
    AMultiplayerCharacter::AMultiplayerCharacter()
    {
    	// 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::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 "OnlineSubsystem.h"
    • #include "Interfaces/OnlineSessionInterface.h"

     

    AMultiplayerCharacter::AMultiplayerCharacter()

    • 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())
                  );
              }
          }

     

     


     

    Package Project

     

     

     


     

    다른 컴퓨터에서 .exe 파일 열기

     

     


     

     

    실행화면