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

相关推荐
OpenC++5 分钟前
【C++QT】Layout 布局管理控件详解
c++·经验分享·qt·leetcode
灏瀚星空22 分钟前
从基础到实战的量化交易全流程学习:1.3 数学与统计学基础——概率与统计基础 | 基础概念
笔记·python·学习·金融·概率论
无敌的牛36 分钟前
AVL树的介绍与学习
数据结构·学习
1白天的黑夜139 分钟前
贪心算法-860.柠檬水找零-力扣(LeetCode)
c++·算法·leetcode·贪心算法
BS_Li1 小时前
C++类和对象(上)
开发语言·c++·类和对象
【0931】1 小时前
进程控制的学习
学习·操作系统
阿图灵1 小时前
文章记单词 | 第48篇(六级)
学习·学习方法
宁建利1 小时前
树莓派学习专题<11>:使用V4L2驱动获取摄像头数据--启动/停止数据流,数据捕获,缓存释放
学习
阳光宅男@李光熠1 小时前
【质量管理】TRIZ(萃智)的工程系统进化法则
笔记·学习
Suckerbin1 小时前
pikachu靶场-敏感信息泄露
网络·学习·安全·网络安全