UE5 C++ TPS开发 学习记录(五)

这节课创建了新的游戏关卡Lobby,制作了属于自己的游戏名字"Match Type",制作了加入游戏会话的委托和函数,最后可以用IP就可以把客户端链接到服务端

.h

// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "Logging/LogMacros.h" #include "OnlineSubsystem.h" #include "Interfaces/OnlineSessionInterface.h" #include "MenuCharacter.generated.h" class USpringArmComponent; class UCameraComponent; class UInputMappingContext; class UInputAction; struct FInputActionValue; DECLARE_LOG_CATEGORY_EXTERN(LogTemplateCharacter, Log, All); UCLASS(config=Game) class AMenuCharacter : public ACharacter { GENERATED_BODY() /** Camera boom positioning the camera behind the character */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) USpringArmComponent* CameraBoom; /** Follow camera */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) UCameraComponent* FollowCamera; /** MappingContext */ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true")) UInputMappingContext* DefaultMappingContext; /** Jump Input Action */ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true")) UInputAction* JumpAction; /** Move Input Action */ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true")) UInputAction* MoveAction; /** Look Input Action */ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true")) UInputAction* LookAction; public: AMenuCharacter(); protected: /** Called for movement input */ void Move(const FInputActionValue& Value); /** Called for looking input */ void Look(const FInputActionValue& Value); protected: // APawn interface virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; // To add mapping context virtual void BeginPlay(); 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 void _MyDebugLog(int32 Key, float TimeToDisplay, FColor DisplayColor, const FString& DebugMessage); IOnlineSessionPtr OnlineSessionInterface; protected: //创建会话 UFUNCTION(BlueprintCallable,Category="My") void CreateGameSession(); //创建会话成功 void OnCreateSessionComplete(FName SessionName, bool bWasSuccess); //加入会话 UFUNCTION(BlueprintCallable,Category="My") void JoinSession(); //查找会话成功 void FindSessionComplete(bool bWasSuccess); // void JoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result); private: //创建会话的委托 FOnCreateSessionCompleteDelegate OnCreateSessionCompleteDelegate; //查找会话的委托 FOnFindSessionsCompleteDelegate OnFindSessionsCompleteDelegate; //查找会话设置 TSharedPtr<FOnlineSessionSearch> SessionSearch; //加入会话 FOnJoinSessionCompleteDelegate OnJoinSessionCompleteDelegate; };

.cpp

// Copyright Epic Games, Inc. All Rights Reserved. #include "MenuCharacter.h" #include "Engine/LocalPlayer.h" #include "Camera/CameraComponent.h" #include "Components/CapsuleComponent.h" #include "GameFramework/CharacterMovementComponent.h" #include "GameFramework/SpringArmComponent.h" #include "GameFramework/Controller.h" #include "EnhancedInputComponent.h" #include "EnhancedInputSubsystems.h" #include "OnlineSessionSettings.h" #include "InputActionValue.h" #include "Online/OnlineSessionNames.h" DEFINE_LOG_CATEGORY(LogTemplateCharacter); // // AMenuCharacter AMenuCharacter::AMenuCharacter(): OnCreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this,&ThisClass::OnCreateSessionComplete)), OnFindSessionsCompleteDelegate(FOnFindSessionsCompleteDelegate::CreateUObject(this,&ThisClass::FindSessionComplete)), OnJoinSessionCompleteDelegate(FOnJoinSessionCompleteDelegate::CreateUObject(this,&ThisClass::JoinSessionComplete)) { // Set size for collision capsule GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f); // 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; GetCharacterMovement()->BrakingDecelerationFalling = 1500.0f; // 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++) //添加访问Steam会话系统 IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get(); if(OnlineSubsystem) { //获得当前会话的指针 OnlineSessionInterface = OnlineSubsystem->GetSessionInterface(); _MyDebugLog(-1,15.f,FColor::Blue,FString::Printf(TEXT("Now Subsystem %s"),*OnlineSubsystem->GetSubsystemName().ToString())); } } void AMenuCharacter::_MyDebugLog(int32 Key, float TimeToDisplay, FColor DisplayColor, const FString& DebugMessage) { if(GEngine) { GEngine->AddOnScreenDebugMessage(Key,TimeToDisplay,DisplayColor,DebugMessage); } } void AMenuCharacter::CreateGameSession() { //Called when pressing the 1 key //检测IOnlineSessionPtr是否有效 if(!OnlineSessionInterface.IsValid()) { return; } //获得当前会话名字并且放在变量内 auto ExistingSession = OnlineSessionInterface->GetNamedSession(NAME_GameSession); //当存在会话的时候,删除会话 if(ExistingSession!=nullptr) { OnlineSessionInterface->DestroySession(NAME_GameSession); } OnlineSessionInterface->AddOnCreateSessionCompleteDelegate_Handle(OnCreateSessionCompleteDelegate); //创建智能指针会话设置 TSharedPtr<FOnlineSessionSettings> SessionSettings = MakeShareable(new FOnlineSessionSettings()); //非局域网 SessionSettings->bIsLANMatch = false; //最多4人 SessionSettings->NumPublicConnections =4; //允许其他玩家加入 SessionSettings->bAllowJoinInProgress = true; //允许好友加入 SessionSettings->bAllowJoinViaPresence = true; //线上公开 SessionSettings->bShouldAdvertise = true; //显示用户状态 SessionSettings->bUsesPresence = true; //使用第三方 SessionSettings->bUseLobbiesIfAvailable = true; //设置会话搜索设置,Name是"MatchType",值是"FreeForAll" SessionSettings->Set(FName("MatchType"),FString("FreeForAll"),EOnlineDataAdvertisementType::ViaOnlineServiceAndPing); const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController(); OnlineSessionInterface->CreateSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession , *SessionSettings); } void AMenuCharacter::OnCreateSessionComplete(FName SessionName, bool bWasSuccess) { if(bWasSuccess) { _MyDebugLog(-1,15.f,FColor::Blue,FString::Printf(TEXT("Create Session Success : %s"), *SessionName.ToString())); UWorld* World = GetWorld(); if(World) { World->ServerTravel("/Game/ThirdPerson/Maps/Lobby?listen"); } } else { _MyDebugLog(-1,15.f,FColor::Red,FString(TEXT("Faild to Create Session"))); } return; } void AMenuCharacter::JoinSession() { /*找到会话*/ if(!OnlineSessionInterface.IsValid()) { return; } //添加查询委托 OnlineSessionInterface->AddOnFindSessionsCompleteDelegate_Handle(OnFindSessionsCompleteDelegate); //设置查找 SessionSearch = MakeShareable(new FOnlineSessionSearch()); SessionSearch->MaxSearchResults = 10000; SessionSearch->bIsLanQuery=false; //设置查询设置 SessionSearch->QuerySettings.Set(SEARCH_PRESENCE,true,EOnlineComparisonOp::Equals); //获得本地的第一个玩家 const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController(); //使用本地的第一个玩家的URL和查找设置进行查找 OnlineSessionInterface->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(),SessionSearch.ToSharedRef()); } void AMenuCharacter::FindSessionComplete(bool bWasSuccess) { if(!OnlineSessionInterface.IsValid()) { return; } for(auto Result : SessionSearch->SearchResults) { FString Id = Result.GetSessionIdStr(); FString User = Result.Session.OwningUserName; FString MatchType; //找到所有Key是"MatchType"类型的房间 Result.Session.SessionSettings.Get("MatchType",MatchType); _MyDebugLog(-1,15.f,FColor::Cyan,FString::Printf(TEXT("Id : %s , Name : %s"),*Id,*User)); if(MatchType == "FreeForAll") { _MyDebugLog(-1,15.f,FColor::Cyan,FString::Printf(TEXT("Join Match Type : %s"),*MatchType)); //绑定加入委托 OnlineSessionInterface->AddOnJoinSessionCompleteDelegate_Handle(OnJoinSessionCompleteDelegate); const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController(); //调用JoinSession,并且加入的时候调用OnJoinSessionCompleteDelegate这个委托 OnlineSessionInterface->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(),NAME_GameSession,Result); } } } void AMenuCharacter::JoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result) { if(!OnlineSessionInterface.IsValid()) { return; } FString Address; // if(OnlineSessionInterface->GetResolvedConnectString(NAME_GameSession,Address)) { _MyDebugLog(-1,15.f,FColor::Yellow,FString::Printf(TEXT("Connect String : %s"),*Address)); APlayerController* PlayerController = GetGameInstance()->GetFirstLocalPlayerController(); if(PlayerController) { PlayerController->ClientTravel(Address,ETravelType::TRAVEL_Absolute); } } } void AMenuCharacter::BeginPlay() { // Call the base class Super::BeginPlay(); //Add Input Mapping Context if (APlayerController* PlayerController = Cast<APlayerController>(Controller)) { if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer())) { Subsystem->AddMappingContext(DefaultMappingContext, 0); } } } // // Input void AMenuCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { // Set up action bindings if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent)) { // Jumping EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump); EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping); // Moving EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMenuCharacter::Move); // Looking EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AMenuCharacter::Look); } else { UE_LOG(LogTemplateCharacter, Error, TEXT("'%s' Failed to find an Enhanced Input component! This template is built to use the Enhanced Input system. If you intend to use the legacy system, then you will need to update this C++ file."), *GetNameSafe(this)); } } void AMenuCharacter::Move(const FInputActionValue& Value) { // input is a Vector2D FVector2D MovementVector = Value.Get<FVector2D>(); if (Controller != nullptr) { // find out which way is forward const FRotator Rotation = Controller->GetControlRotation(); const FRotator YawRotation(0, Rotation.Yaw, 0); // get forward vector const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X); // get right vector const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y); // add movement AddMovementInput(ForwardDirection, MovementVector.Y); AddMovementInput(RightDirection, MovementVector.X); } } void AMenuCharacter::Look(const FInputActionValue& Value) { // input is a Vector2D FVector2D LookAxisVector = Value.Get<FVector2D>(); if (Controller != nullptr) { // add yaw and pitch input to controller AddControllerYawInput(LookAxisVector.X); AddControllerPitchInput(LookAxisVector.Y); } }

因为一个Steam只能同时链接一个Address,所以我没有测试成功.第一个链接上了Steam,第二个就会出现链接Null

相关推荐
Voyager_48 小时前
算法学习记录03——二叉树学习笔记:从两道题看透后序位置的关键作用
笔记·学习·算法
云泽8089 小时前
函数模板与类模板:C++泛型编程核心解析
java·开发语言·c++
我先去打把游戏先10 小时前
ESP32学习笔记(基于IDF):ESP32连接MQTT服务器
服务器·笔记·单片机·嵌入式硬件·学习·esp32
R-G-B13 小时前
【25】MFC入门到精通——MFC静态文本框 中字符串 连续输出 不覆盖先前的文本 换行输出
c++·mfc·mfc静态文本框输出字符串·mfc静态文本框连续输出字符串·mfc静态文本框换行输出字符串
deng-c-f13 小时前
Linux C/C++ 学习日记(29):IO密集型与CPU密集型、CPU的调度与线程切换
linux·学习·线程·cpu·io密集·cpu密集
四谎真好看15 小时前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
洋洋的笔记15 小时前
银行测试学习计划
学习
FFZero116 小时前
【C++/Lua联合开发】 (二) Lua调用C++函数
c++·junit·lua
Allan_202516 小时前
数据库学习
数据库·学习
报错小能手16 小时前
linux学习笔记(43)网络编程——HTTPS (补充)
linux·网络·学习