本文为B站系列教学视频 《UE5_C++多人TPS完整教程》 —— 《P18 访问我们的子系统(Acessing Our Subsystem》 的学习笔记,该系列教学视频为 Udemy 课程 《Unreal Engine 5 C++ Multiplayer Shooter》 的中文字幕翻译版,UP主(也是译者)为 游戏引擎能吃么。
P18 访问我们的子系统
本节课我们将定义能够响应点击按钮事件的回调函数,并这些函数与虚幻引擎中的相应的控件进行链接、绑定,从而在访问我们的子系统后调用子系统的会话接口函数。
18.1 创建按钮类及与其绑定的回调函数
-
在 “
Menu.h
” 中定义按钮类 “HostButton
” 和 “JoinButton
”并将它们与虚幻引擎中控件蓝图 “WBP_Menu
” 中对应的两个按钮链接起来,注意在定义按钮类时需要保证 C++ 变量名和虚幻引擎中的按钮控件名称相同,否则会报错。// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Blueprint/UserWidget.h" /* P18 访问我们的子系统(Acessing Our Subsystem)*/ #include "Components/Button.h" /* P18 访问我们的子系统(Acessing Our Subsystem)*/ #include "Menu.generated.h" /** * */ UCLASS() class MULTIPLAYERSESSIONS_API UMenu : public UUserWidget { GENERATED_BODY() public: UFUNCTION(BlueprintCallable) void MenuSetup(); /* P18 访问我们的子系统(Acessing Our Subsystem)*/ protected: virtual bool Initialize() override; // 初始化函数重写,绑定按钮与回调函数 private: UPROPERTY(meta = (BindWidget)) // 与虚幻引擎中的按钮控件链接 class UButton* HostButton; // 保证 C++ 变量名和虚幻引擎中的按钮控件名称相同 UPROPERTY(meta = (BindWidget)) // 与虚幻引擎中的按钮控件链接 UButton* JoinButton; // 保证 C++ 变量名和虚幻引擎中的按钮控件名称相同 UFUNCTION() void HostButtonClicked(); // 回调函数:响应鼠标单击 HostButton 事件 UFUNCTION() void JoinButtonClicked(); // 回调函数:响应鼠标单击 JoinButton 事件 /* P18 访问我们的子系统(Acessing Our Subsystem)*/ };
-
在 “
Menu.cpp
” 中重写(Override) “Initialize()
” 函数,将回调函数绑定到鼠标单击按钮事件上。/* P18 访问我们的子系统(Acessing Our Subsystem)*/ bool UMenu::Initialize() // 用户控件初始化 { // 调用父类的 Initialize() 函数 if (!Super::Initialize()) { // 若初始化失败,直接退出 return false; } if (HostButton) { HostButton->OnClicked.AddDynamic(this, &ThisClass::HostButtonClicked); // 绑定回调函数 HostButtonClicked() } if (JoinButton) { JoinButton->OnClicked.AddDynamic(this, &ThisClass::JoinButtonClicked); // 绑定回调函数 JoinButtonClicked() } return true; } void UMenu::HostButtonClicked() // 回调函数:响应鼠标单击 HostButton 事件 { if (GEngine) { GEngine->AddOnScreenDebugMessage( // 添加调试信息到屏幕上 -1, // 使用 -1 不会覆盖前面的调试信息 15.f, // 调试信息的显示时间 FColor::Yellow, // 字体颜色:黄色 FString::Printf(TEXT("Host Button Clicked!")) // 打印点击事件消息 ); } } void UMenu::JoinButtonClicked() // 回调函数:响应鼠标单击 HostButton 事件 { if (GEngine) { GEngine->AddOnScreenDebugMessage( // 添加调试信息到屏幕上 -1, // 使用 -1 不会覆盖前面的调试信息 15.f, // 调试信息的显示时间 FColor::Yellow, // 字体颜色:黄色 FString::Printf(TEXT("Join Button Clicked!")) // 打印点击事件消息 ); } } /* P18 访问我们的子系统(Acessing Our Subsystem)*/
-
在 VS 中生成解决方案,打开虚幻引擎,使用 PIE 模式进行测试,可以看到点击两个按钮之后视口面板左上角出现了相应的消息文本。
18.2 访问子系统
-
在 “
Menu.h
” 中添加头文件 “MultiplayerSessionsSubsystem.h
”;然后在 “Menu
” 类中添加代码,定义一个子系统类型 “UMultiplayerSessionsSubsystem
” 的变量。... /* P18 访问我们的子系统(Acessing Our Subsystem)*/ #include "Components/Button.h" #include "MultiplayerSessionsSubsystem.h" /* P18 访问我们的子系统(Acessing Our Subsystem)*/ ... class MULTIPLAYERSESSIONS_API UMenu : public UUserWidget { GENERATED_BODY() ... /* P18 访问我们的子系统(Acessing Our Subsystem)*/ protected: virtual bool Initialize() override; // 初始化重写函数,绑定按钮与回调函数 private: UPROPERTY(meta = (BindWidget)) // 与虚幻引擎中的按钮控件链接 class UButton* HostButton; // 保证 C++ 变量名和虚幻引擎中的按钮控件名称相同 UPROPERTY(meta = (BindWidget)) // 与虚幻引擎中的按钮控件链接 UButton* JoinButton; // 保证 C++ 变量名和虚幻引擎中的按钮控件名称相同 UFUNCTION() void HostButtonClicked(); // 回调函数:响应单击 HostButton 事件 UFUNCTION() void JoinButtonClicked(); // 回调函数:响应单击 HostButton 事件 class UMultiplayerSessionsSubsystem* MultiplayerSessionsSubsystem; // 处理所有在线会话功能的子系统 /* P18 访问我们的子系统(Acessing Our Subsystem)*/ };
-
在 “
Menu.cpp
” 的 “MenuSetup()
” 函数中添加访问子系统的代码。void UMenu::MenuSetup() { AddToViewport(); // 添加到视口 SetVisibility(ESlateVisibility::Visible); // 设置菜单可见 bIsFocusable = true; // 允许鼠标点击的时候聚焦 UWorld* world = GetWorld(); if (world) { APlayerController* playerControler = world->GetFirstPlayerController(); // 获取玩家控制器指针 if (playerControler) { FInputModeUIOnly InputModeSettings; // 用于设置只允许控制 UI 的输入模式 // 输入模式设置 InputModeSettings.SetWidgetToFocus(TakeWidget()); // 设置焦距,TakeWidget()将获取底层的 slate 部件,如果不存在则构造它 InputModeSettings.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock); //设置鼠标在视口时不锁定 // 将设置好的输入模式传送到到玩家控制器的输入模式 playerControler->SetInputMode(InputModeSettings); // 设置玩家控制器的输入模式 playerControler->SetShowMouseCursor(true); // 显示鼠标光标 } } /* P18 访问我们的子系统(Acessing Our Subsystem)*/ UGameInstance* GameInstance = GetGameInstance(); // 获取游戏实例 if (GameInstance) { MultiplayerSessionsSubsystem = GameInstance->GetSubsystem<UMultiplayerSessionsSubsystem>(); // 访问子系统 } /* P18 访问我们的子系统(Acessing Our Subsystem)*/ }
-
在 “
Menu.cpp
” 的 “HostButtonClicked()
” 函数中添加使用子系统 “MultiplayerSessionsSubsystem
” 创建游戏会话函数的代码,最后进行编译。void UMenu::HostButtonClicked() // 回调函数:响应鼠标单击 HostButton 事件 { if (GEngine) { GEngine->AddOnScreenDebugMessage( // 添加调试信息到屏幕上 -1, // 使用 -1 不会覆盖前面的调试信息 15.f, // 调试信息的显示时间 FColor::Yellow, // 字体颜色:黄色 FString::Printf(TEXT("Host Button Clicked!")) // 打印点击事件消息 ); } if (MultiplayerSessionsSubsystem) { MultiplayerSessionsSubsystem->CreateSession(4, FString("FreeForAll")); // 创建游戏会话 } }
18.3 Summary
本节课首先在 “Menu.h
” 中定义按钮类 “HostButton
” 和 “JoinButton
”,将它们与虚幻引擎中控件蓝图 “WBP_Menu
” 中对应的两个按钮链接起来,接着将回调函数绑定到鼠标单击按钮事件上;此后在 “Menu
” 类定义一个我们之前创建的子系统类型 “UMultiplayerSessionsSubsystem
” 的变量,通过获取到的游戏实例访问子系统。
在 18.1 创建按钮类及与其绑定的回调函数 的 步骤 1 中,注意在定义按钮类时需要保证 C++ 变量名和虚幻引擎中的按钮控件名称 相同,否则会报错。