2 - 实现你的角色

如何实现第一人称射击角色。

Choose your operating system:

Windows

macOS

Linux

前置主题

为了能够理解并使用此页面中的内容,请确保您已掌握以下主题:

Section0208.gif

这就是你将在本分段结束时看到的内容。

目标

本分段旨在向你展示如何实现第一人称射击角色。

目的

完成本教程的此分段,你便能够:

  • 创建新角色

  • 设置轴映射

  • 实现角色移动函数

  • 实现鼠标摄像机控制

  • 实现角色跳跃

  • 将网格体添加到角色

  • 更改摄像机视角

  • 将第一人称网格体添加到角色

步骤

  • 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++类向导,引擎可创建头文件和源文件模板,这些模板文件将为你预先设置一些虚幻特定的宏。

  1. 在UE中启动FPS项目(如果你尚未完成此操作)。

  2. 在文件(File)菜单中,选择 新建C++类...(New C++ Class...) ,以选择新的父类。

    SelectNewCPPClass.png

  3. 以上操作将打开 选择父类(Choose Parent Class) 菜单。向下滚动,选择 角色 作为父类,然后点击 下一步(Next)

    ChooseCharacterClass.png

  4. 将新类命名为"FPSCharacter",然后点击 创建类(Create Class)

    MakeFPSCharacterClass.png

确认角色类

  1. 在VS的 解决方案浏览器 中,依次展开 FPSProject > 源(Source) > FPSProject

    ExpandedSolutionExplorer.png

  2. 点击 FPSCharacter.cpp ,打开 FPSCharacter 类的实现文件。

  3. BeginPlay() 函数中添加以下代码行(在 Super::BeginPlay(); 下面),以便确认正在使用 FPSCharacter 类:

    check(GEngine != nullptr);
    
    // 显示调试消息五秒。 
    // -1"键"值参数可以防止更新或刷新消息。
    GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("We are using FPSCharacter."));
  4. 现在 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);
    
    }
  5. 在Visual Studio中保存 FPSCharacter CPP文件。

  6. 解决方案浏览器(Solution Explorer) 中找到 FPSProject

    到目前为止,你一直在使用编辑器的 构建(Build) 按钮编译项目。在此步骤中,你将使用Visual Studio的构建功能来编译代码。要从Visual Studio中编译代码,请右键点击 FPSProject ,并选择 构建(Build) 来编译项目。

  7. 要从VS中编译代码,请右键点击 FPSProject ,并选择 构建(Build) 来编译项目。

    BuildProject.png

    如果你使用的是VS的默认设置,则在界面底部附近(可能在代码编辑器的下方),你应该会看到一个对话框。当你点击构建(Build)后,在生成过程中该对话框中应该会显示一些信息,我们最希望显示的是构建成功的信息。 如果构建失败,不要紧张!回头看看你之前的操作步骤,确保你的代码与此处和第1分段中列出的内容相同。

  8. 构建完成后,打开虚幻编辑器,确认新编译的 FPSCharacter 类在 内容浏览器 中可见。

    FPSCharacterContentBrowser.png

扩展你的C++ FPS角色类到蓝图

现在可以扩展C++ FPS角色类到蓝图了(类似之前进行的FPSProject游戏模式操作)。请随时前往我们的 C++和蓝图 参考页面,以了解更多关于扩展C++类到蓝图的信息。

  1. 右键点击FPSCharacter类,打开 C++类操作(C++ Class Actions) 菜单。

  2. 点击 基于FPSCharacter创建蓝图类(Create Blueprint class based on FPSHUD) ,打开 添加蓝图类(Add Blueprint Class) 对话框菜单。

    CreateDerivedBPClass.png

  3. 将新的蓝图类命名为 BP_FPSCharacter ,选择蓝图(Blueprints)文件夹,然后点击 创建蓝图类(Create Blueprint Class) 按钮。

    AddBPClass.png

  4. 现在,在蓝图(Blueprints)文件夹内,你应该可以看到新创建的 BP_FPSCharacter 蓝图类。

    AddedBPClass.png

  5. 请确保在关闭蓝图编辑器前保存 BP_FPSCharacter 蓝图。

设置默认的Pawn类

现在你已经成功地把新修改的游戏模式扩展到了蓝图,接下来你需要在此步骤中设置项目,将 BP_FPSCharacter 作为默认的 Pawn

  1. 编辑(Edit) 菜单中点击 项目设置(Project Settings)

  2. 项目设置(Project Settings) 选项卡左侧的 项目(Project) 标题栏下,点击 地图和模式(Maps & Modes)

  3. 展开 已选择的游戏模式(Selected GameMode) 段,并在 默认Pawn类(Default Pawn Class) 下拉菜单中选择 BP_FPSCharacter

    SettingFPSCharacter.png

  4. 关闭 项目设置(Project Settings) 菜单。

  5. 在关卡编辑器工具栏中点击 运行(Play) 按钮。在视口左上角,红色文本"We are using FPSCharacter."将显示在"Hello World, this is FPSGameMode!"的下方,并持续5秒钟。

    VerifyingFPSCharacterResult.png

    如果你无法移动,说明你已经正确地将FPSCharacter用作了Pawn!你的新角色还没有任何移动功能按钮,因此你还不能在关卡中四处移动。

  6. 在进入下一步前,按退出键(Escape)或在关卡编辑器中点击 停止(Stop) ,退出在编辑器中运行(Play in Editor)(PIE)模式。

2.2 - 设置轴映射

通常,轴映射支持将键盘、鼠标和控制器输入映射到"友好名称",该名称稍后可以绑定到游戏行为上(例如移动)。轴映射会不断被轮询,从而实现无缝的移动过渡和流畅的游戏行为。硬件轴(例如游戏摇杆)所提供的输入值为程度值,而不是离散的数字输入(例如,按下为1,不按下为0)。虽然游戏摇杆输入方法在提供可平滑伸缩的移动输入方面很有效,但轴映射也可以将常见的移动键(如WASD键或箭头键)映射到持续轮询的游戏行为。

在继续此步骤之前,如果你想要了解有关玩家输入的更多信息,请参阅 玩家输入和Pawn 教程。在此步骤中,你将设置W、A、S和D键的输入轴映射,从而使新角色可以在地图上四处移动。

向前移动轴映射

  1. 编辑(Edit) 菜单中,点击 项目设置(Project Settings)

  2. 项目设置(Project Settings) 选项卡左侧的 引擎(Engine) 标题栏下,点击 输入(Input)

  3. 绑定(Bindings) 中,点击 轴映射(Axis Mappings) 旁边的+号。

  4. 点击 轴映射(Axis Mappings) 左侧的箭头。

  5. 在界面显示的文本框中输入"MoveForward",然后点击文本框左侧的箭头,展开轴绑定选项。

  6. 在下拉菜单中,从 键盘(Keyboard) 下拉列表中选择 W

  7. 现在输入设置界面应如下图所示:

    MoveForwardAxisMap_W.png

  8. 点击 MoveForward 旁边的+号。

  9. 在第二个下拉菜单中,从 键盘(Keyboard) 下拉列表中选择 S

  10. S 旁边的 比例(Scale) 字段中输入"-1"。

  11. 现在输入设置界面应如下图所示:

    MoveForwardAxisMap_S.png

向右移动轴映射

  1. 绑定(Bindings) 中,点击 轴映射(Axis Mappings) 旁边的+号。

  2. 在显示的文本字段中输入"向右移动(MoveForward)",然后点击文本框左侧的箭头,展开轴绑定选项。

  3. 在下拉菜单中,从 键盘(Keyboard) 下拉列表中选择 D

  4. 现在输入设置界面应如下图所示:

    MoveRightAxisMap_D.png

  5. 点击 向右移动(MoveRight) 旁边的+号。

  6. 在第二个下拉菜单中,从 键盘(Keyboard) 下拉列表中选择 A

  7. A 旁边的 比例(Scale) 字段中输入"-1"。

  8. 现在输入设置界面应如下图所示:

    MoveRightAxisMap_A.png

  9. 现在你已设置好向左移动(MoveLeft)和向右移动(MoveRight)轴映射,请关闭 项目设置(Project Settings) 菜单并继续。

2.3 - 实现角色移动函数

在此步骤中,我们将设置玩家输入组件,并在FPSCharacter类中实现以下函数:

  • MoveForward

  • MoveRight

移动函数接口

你已经设置好FPSCharacter的轴映射,现在可以切换到VS中的项目界面。

  1. FPSCharacter.h 中,将以下函数声明添加到 SetupPlayerInputComponent 成员函数的下方。

    // 处理用于前后移动的输入。
    UFUNCTION()
    void MoveForward(float Value);
    
    // 处理用于左右移动的输入。
    UFUNCTION()
    void MoveRight(float Value);

    UFUNCTION 宏(位于每个函数上方)让引擎可以发觉这些函数,以便将它们纳入序列化和其他引擎功能中。

  2. 现在 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平面上,以确保在你向上或向下看时,你的角色将沿着地面移动。

  1. FPSCharacter.cpp 中,将以下行添加到`SetupPlayerInputComponent 函数中的 Super::SetupPlayerInputComponent(PlayerInputComponent);` 下方 。

    // 设置"移动"绑定。
    PlayerInputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward);
    PlayerInputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight);

    InputComponent 是定义如何处理输入数据的组件。可以将 InputComponent 附加到想要接收输入的actor。

  2. FPSCharacter.cpp 中, SetupPlayerInputComponent 下方,添加以下 MoveForward 函数定义。

    void AFPSCharacter::MoveForward(float Value)
    {
        // 找出"前进"方向,并记录玩家想向该方向移动。
        FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::X);
        AddMovementInput(Direction, Value);
    }
  3. FPSCharacter.cpp 中添加以下 MoveRight 函数定义( MoveForward 下方)。

    void AFPSCharacter::MoveRight(float Value)
    {
        // 找出"右侧"方向,并记录玩家想向该方向移动。
        FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y);
        AddMovementInput(Direction, Value);
    }
  4. 现在 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);
    }

测试角色移动

现在我们来编译和测试新实现的角色移动函数。

  1. 在VS中保存 FPSCharacter 头文件(.h)和C++(.cpp)文件。

  2. 解决方案浏览器(Solution Explorer) 中找到 FPSProject

  3. 右键点击 FPSProject 并选择 构建(Build) ,编译你的项目。

    BuildProject.png

  4. 构建完毕后,在虚幻引擎中打开 FPSProject

  5. 在关卡编辑器工具栏中点击 运行(Play) 。现在,你应该能够向前、向后、向左和向右移动。

  6. 按退出键(Escape)或在关卡编辑器中点击 停止(Stop) ,退出PIE模式。

2.4 - 实现鼠标摄像机控制

在此步骤中,你将为角色添加能够环顾四周并用鼠标操纵的功能。

转向轴映射

  1. 在FPS项目中,展开 编辑(Edit) 菜单,并点击 项目设置(Project Settings)

  2. 项目设置(Project Settings) 选项卡左侧的 引擎(Engine) 标题栏下,点击 输入(Input)

  3. 绑定(Bindings) 中,点击 轴映射(Axis Mappings) 旁边的+号。

  4. 点击 轴映射(Axis Mappings) 左侧的箭头。

  5. 在显示的文本输入框中输入"Turn",然后点击文本框左侧的箭头,以便展开轴绑定选项

  6. 在下拉菜单中,从 鼠标(Mouse) 下拉列表中选择 鼠标X(Mouse X)

  7. 现在输入设置界面应如下图所示:

    TurnAxisMapping_MouseX.png

查找轴映射

  1. 绑定(Bindings) 中,点击 轴映射(Axis Mappings) 旁边的+号。

  2. 在显示的文本输入框中输入"LookUp",然后点击文本框左侧的箭头,以便展开轴绑定选项。

  3. 在下拉菜单中,从 鼠标(Mouse) 下拉列表中选择 鼠标Y(Mouse Y)

  4. 鼠标Y(Mouse Y) 旁边的 比例(Scale) 输入框中输入"-1.0"。

  5. 现在输入设置界面应如下图所示:

    TurnAxisMapping_MouseY.png

  6. 关闭 项目设置(Project Settings) 菜单。

实现输入处理

现在可以添加代码处理鼠标输入以便进行转向和抬头看。 角色 基类为我们定义了两个必要函数,即:

  • AddControllerYawInput

  • AddControllerPitchInput

    如果你想要执行更多的处理,例如增加对灵敏度或轴反转的支持,那么你可以提供自己的函数,以便在将输入值传递给函数之前对其进行调整。但是,在本示例中,你将直接将输入绑定到 AddControllerYawInput AddControllerPitchInput 函数。

  1. 将以下代码行添加到 FPSCharacter.cpp 中的 SetupPlayerInputComponent 函数。

    // 设置"观看"绑定。
    PlayerInputComponent->BindAxis("Turn", this, &AFPSCharacter::AddControllerYawInput);
    PlayerInputComponent->BindAxis("LookUp", this, &AFPSCharacter::AddControllerPitchInput);
  2. 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);
    }

测试鼠标摄像机控制

  1. 在VS中保存 FPSCharacter 的实现文件。

  2. 解决方案浏览器(Solution Explorer) 中找到 FPSProject

  3. 右键点击 FPSProject 并选择 构建(Build) ,编译你的项目。

  4. 构建完毕后,在虚幻引擎中打开 FPSProject

  5. 在关卡编辑器工具栏中点击 运行(Play) 。现在,你可以通过鼠标控制摄像机。

  6. 退出键(Escape key) 或在关卡编辑器中点击 停止(Stop) ,退出PIE模式。

2.5 - 实现角色跳跃

通常,操作映射处理离散事件的输入,让你可以将输入映射到"友好名称",该名称稍后可以与事件驱动的行为绑定。最终效果是,按下和/或释放单个键、鼠标按钮或辅助键盘按钮可以直接触发游戏行为。在此步骤中,你将为空格键设置输入操作映射,增加角色的跳跃能力。

跳跃操作映射

  1. 编辑(Edit) 菜单中,点击 项目设置(Project Settings)

  2. 项目设置(Project Settings) 选项卡左侧的 引擎(Engine) 标题栏下,点击 输入(Input)

  3. 绑定(Bindings) 中,点击 操作映射(Action Mappings) 旁边的+号。

  4. 点击 操作映射(Action Mappings) 左侧的箭头。

  5. 在显示的文本输入框中输入"Jump",然后点击文本框左侧的箭头,展开操作绑定选项。

  6. 在下拉菜单中,从 键盘(Keyboard) 下拉列表中选择 空格键(Space Bar)

  7. 现在输入设置界面应如下图所示:

    JumpActionMapping_SpaceBar.png

  8. 关闭 项目设置(Project Settings) 菜单。

实现输入处理

如果你查看 Acharacter 基类的接口文件(.h)的内容,你会看到角色跳跃的内置支持。角色跳跃与 bPressedJump 变量绑定,因此我们需要做的就是,在跳跃操作按下时将该布尔值设置为 true ,在跳跃操作释放时将该布尔值设置为 false 。你需要添加以下两个函数完成此操作:

  • StartJump

  • StopJump

返回Visual Studio,将代码添加到 FPSCharacter 类。

  1. FPSCharacter.h 中,添加以下公共函数声明:

    // 按下键时,设置跳跃标记。
    UFUNCTION()
    void StartJump();
    
    // 释放键时,清除跳跃标记。
    UFUNCTION()
    void StopJump();
  2. 现在 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();
    };
  3. FPSCharacter.cpp 中,将以下函数定义添加到代码底部:

    void AFPSCharacter::StartJump()
    {
        bPressedJump = true;
    }
    
    void AFPSCharacter::StopJump()
    {
        bPressedJump = false;
    }
  4. 现在,将以下代码添加到 SetupPlayerInputComponent ,以便将跳跃操作与刚才编写的函数绑定:

    // 设置"操作"绑定。
    PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AFPSCharacter::StartJump);
    PlayerInputComponent->BindAction("Jump", IE_Released, this, &AFPSCharacter::StopJump);
  5. 现在 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;
    }

测试角色跳跃

现在我们来编译和测试新实现的角色移动函数。

  1. 在VS中保存FPSCharacter 头文件(.h)和C++(.cpp)文件。

  2. 解决方案浏览器(Solution Explorer) 中找到 FPSProject

  3. 右键点击 FPSProject 并选择 构建(Build) ,编译你的项目。

  4. 构建完毕后,在虚幻引擎中打开 FPSProject

  5. 在关卡编辑器工具栏中点击 运行(Play) 。你应该能够在地图上跳跃。

  6. 退出(Escape) 键或在关卡编辑器中点击 停止(Stop) ,退出PIE模式。

2.6 - 将网格体添加到角色

通过以下链接下载并提取示例网格体:

在此步骤中,你将为角色提供骨骼网格体。默认情况下,角色类为你创建了SkeletalMeshComponent对象,因此仅需了解使用哪个SkeletalMesh资产。

导入骨骼网格体

  1. 导航返回内容浏览器文件框内的内容(Content)文件夹。

  2. 现在,右键点击内容浏览器的文件框,打开 导入资产(Import Asset) 对话框。

  3. 点击 ‘导入/游戏...(Import to /Game...)' ,打开 导入(Import) 对话框。

  4. 找到并选择 GenericMale.fbx 网格体文件。

  5. 点击 打开(Open) ,开始将网格体导入到你的项目中。

  6. 内容浏览器(Content Browser) 中将显示 FBX导入选项(FBX Import Options) 对话框。点击 全部导入(Import All) ,将你的网格体添加到项目。

    ImportGenericMale.png

  7. 点击 保存(Save) 按钮保存导入的网格体。

设置第三人称网格体

  1. 内容(Content) > 蓝图(Blueprints) 中,双击 BP_FPSCharacter 蓝图类图标,在 蓝图编辑器 中打开它。

    如果你看到有关此蓝图为仅数据蓝图的说明,请点击 打开完整蓝图编辑器(Open Full Blueprint Editor)

  2. 组件(Components) 选项卡中点击 网格体(Mesh) 组件。

    MeshComponent.png

  3. 滚动到 细节(Details) 选项卡(屏幕右侧,或在 窗口(Window) > 细节(Details) 中)的 网格体(Mesh) 段。

  4. 点击骨骼网格体(Skeletal Mesh)行中显示为"无"的下拉列表,然后选择 GenericMale 骨骼网格体。

    SelectSkeletalMesh.png

  5. 滚动到 细节(Details) 窗格中的 变换(Transform) 段,然后,将变换的 Z 轴向位置设置为 "-88.0" ,使 SkeletalMeshComponent CapsuleComponent 对齐。

    NewZLoc_Mesh.png

  6. 打开视口(Viewport)预览骨骼网格体。骨骼网格体应该如下图所示:

    SkeletalMeshLocation.png

    确认骨骼网格体在 CapsuleComponent 内部,并且网格体的朝向与 ArrowComponent 相同。正确确定骨骼网格体组件的朝向,将确保你的角色朝正确的方向在整个世界中移动。

  7. 请确保在关闭 蓝图编辑器(Blueprint Editor) 之前 编译(Compile) 保存(Save) BP_FPSCharacter 蓝图。

确认处于PIE模式的新网格体

现在可在编辑器中查看新增网格体。

  1. 在关卡编辑器工具栏中点击 运行(Play) 按钮。在你四处移动时,你应该能看到角色的影子。

    PawnwithShadow.png

    Section0206.gif

    如果你要在编辑器的视口中查看角色的网格体,请按F8键,使自己从pawn中弹出来。按下F8键后,你将可以在关卡中自由移动摄像机。要移动摄像机,请在移动鼠标的同时按住鼠标左键。

    FreelyMovingCamera.png

  2. 退出(Escape) 键或在关卡编辑器中点击 停止(Stop) 按钮,退出在编辑器中运行(Play in Editor)(PIE)模式。

2.7 - 更改摄像机视角

在上一步结束时,默认摄像机放置在网格体的颈部。在此步骤中,你将设置FPS摄像机,这样你可以调整摄像机的属性(例如位置和视野)。 在开始之前,你需要在 FPSCharacter.h 中包含更多的头文件。这将使你的代码可以访问更多与摄像机相关的函数,并最终使你能够操纵摄像机的位置。

  1. 打开Visual Studio项目,然后导航至 FPSCharacter.h

  2. 将以下头文件添加到 FPSCharacter.h

    #include "Camera/CameraComponent.h"
    #include "Components/CapsuleComponent.h"

附加摄像机组件

  1. 打开 FPSCharacter.h ,添加以下代码:

    // FPS摄像机。
    UPROPERTY(VisibleAnywhere)
    UCameraComponent* FPSCameraComponent;
  2. 现在 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;
    };
  3. 打开 FPSCharacter.cpp ,将以下代码添加到构造函数中: PrimaryActorTick.bCanEverTick = true:

    // 创建第一人称摄像机组件。
    FPSCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
    check(FPSCameraComponent != nullptr);
    
    // 将摄像机组件附加到我们的胶囊体组件。
    FPSCameraComponent->SetupAttachment(CastChecked<USceneComponent, UCapsuleComponent>(GetCapsuleComponent()));

    此代码创建 UCameraComponent ,并将其附加到角色的 CapsuleComponent

  4. 现在,将以下代码添加到你刚刚在构造函数中编写的代码块下面:

    // 将摄像机置于略高于眼睛上方的位置。
    FPSCameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 50.0f + BaseEyeHeight));
    
    // 启用Pawn控制摄像机旋转。
    FPSCameraComponent->bUsePawnControlRotation = true;

    此代码将摄像机的位置调整为略高于角色眼睛的位置,同时允许pawn控制摄像机的旋转。

    SetRelativeLocation 用于设置组件的默认值。不过,上一个值仍然会在设置在编辑器中。为纠正这点,请打开蓝图编辑器。点击 FPSCameraComponent ,然后在 细节 面板中找到 变换 -> 位置(Transform -> Location) 数值。点击这个值旁边的 重置为默认(Reset to Default)

  5. 现在 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;
    }

测试新摄像机

现在我们来编译和测试新实现的摄像机代码。

  1. 在Visual Studio中保存 FPSCharacter 头文件(.h)和C++(.cpp)文件。

  2. 解决方案浏览器(Solution Explorer) 中找到 FPSProject

  3. 右键点击 FPSProject 并选择 构建(Build) ,编译你的项目。

  4. 构建完毕后,在虚幻引擎中打开 FPSProject

  5. 在关卡编辑器工具栏中点击 运行(Play)

现在,摄像机应该略高于角色的头部。

你还可以通过打开BP_FPSCharacter视口来确认新添加的摄像机组件。 NewCameraComponent.png

NewCameraPosition.png

2.8-将第一人称网格体添加到你的角色

构建FPS游戏的常见方法是使用两个分开的角色网格体,其中一个是全身网格体,另一个是"武器和手部"网格体。全身网格体用于从第三人称视角观察角色。但是,当玩家以第一人称视角进行游戏时,全身网格体是隐藏的。"武器和手部"网格体通常附着到摄像机,并且仅当玩家以第一人称视角查看地图时才对玩家可见。在此步骤中,你将向角色添加第一人称网格体。

添加第一人称角色网格体

  1. 切换回Visual Studio并打开 FPSCharacter.h ,在 public: 下添加以下代码:

    // 第一人称网格体(手臂),仅对所属玩家可见。
    UPROPERTY(VisibleDefaultsOnly, Category = Mesh)
    USkeletalMeshComponent* FPSMesh;
  2. 现在,打开 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 可见。此代码还将网格体附加到摄像机,并禁用某些环境阴影。让手臂投射阴影会破坏第一人称角色应该只有单个网格体的感觉。

  3. 最后,将以下代码添加到FPSCharacter.cpp的构造函数中,以便隐藏所属角色的现有第三人称网格体:

    // 所属玩家看不到常规(第三人称)全身网格体。
    GetMesh()->SetOwnerNoSee(true);
  4. 在Visual Studio中保存FPSCharacter头文件(.h)和实现(.cpp)文件。

  5. 解决方案浏览器(Solution Explorer) 中找到 FPSProject

  6. 右键点击 FPSProject 并选择 构建(Build) ,编译你的项目。

  7. 构建完成后,打开并以PIE模式运行 FPSProject

    HiddenMeshInGame.png

此时,你的角色网格体在编辑器中应该不可见。

如果你仍然看到网格体及其阴影投射,请关闭并重新启动编辑器。

构建网格体蓝图

在继续之前,请通过以下链接下载并提取示例网格体: "第一人称骨骼网格体"

  1. 右键点击内容浏览器的文件框,打开 导入资产(Import Asset) 对话框。

  2. 点击 导入/游戏...(Import to /Game...) ,打开 导入(Import) 对话框。

    RightClickImport.png

  3. 找到并选择 HeroFPP.fbx 网格体文件。

  4. 点击 打开(Open) ,开始将网格体导入到你的项目中。

  5. 内容浏览器(Content Browser) 中将显示 FBX导入选项(FBX Import Options) 对话框。

  6. 请确保将 骨架(Skeleton) 设置为 无(None) ,然后点击 全部导入(Import All)

    ClearSkeletonMesh.png

  7. 关闭以下消息日志。

    FBXWarning.png

    此网格体仍展示第一人称网格体设置,它将与你在后面分段中设置的动画一起使用。

  8. 点击 保存(Save) ,保存导入的网格体。

  9. 导航返回 内容浏览器(Content Browser) 中的 蓝图(Blueprints) 文件夹。

  10. 双击 BP_FPSCharacter 图标,在 蓝图编辑器 中打开它。

  11. 组件(Components) 选项卡中找到新的 FPSMesh 组件。首先,你可能需要打开 完整的蓝图编辑器

    LocateFPSMeshComponent.png

    FPSMesh 组件是 FPSCameraComponent 组件的子项,这意味着它将始终附加到摄像机。

  12. 组件(Components) 菜单中点击 FPSMesh

  13. 滚动到 细节(Details) 选项卡的 网格体(Mesh) 段,然后点击显示为"无(None)"的下拉菜单。现在,选择 HeroFPP 骨骼网格体,将手臂添加到 视口(Viewport)

    SelectHeroFPPSkeletalMesh.png

  14. 视口(Viewport) 中,新增的 HeroFPP 骨骼网格体应如下图所示。

    HeroFPPMesh_Viewport.png

  15. 将新增网格体的变换属性调整为在摄像机前面:将其 位置(Location) 设置为{220, 0, 35},将其 旋转(Rotation) 设置为{180, 50, 180}。

    点击查看大图。

  16. 请确保在关闭 蓝图编辑器(Blueprint Editor) 之前 编译(Compile) 保存(Save) BP_FPSCharacter 蓝图。

在游戏中查看新网格体

  1. 点击 关卡编辑器工具栏 中的 运行(Play) 按钮**,在游戏中查看新网格体。

    Section0208.gif

  2. 退出(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;
    }

祝贺你!你已经学会了如何:

✓ 制作新角色
✓ 设置轴映射
✓ 实现角色移动函数
✓ 实现鼠标摄像机控制
✓ 实现角色跳跃
✓ 将网格体添加到角色
✓ 更改摄像机视角
✓ 将第一人称网格体添加到角色

现在,你可以准备在下一分段中学习如何实现发射物。

欢迎帮助改进虚幻引擎文档!请告诉我们该如何更好地为您服务。
填写问卷调查
取消