Choose your operating system:
Windows
macOS
Linux
目标
本分段旨在向你展示如何实现第一人称射击角色。
目的
完成本教程的此分段,你便能够:
创建新角色
设置轴映射
实现角色移动函数
实现鼠标摄像机控制
实现角色跳跃
将网格体添加到角色
更改摄像机视角
将第一人称网格体添加到角色
步骤
2.1 - 创建新角色
2.2 - 设置轴映射
2.3 - 实现角色移动函数
2.4 - 实现鼠标摄像机控制
2.5 - 实现角色跳跃
2.6 - 将网格体添加到角色
2.7 - 更改摄像机视角
2.8 - 将第一人称网格体添加到角色
2.1 创建新角色
在此步骤中,你将使用引擎的 角色 基类在虚幻引擎(UE)中创建一个新角色。角色类(派生自 Pawn 类)的内置功能支持走、跑和跳等双足运动。
添加角色类
虽然你可以手动将.h和.cpp文件添加到你的Visual Studio (VS)解决方案,但使用C++类向导将新类添加到你的项目是一种很好的做法。
使用C++类向导,引擎可创建头文件和源文件模板,这些模板文件将为你预先设置一些虚幻特定的宏。
在UE中启动FPS项目(如果你尚未完成此操作)。
在文件(File)菜单中,选择 新建C++类...(New C++ Class...),以选择新的父类。
以上操作将打开 选择父类(Choose Parent Class) 菜单。向下滚动,选择 角色 作为父类,然后点击 下一步(Next)。
将新类命名为"FPSCharacter",然后点击 创建类(Create Class)。
确认角色类
在VS的 解决方案浏览器 中,依次展开 FPSProject > 源(Source) > FPSProject。
点击
FPSCharacter.cpp
,打开 FPSCharacter 类的实现文件。在
BeginPlay()
函数中添加以下代码行(在Super::BeginPlay();
下面),以便确认正在使用FPSCharacter
类:check(GEngine != nullptr); // 显示调试消息五秒。 // -1"键"值参数可以防止更新或刷新消息。 GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("We are using FPSCharacter."));
现在
FPSCharacter.cpp
的内容应如下所示://版权所有Epic Games, Inc。保留所有权利。 #include "FPSCharacter.h" // 设置默认值 AFPSCharacter::AFPSCharacter() { // 将此角色设置为每帧调用Tick()。 如果不需要此特性,可以关闭以提升性能。 PrimaryActorTick.bCanEverTick = true; } // 当游戏开始或重生(Spawn)时被调用 void AFPSCharacter::BeginPlay() { Super::BeginPlay(); check(GEngine != nullptr); // 显示调试消息五秒。 // -1"键"值参数可以防止更新或刷新消息。 GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("We are using FPSCharacter.")); } // 每一帧都被调用 void AFPSCharacter::Tick(float DeltaTime) { Super::Tick(DeltaTime); } // 被调用,将功能与输入绑定 void AFPSCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); }
在Visual Studio中保存
FPSCharacter
CPP文件。在 解决方案浏览器(Solution Explorer) 中找到 FPSProject。
到目前为止,你一直在使用编辑器的 构建(Build) 按钮编译项目。在此步骤中,你将使用Visual Studio的构建功能来编译代码。要从Visual Studio中编译代码,请右键点击 FPSProject,并选择 构建(Build) 来编译项目。
要从VS中编译代码,请右键点击 FPSProject,并选择 构建(Build) 来编译项目。
如果你使用的是VS的默认设置,则在界面底部附近(可能在代码编辑器的下方),你应该会看到一个对话框。当你点击构建(Build)后,在生成过程中该对话框中应该会显示一些信息,我们最希望显示的是构建成功的信息。 如果构建失败,不要紧张!回头看看你之前的操作步骤,确保你的代码与此处和第1分段中列出的内容相同。
构建完成后,打开虚幻编辑器,确认新编译的 FPSCharacter 类在 内容浏览器 中可见。
扩展你的C++ FPS角色类到蓝图
现在可以扩展C++ FPS角色类到蓝图了(类似之前进行的FPSProject游戏模式操作)。请随时前往我们的C++和蓝图参考页面,以了解更多关于扩展C++类到蓝图的信息。
右键点击FPSCharacter类,打开 C++类操作(C++ Class Actions) 菜单。
点击 基于FPSCharacter创建蓝图类(Create Blueprint class based on FPSHUD),打开 添加蓝图类(Add Blueprint Class) 对话框菜单。
将新的蓝图类命名为
BP_FPSCharacter
,选择蓝图(Blueprints)文件夹,然后点击 创建蓝图类(Create Blueprint Class) 按钮。现在,在蓝图(Blueprints)文件夹内,你应该可以看到新创建的
BP_FPSCharacter
蓝图类。请确保在关闭蓝图编辑器前保存
BP_FPSCharacter
蓝图。
设置默认的Pawn类
现在你已经成功地把新修改的游戏模式扩展到了蓝图,接下来你需要在此步骤中设置项目,将 BP_FPSCharacter
作为默认的 Pawn。
在 编辑(Edit) 菜单中点击 项目设置(Project Settings)。
在 项目设置(Project Settings) 选项卡左侧的 项目(Project) 标题栏下,点击 地图和模式(Maps & Modes)。
展开 已选择的游戏模式(Selected GameMode) 段,并在 默认Pawn类(Default Pawn Class) 下拉菜单中选择 BP_FPSCharacter。
关闭 项目设置(Project Settings) 菜单。
在关卡编辑器工具栏中点击 运行(Play) 按钮。在视口左上角,红色文本"We are using FPSCharacter."将显示在"Hello World, this is FPSGameMode!"的下方,并持续5秒钟。
如果你无法移动,说明你已经正确地将FPSCharacter用作了Pawn!你的新角色还没有任何移动功能按钮,因此你还不能在关卡中四处移动。
在进入下一步前,按退出键(Escape)或在关卡编辑器中点击 停止(Stop),退出在编辑器中运行(Play in Editor)(PIE)模式。
2.2 - 设置轴映射
通常,轴映射支持将键盘、鼠标和控制器输入映射到"友好名称",该名称稍后可以绑定到游戏行为上(例如移动)。轴映射会不断被轮询,从而实现无缝的移动过渡和流畅的游戏行为。硬件轴(例如游戏摇杆)所提供的输入值为程度值,而不是离散的数字输入(例如,按下为1,不按下为0)。虽然游戏摇杆输入方法在提供可平滑伸缩的移动输入方面很有效,但轴映射也可以将常见的移动键(如WASD键或箭头键)映射到持续轮询的游戏行为。
在继续此步骤之前,如果你想要了解有关玩家输入的更多信息,请参阅玩家输入和Pawn教程。在此步骤中,你将设置W、A、S和D键的输入轴映射,从而使新角色可以在地图上四处移动。
向前移动轴映射
在 编辑(Edit) 菜单中,点击 项目设置(Project Settings)。
在 项目设置(Project Settings) 选项卡左侧的 引擎(Engine) 标题栏下,点击 输入(Input)。
在 绑定(Bindings) 中,点击 轴映射(Axis Mappings) 旁边的+号。
点击 轴映射(Axis Mappings) 左侧的箭头。
在界面显示的文本框中输入"MoveForward",然后点击文本框左侧的箭头,展开轴绑定选项。
在下拉菜单中,从 键盘(Keyboard) 下拉列表中选择 W。
现在输入设置界面应如下图所示:
点击 MoveForward 旁边的+号。
在第二个下拉菜单中,从 键盘(Keyboard) 下拉列表中选择 S。
在 S 旁边的 比例(Scale) 字段中输入"-1"。
现在输入设置界面应如下图所示:
向右移动轴映射
在 绑定(Bindings) 中,点击 轴映射(Axis Mappings) 旁边的+号。
在显示的文本字段中输入"向右移动(MoveForward)",然后点击文本框左侧的箭头,展开轴绑定选项。
在下拉菜单中,从 键盘(Keyboard) 下拉列表中选择 D。
现在输入设置界面应如下图所示:
点击 向右移动(MoveRight) 旁边的+号。
在第二个下拉菜单中,从 键盘(Keyboard) 下拉列表中选择 A。
在 A 旁边的 比例(Scale) 字段中输入"-1"。
现在输入设置界面应如下图所示:
现在你已设置好向左移动(MoveLeft)和向右移动(MoveRight)轴映射,请关闭 项目设置(Project Settings) 菜单并继续。
2.3 - 实现角色移动函数
在此步骤中,我们将设置玩家输入组件,并在FPSCharacter类中实现以下函数:
MoveForward
MoveRight
移动函数接口
你已经设置好FPSCharacter的轴映射,现在可以切换到VS中的项目界面。
在
FPSCharacter.h
中,将以下函数声明添加到SetupPlayerInputComponent
成员函数的下方。// 处理用于前后移动的输入。 UFUNCTION() void MoveForward(float Value); // 处理用于左右移动的输入。 UFUNCTION() void MoveRight(float Value);
UFUNCTION
宏(位于每个函数上方)让引擎可以发觉这些函数,以便将它们纳入序列化和其他引擎功能中。现在
FPSCharacter.h
的内容应如下所示://版权所有Epic Games, Inc。保留所有权利。 #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "FPSCharacter.generated.h" UCLASS() class FPSPROJECT_API AFPSCharacter : public ACharacter { GENERATED_BODY() public: // 为此角色的属性设置默认值 AFPSCharacter(); protected: // 当游戏开始或重生(Spawn)时被调用 virtual void BeginPlay() override; public: // 每一帧都被调用 virtual void Tick( float DeltaTime ) override; // 被调用,将功能与输入绑定 virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; // 处理用于前后移动的输入。 UFUNCTION() void MoveForward(float Value); // 处理用于左右移动的输入。 UFUNCTION() void MoveRight(float Value); };
移动函数的实现
在典型的FPS控制模式中,角色的移动轴是相对于摄像机的。"向前"移动是指"摄像机指向的方向","向右"是指"摄像机指向方向的右侧"。你将使用 PlayerController
获取角色的控制旋转输入值。另外, MoveForward
函数将忽略控制旋转输入值的俯仰(Pitch)分量,将输入限制在XY平面上,以确保在你向上或向下看时,你的角色将沿着地面移动。
在
FPSCharacter.cpp
中,将以下行添加到`SetupPlayerInputComponent函数中的
Super::SetupPlayerInputComponent(PlayerInputComponent);` 下方 。// 设置"移动"绑定。 PlayerInputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward); PlayerInputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight);
InputComponent
是定义如何处理输入数据的组件。可以将InputComponent
附加到想要接收输入的actor。在
FPSCharacter.cpp
中,SetupPlayerInputComponent
下方,添加以下MoveForward
函数定义。void AFPSCharacter::MoveForward(float Value) { // 找出"前进"方向,并记录玩家想向该方向移动。 FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::X); AddMovementInput(Direction, Value); }
在
FPSCharacter.cpp
中添加以下MoveRight
函数定义(MoveForward
下方)。void AFPSCharacter::MoveRight(float Value) { // 找出"右侧"方向,并记录玩家想向该方向移动。 FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y); AddMovementInput(Direction, Value); }
现在
FPSCharacter.cpp
的内容应如下所示://版权所有Epic Games, Inc。保留所有权利。 #include "FPSCharacter.h" // 设置默认值 AFPSCharacter::AFPSCharacter() { // 将此角色设置为每帧调用Tick()。 如果不需要此特性,可以关闭以提升性能。 PrimaryActorTick.bCanEverTick = true; } // 当游戏开始或重生(Spawn)时被调用 void AFPSCharacter::BeginPlay() { Super::BeginPlay(); check(GEngine != nullptr); // 显示调试消息五秒。 // -1"键"值参数可以防止更新或刷新消息。 GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("We are using FPSCharacter.")); } // 每一帧都被调用 void AFPSCharacter::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); } // 被调用,将功能与输入绑定 void AFPSCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); // 设置"移动"绑定。 PlayerInputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward); PlayerInputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight); } void AFPSCharacter::MoveForward(float Value) { // 找出"前进"方向,并记录玩家想向该方向移动。 FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::X); AddMovementInput(Direction, Value); } void AFPSCharacter::MoveRight(float Value) { // 找出"右侧"方向,并记录玩家想向该方向移动。 FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y); AddMovementInput(Direction, Value); }
测试角色移动
现在我们来编译和测试新实现的角色移动函数。
在VS中保存
FPSCharacter
头文件(.h)和C++(.cpp)文件。在 解决方案浏览器(Solution Explorer) 中找到 FPSProject。
右键点击 FPSProject 并选择 构建(Build),编译你的项目。
构建完毕后,在虚幻引擎中打开 FPSProject。
在关卡编辑器工具栏中点击 运行(Play)。现在,你应该能够向前、向后、向左和向右移动。
按退出键(Escape)或在关卡编辑器中点击 停止(Stop),退出PIE模式。
2.4 - 实现鼠标摄像机控制
在此步骤中,你将为角色添加能够环顾四周并用鼠标操纵的功能。
转向轴映射
在FPS项目中,展开 编辑(Edit) 菜单,并点击 项目设置(Project Settings)。
在 项目设置(Project Settings) 选项卡左侧的 引擎(Engine) 标题栏下,点击 输入(Input)。
在 绑定(Bindings) 中,点击 轴映射(Axis Mappings) 旁边的+号。
点击 轴映射(Axis Mappings) 左侧的箭头。
在显示的文本输入框中输入"Turn",然后点击文本框左侧的箭头,以便展开轴绑定选项
在下拉菜单中,从 鼠标(Mouse) 下拉列表中选择 鼠标X(Mouse X)。
现在输入设置界面应如下图所示:
查找轴映射
在 绑定(Bindings) 中,点击 轴映射(Axis Mappings) 旁边的+号。
在显示的文本输入框中输入"LookUp",然后点击文本框左侧的箭头,以便展开轴绑定选项。
在下拉菜单中,从 鼠标(Mouse) 下拉列表中选择 鼠标Y(Mouse Y)。
在 鼠标Y(Mouse Y) 旁边的 比例(Scale) 输入框中输入"-1.0"。
现在输入设置界面应如下图所示:
关闭 项目设置(Project Settings) 菜单。
实现输入处理
现在可以添加代码处理鼠标输入以便进行转向和抬头看。角色
基类为我们定义了两个必要函数,即:
AddControllerYawInput
AddControllerPitchInput
如果你想要执行更多的处理,例如增加对灵敏度或轴反转的支持,那么你可以提供自己的函数,以便在将输入值传递给函数之前对其进行调整。但是,在本示例中,你将直接将输入绑定到
AddControllerYawInput
和AddControllerPitchInput
函数。
将以下代码行添加到
FPSCharacter.cpp
中的SetupPlayerInputComponent
函数。// 设置"观看"绑定。 PlayerInputComponent->BindAxis("Turn", this, &AFPSCharacter::AddControllerYawInput); PlayerInputComponent->BindAxis("LookUp", this, &AFPSCharacter::AddControllerPitchInput);
SetupPlayerInputComponent
函数应如下图所示:// 被调用,将功能与输入绑定 void AFPSCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); // 设置"移动"绑定。 PlayerInputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward); PlayerInputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight); // 设置"观看"绑定。 PlayerInputComponent->BindAxis("Turn", this, &AFPSCharacter::AddControllerYawInput); PlayerInputComponent->BindAxis("LookUp", this, &AFPSCharacter::AddControllerPitchInput); }
测试鼠标摄像机控制
在VS中保存
FPSCharacter
的实现文件。在 解决方案浏览器(Solution Explorer) 中找到 FPSProject。
右键点击 FPSProject 并选择 构建(Build),编译你的项目。
构建完毕后,在虚幻引擎中打开 FPSProject。
在关卡编辑器工具栏中点击 运行(Play)。现在,你可以通过鼠标控制摄像机。
按 退出键(Escape key) 或在关卡编辑器中点击 停止(Stop),退出PIE模式。
2.5 - 实现角色跳跃
通常,操作映射处理离散事件的输入,让你可以将输入映射到"友好名称",该名称稍后可以与事件驱动的行为绑定。最终效果是,按下和/或释放单个键、鼠标按钮或辅助键盘按钮可以直接触发游戏行为。在此步骤中,你将为空格键设置输入操作映射,增加角色的跳跃能力。
跳跃操作映射
在 编辑(Edit) 菜单中,点击 项目设置(Project Settings)。
在 项目设置(Project Settings) 选项卡左侧的 引擎(Engine) 标题栏下,点击 输入(Input)。
在 绑定(Bindings) 中,点击 操作映射(Action Mappings) 旁边的+号。
点击 操作映射(Action Mappings) 左侧的箭头。
在显示的文本输入框中输入"Jump",然后点击文本框左侧的箭头,展开操作绑定选项。
在下拉菜单中,从 键盘(Keyboard) 下拉列表中选择 空格键(Space Bar)。
现在输入设置界面应如下图所示:
关闭 项目设置(Project Settings) 菜单。
实现输入处理
如果你查看 Acharacter
基类的接口文件(.h)的内容,你会看到角色跳跃的内置支持。角色跳跃与 bPressedJump
变量绑定,因此我们需要做的就是,在跳跃操作按下时将该布尔值设置为 true
,在跳跃操作释放时将该布尔值设置为 false
。你需要添加以下两个函数完成此操作:
StartJump
StopJump
返回Visual Studio,将代码添加到 FPSCharacter
类。
在
FPSCharacter.h
中,添加以下公共函数声明:// 按下键时,设置跳跃标记。 UFUNCTION() void StartJump(); // 释放键时,清除跳跃标记。 UFUNCTION() void StopJump();
现在
FPSCharacter.h
的内容应如下所示://版权所有Epic Games, Inc。保留所有权利。 #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "FPSCharacter.generated.h" UCLASS() class FPSPROJECT_API AFPSCharacter : public ACharacter { GENERATED_BODY() public: // 为此角色的属性设置默认值 AFPSCharacter(); protected: // 当游戏开始或重生(Spawn)时被调用 virtual void BeginPlay() override; public: // 每一帧都被调用 virtual void Tick( float DeltaTime ) override; // 被调用,将功能与输入绑定 virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; // 处理用于前后移动的输入。 UFUNCTION() void MoveForward(float Value); // 处理用于左右移动的输入。 UFUNCTION() void MoveRight(float Value); // 按下键时,设置跳跃标记。 UFUNCTION() void StartJump(); // 释放键时,清除跳跃标记。 UFUNCTION() void StopJump(); };
在
FPSCharacter.cpp
中,将以下函数定义添加到代码底部:void AFPSCharacter::StartJump() { bPressedJump = true; } void AFPSCharacter::StopJump() { bPressedJump = false; }
现在,将以下代码添加到
SetupPlayerInputComponent
,以便将跳跃操作与刚才编写的函数绑定:// 设置"操作"绑定。 PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AFPSCharacter::StartJump); PlayerInputComponent->BindAction("Jump", IE_Released, this, &AFPSCharacter::StopJump);
现在
FPSCharacter.cpp
的内容应如下所示://版权所有Epic Games, Inc。保留所有权利。 #include "FPSCharacter.h" // 设置默认值 AFPSCharacter::AFPSCharacter() { // 将此角色设置为每帧调用Tick()。 如果不需要此特性,可以关闭以提升性能。 PrimaryActorTick.bCanEverTick = true; } // 当游戏开始或重生(Spawn)时被调用 void AFPSCharacter::BeginPlay() { Super::BeginPlay(); check(GEngine != nullptr); // 显示调试消息五秒。 // -1"键"值参数可以防止更新或刷新消息。 GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("We are using FPSCharacter.")); } // 每一帧都被调用 void AFPSCharacter::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); } // 被调用,将功能与输入绑定 void AFPSCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); // 设置"移动"绑定。 PlayerInputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward); PlayerInputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight); // 设置"观看"绑定。 PlayerInputComponent->BindAxis("Turn", this, &AFPSCharacter::AddControllerYawInput); PlayerInputComponent->BindAxis("LookUp", this, &AFPSCharacter::AddControllerPitchInput); // 设置"操作"绑定。 PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AFPSCharacter::StartJump); PlayerInputComponent->BindAction("Jump", IE_Released, this, &AFPSCharacter::StopJump); } void AFPSCharacter::MoveForward(float Value) { // 找出"前进"方向,并记录玩家想向该方向移动。 FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::X); AddMovementInput(Direction, Value); } void AFPSCharacter::MoveRight(float Value) { // 找出"右侧"方向,并记录玩家想向该方向移动。 FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y); AddMovementInput(Direction, Value); } void AFPSCharacter::StartJump() { bPressedJump = true; } void AFPSCharacter::StopJump() { bPressedJump = false; }
测试角色跳跃
现在我们来编译和测试新实现的角色移动函数。
在VS中保存FPSCharacter 头文件(.h)和C++(.cpp)文件。
在 解决方案浏览器(Solution Explorer) 中找到 FPSProject。
右键点击 FPSProject 并选择 构建(Build),编译你的项目。
构建完毕后,在虚幻引擎中打开 FPSProject。
在关卡编辑器工具栏中点击 运行(Play)。你应该能够在地图上跳跃。
按 退出(Escape) 键或在关卡编辑器中点击 停止(Stop),退出PIE模式。
2.6 - 将网格体添加到角色
通过以下链接下载并提取示例网格体:
在此步骤中,你将为角色提供骨骼网格体。默认情况下,角色类为你创建了SkeletalMeshComponent对象,因此仅需了解使用哪个SkeletalMesh资产。
导入骨骼网格体
导航返回内容浏览器文件框内的内容(Content)文件夹。
现在,右键点击内容浏览器的文件框,打开 导入资产(Import Asset) 对话框。
点击 ‘导入/游戏...(Import to /Game...)',打开 导入(Import) 对话框。
找到并选择 GenericMale.fbx 网格体文件。
点击 打开(Open),开始将网格体导入到你的项目中。
内容浏览器(Content Browser) 中将显示 FBX导入选项(FBX Import Options) 对话框。点击 全部导入(Import All),将你的网格体添加到项目。
点击 保存(Save) 按钮保存导入的网格体。
设置第三人称网格体
在 内容(Content) > 蓝图(Blueprints) 中,双击 BP_FPSCharacter 蓝图类图标,在 蓝图编辑器 中打开它。
如果你看到有关此蓝图为仅数据蓝图的说明,请点击 打开完整蓝图编辑器(Open Full Blueprint Editor)。
在 组件(Components) 选项卡中点击 网格体(Mesh) 组件。
滚动到 细节(Details) 选项卡(屏幕右侧,或在 窗口(Window) > 细节(Details) 中)的 网格体(Mesh) 段。
点击骨骼网格体(Skeletal Mesh)行中显示为"无"的下拉列表,然后选择 GenericMale 骨骼网格体。
滚动到 细节(Details) 窗格中的 变换(Transform) 段,然后,将变换的 Z 轴向位置设置为 "-88.0",使
SkeletalMeshComponent
与CapsuleComponent
对齐。打开视口(Viewport)预览骨骼网格体。骨骼网格体应该如下图所示:
确认骨骼网格体在
CapsuleComponent
内部,并且网格体的朝向与ArrowComponent
相同。正确确定骨骼网格体组件的朝向,将确保你的角色朝正确的方向在整个世界中移动。请确保在关闭 蓝图编辑器(Blueprint Editor) 之前 编译(Compile) 并 保存(Save) BP_FPSCharacter 蓝图。
确认处于PIE模式的新网格体
现在可在编辑器中查看新增网格体。
在关卡编辑器工具栏中点击 运行(Play) 按钮。在你四处移动时,你应该能看到角色的影子。
如果你要在编辑器的视口中查看角色的网格体,请按F8键,使自己从pawn中弹出来。按下F8键后,你将可以在关卡中自由移动摄像机。要移动摄像机,请在移动鼠标的同时按住鼠标左键。
按 退出(Escape) 键或在关卡编辑器中点击 停止(Stop) 按钮,退出在编辑器中运行(Play in Editor)(PIE)模式。
2.7 - 更改摄像机视角
在上一步结束时,默认摄像机放置在网格体的颈部。在此步骤中,你将设置FPS摄像机,这样你可以调整摄像机的属性(例如位置和视野)。
在开始之前,你需要在 FPSCharacter.h
中包含更多的头文件。这将使你的代码可以访问更多与摄像机相关的函数,并最终使你能够操纵摄像机的位置。
打开Visual Studio项目,然后导航至
FPSCharacter.h
。将以下头文件添加到
FPSCharacter.h
:#include "Camera/CameraComponent.h" #include "Components/CapsuleComponent.h"
附加摄像机组件
打开
FPSCharacter.h
,添加以下代码:// FPS摄像机。 UPROPERTY(VisibleAnywhere) UCameraComponent* FPSCameraComponent;
现在
FPSCharacter.h
的内容应如下所示://版权所有Epic Games, Inc。保留所有权利。 #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "Camera/CameraComponent.h" #include "Components/CapsuleComponent.h" #include "FPSCharacter.generated.h" UCLASS() class FPSPROJECT_API AFPSCharacter : public ACharacter { GENERATED_BODY() public: // 为此角色的属性设置默认值 AFPSCharacter(); protected: // 当游戏开始或重生(Spawn)时被调用 virtual void BeginPlay() override; public: // 每一帧都被调用 virtual void Tick( float DeltaTime ) override; // 被调用,将功能与输入绑定 virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; // 处理用于前后移动的输入。 UFUNCTION() void MoveForward(float Value); // 处理用于左右移动的输入。 UFUNCTION() void MoveRight(float Value); // 按下键时,设置跳跃标记。 UFUNCTION() void StartJump(); // 释放键时,清除跳跃标记。 UFUNCTION() void StopJump(); // FPS摄像机 UPROPERTY(VisibleAnywhere) UCameraComponent* FPSCameraComponent; };
打开
FPSCharacter.cpp
,将以下代码添加到构造函数中:PrimaryActorTick.bCanEverTick = true:
。// 创建第一人称摄像机组件。 FPSCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera")); check(FPSCameraComponent != nullptr); // 将摄像机组件附加到我们的胶囊体组件。 FPSCameraComponent->SetupAttachment(CastChecked<USceneComponent, UCapsuleComponent>(GetCapsuleComponent()));
此代码创建
UCameraComponent
,并将其附加到角色的CapsuleComponent
。现在,将以下代码添加到你刚刚在构造函数中编写的代码块下面:
// 将摄像机置于略高于眼睛上方的位置。 FPSCameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 50.0f + BaseEyeHeight)); // 启用Pawn控制摄像机旋转。 FPSCameraComponent->bUsePawnControlRotation = true;
此代码将摄像机的位置调整为略高于角色眼睛的位置,同时允许pawn控制摄像机的旋转。
SetRelativeLocation
用于设置组件的默认值。不过,上一个值仍然会在设置在编辑器中。为纠正这点,请打开蓝图编辑器。点击FPSCameraComponent
,然后在 细节 面板中找到 变换 -> 位置(Transform -> Location) 数值。点击这个值旁边的 重置为默认(Reset to Default)。现在
FPSCharacter.cpp
的内容应如下所示://版权所有Epic Games, Inc。保留所有权利。 #include "FPSCharacter.h" // 设置默认值 AFPSCharacter::AFPSCharacter() { // 将此角色设置为每帧调用Tick()。 如果不需要此特性,可以关闭以提升性能。 PrimaryActorTick.bCanEverTick = true; // 创建第一人称摄像机组件。 FPSCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera")); check(FPSCameraComponent != nullptr); // 将摄像机组件附加到我们的胶囊体组件。 FPSCameraComponent->SetupAttachment(CastChecked<USceneComponent, UCapsuleComponent>(GetCapsuleComponent())); // 将摄像机置于略高于眼睛上方的位置。 FPSCameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 50.0f + BaseEyeHeight)); // 启用Pawn控制摄像机旋转。 FPSCameraComponent->bUsePawnControlRotation = true; } // 当游戏开始或重生(Spawn)时被调用 void AFPSCharacter::BeginPlay() { Super::BeginPlay(); check(GEngine != nullptr) // 显示调试消息五秒。 // -1"键"值(第一个参数)表示我们从不需要更新或刷新此消息。 GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("We are using FPSCharacter.")); } // 每一帧都被调用 void AFPSCharacter::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); } // 被调用,将功能与输入绑定 void AFPSCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); // 设置"移动"绑定。 PlayerInputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward); PlayerInputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight); // 设置"观看"绑定。 PlayerInputComponent->BindAxis("Turn", this, &AFPSCharacter::AddControllerYawInput); PlayerInputComponent->BindAxis("LookUp", this, &AFPSCharacter::AddControllerPitchInput); // 设置"操作"绑定。 PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AFPSCharacter::StartJump); PlayerInputComponent->BindAction("Jump", IE_Released, this, &AFPSCharacter::StopJump); } void AFPSCharacter::MoveForward(float Value) { // 找出"前进"方向,并记录玩家想向该方向移动。 FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::X); AddMovementInput(Direction, Value); } void AFPSCharacter::MoveRight(float Value) { // 找出"右侧"方向,并记录玩家想向该方向移动。 FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y); AddMovementInput(Direction, Value); } void AFPSCharacter::StartJump() { bPressedJump = true; } void AFPSCharacter::StopJump() { bPressedJump = false; }
测试新摄像机
现在我们来编译和测试新实现的摄像机代码。
在Visual Studio中保存
FPSCharacter
头文件(.h)和C++(.cpp)文件。在 解决方案浏览器(Solution Explorer) 中找到 FPSProject。
右键点击 FPSProject 并选择 构建(Build),编译你的项目。
构建完毕后,在虚幻引擎中打开 FPSProject。
在关卡编辑器工具栏中点击 运行(Play)。
现在,摄像机应该略高于角色的头部。
你还可以通过打开BP_FPSCharacter视口来确认新添加的摄像机组件。
2.8-将第一人称网格体添加到你的角色
构建FPS游戏的常见方法是使用两个分开的角色网格体,其中一个是全身网格体,另一个是"武器和手部"网格体。全身网格体用于从第三人称视角观察角色。但是,当玩家以第一人称视角进行游戏时,全身网格体是隐藏的。"武器和手部"网格体通常附着到摄像机,并且仅当玩家以第一人称视角查看地图时才对玩家可见。在此步骤中,你将向角色添加第一人称网格体。
添加第一人称角色网格体
切换回Visual Studio并打开
FPSCharacter.h
,在 public: 下添加以下代码:// 第一人称网格体(手臂),仅对所属玩家可见。 UPROPERTY(VisibleDefaultsOnly, Category = Mesh) USkeletalMeshComponent* FPSMesh;
现在,打开
FPSCharacter.cpp
,找到构造函数,添加以下代码,创建和配置第一人称网格体:// 为所属玩家创建第一人称网格体组件。 FPSMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("FirstPersonMesh")); check(FPSMesh != nullptr); // 仅所属玩家可以看见此网格体。 FPSMesh->SetOnlyOwnerSee(true); // 将 FPS 网格体附加到 FPS 摄像机。 FPSMesh->SetupAttachment(FPSCameraComponent); // 禁用某些环境阴影以便实现只有单个网格体的感觉。 FPSMesh->bCastDynamicShadow = false; FPSMesh->CastShadow = false;
SetOnlyOwnerSee
表示此网格体仅对拥有此角色的PlayerController
可见。此代码还将网格体附加到摄像机,并禁用某些环境阴影。让手臂投射阴影会破坏第一人称角色应该只有单个网格体的感觉。最后,将以下代码添加到FPSCharacter.cpp的构造函数中,以便隐藏所属角色的现有第三人称网格体:
// 所属玩家看不到常规(第三人称)全身网格体。 GetMesh()->SetOwnerNoSee(true);
在Visual Studio中保存FPSCharacter头文件(.h)和实现(.cpp)文件。
在 解决方案浏览器(Solution Explorer) 中找到 FPSProject。
右键点击 FPSProject 并选择 构建(Build),编译你的项目。
构建完成后,打开并以PIE模式运行 FPSProject。
此时,你的角色网格体在编辑器中应该不可见。
如果你仍然看到网格体及其阴影投射,请关闭并重新启动编辑器。
构建网格体蓝图
在继续之前,请通过以下链接下载并提取示例网格体: "第一人称骨骼网格体"
右键点击内容浏览器的文件框,打开 导入资产(Import Asset) 对话框。
点击 导入/游戏...(Import to /Game...),打开 导入(Import) 对话框。
找到并选择 HeroFPP.fbx 网格体文件。
点击 打开(Open),开始将网格体导入到你的项目中。
内容浏览器(Content Browser) 中将显示 FBX导入选项(FBX Import Options) 对话框。
请确保将 骨架(Skeleton) 设置为 无(None),然后点击 全部导入(Import All)。
关闭以下消息日志。
此网格体仍展示第一人称网格体设置,它将与你在后面分段中设置的动画一起使用。
点击 保存(Save),保存导入的网格体。
导航返回 内容浏览器(Content Browser) 中的 蓝图(Blueprints) 文件夹。
双击 BP_FPSCharacter 图标,在 蓝图编辑器 中打开它。
在 组件(Components) 选项卡中找到新的 FPSMesh 组件。首先,你可能需要打开 完整的蓝图编辑器。
FPSMesh 组件是 FPSCameraComponent 组件的子项,这意味着它将始终附加到摄像机。
在 组件(Components) 菜单中点击 FPSMesh。
滚动到 细节(Details) 选项卡的 网格体(Mesh) 段,然后点击显示为"无(None)"的下拉菜单。现在,选择 HeroFPP 骨骼网格体,将手臂添加到 视口(Viewport)。
在 视口(Viewport) 中,新增的 HeroFPP 骨骼网格体应如下图所示。
将新增网格体的变换属性调整为在摄像机前面:将其 位置(Location) 设置为{220, 0, 35},将其 旋转(Rotation) 设置为{180, 50, 180}。
请确保在关闭 蓝图编辑器(Blueprint Editor) 之前 编译(Compile) 并 保存(Save) BP_FPSCharacter 蓝图。
在游戏中查看新网格体
点击 关卡编辑器工具栏 中的 运行(Play) 按钮**,在游戏中查看新网格体。
按 退出(Escape) 键或在关卡编辑器中点击 停止(Stop) 按钮,退出在编辑器中运行(Play in Editor)(PIE)模式。
已完成分段代码
FPSCharacter.h
//版权所有Epic Games, Inc。保留所有权利。
#pragma once
#include "GameFramework/Character.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "FPSCharacter.generated.h"
UCLASS()
class FPSPROJECT_API AFPSCharacter : public ACharacter
{
GENERATED_BODY()
public:
// 为此角色的属性设置默认值
AFPSCharacter();
protected:
// 当游戏开始或重生(Spawn)时被调用
virtual void BeginPlay() override;
public:
// 每一帧都被调用
virtual void Tick( float DeltaTime ) override;
// 被调用,将功能与输入绑定
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
// 处理用于前后移动的输入。
UFUNCTION()
void MoveForward(float Value);
// 处理用于左右移动的输入。
UFUNCTION()
void MoveRight(float Value);
// 按下键时,设置跳跃标记。
UFUNCTION()
void StartJump();
// 释放键时,清除跳跃标记。
UFUNCTION()
void StopJump();
// FPS摄像机
UPROPERTY(VisibleAnywhere)
UCameraComponent* FPSCameraComponent;
// 第一人称网格体(手臂),仅对所属玩家可见。
UPROPERTY(VisibleDefaultsOnly, Category = Mesh)
USkeletalMeshComponent* FPSMesh;
};
FPSCharacter.cpp
//版权所有Epic Games, Inc。保留所有权利。
#include "FPSCharacter.h"
// 设置默认值
AFPSCharacter::AFPSCharacter()
{
// 将此角色设置为每帧调用Tick()。 如果不需要此特性,可以关闭以提升性能。
PrimaryActorTick.bCanEverTick = true;
// 创建第一人称摄像机组件。
FPSCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
check(FPSCameraComponent != nullptr);
// 将摄像机组件附加到我们的胶囊体组件。
FPSCameraComponent->SetupAttachment(CastChecked<USceneComponent>(GetCapsuleComponent()));
// 将摄像机置于略高于眼睛上方的位置。
FPSCameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 50.0f + BaseEyeHeight));
// 启用Pawn控制摄像机旋转。
FPSCameraComponent->bUsePawnControlRotation = true;
// 为所属玩家创建第一人称网格体组件。
FPSMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("FirstPersonMesh"));
check(FPSMesh != nullptr);
// 仅所属玩家可以看见此网格体。
FPSMesh->SetOnlyOwnerSee(true);
// 将 FPS 网格体附加到 FPS 摄像机。
FPSMesh->SetupAttachment(FPSCameraComponent);
// 禁用某些环境阴影以便实现只有单个网格体的感觉。
FPSMesh->bCastDynamicShadow = false;
FPSMesh->CastShadow = false;
// 所属玩家看不到常规(第三人称)全身网格体。
GetMesh()->SetOwnerNoSee(true);
}
// 当游戏开始或重生(Spawn)时被调用
void AFPSCharacter::BeginPlay()
{
Super::BeginPlay();
check(GEngine != nullptr);
// 显示调试消息五秒。
// -1"键"值参数可以防止更新或刷新消息。
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("We are using FPSCharacter."));
}
// 每一帧都被调用
void AFPSCharacter::Tick( float DeltaTime )
{
Super::Tick( DeltaTime );
}
// 被调用,将功能与输入绑定
void AFPSCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
// 设置"移动"绑定。
PlayerInputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight);
// 设置"观看"绑定。
PlayerInputComponent->BindAxis("Turn", this, &AFPSCharacter::AddControllerYawInput);
PlayerInputComponent->BindAxis("LookUp", this, &AFPSCharacter::AddControllerPitchInput);
// 设置"操作"绑定。
PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AFPSCharacter::StartJump);
PlayerInputComponent->BindAction("Jump", IE_Released, this, &AFPSCharacter::StopJump);
}
void AFPSCharacter::MoveForward(float Value)
{
// 找出"前进"方向,并记录玩家想向该方向移动。
FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::X);
AddMovementInput(Direction, Value);
}
void AFPSCharacter::MoveRight(float Value)
{
// 找出"右侧"方向,并记录玩家想向该方向移动。
FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y);
AddMovementInput(Direction, Value);
}
void AFPSCharacter::StartJump()
{
bPressedJump = true;
}
void AFPSCharacter::StopJump()
{
bPressedJump = false;
}
祝贺你!你已经学会了如何:
✓ 制作新角色
✓ 设置轴映射
✓ 实现角色移动函数
✓ 实现鼠标摄像机控制
✓ 实现角色跳跃
✓ 将网格体添加到角色
✓ 更改摄像机视角
✓ 将第一人称网格体添加到角色
现在,你可以准备在下一分段中学习如何实现发射物。