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

相关推荐
Paddi93029 分钟前
Codeforces Round 1004 (Div. 1) C. Bitwise Slides
c++·算法
Luis Li 的猫猫1 小时前
深度学习中的知识蒸馏
人工智能·经验分享·深度学习·学习·算法
鹿鸣悠悠3 小时前
第二月:学习 NumPy、Pandas 和 Matplotlib 是数据分析和科学计算的基础
学习·numpy·pandas
流星白龙5 小时前
【C++】36.C++IO流
开发语言·c++
Java能学吗5 小时前
2.17学习总结
数据结构·学习
靡不有初1116 小时前
CCF-CSP第31次认证第二题——坐标变换(其二)【NA!前缀和思想的细节,输出为0的常见原因】
c++·学习·ccfcsp
YH_DevJourney8 小时前
Linux-C/C++《C/7、字符串处理》(字符串输入/输出、C 库中提供的字符串处理函数、正则表达式等)
linux·c语言·c++
和光同尘@8 小时前
1011. A+B和C (15)-PAT乙级真题
c语言·开发语言·数据结构·c++·算法
虾球xz9 小时前
游戏引擎学习第108天
学习·游戏引擎
初尘屿风9 小时前
小程序类毕业设计选题题目推荐 (29)
spring boot·后端·学习·微信·小程序·课程设计