在本教程中,你将创建一个角色并设置其输入。之后,你将为该人物指定一个游戏模式,以便该人物作为游戏过程中的默认Pawn。创建好人物后,你需要定义其如何对玩家输入做出反应。
虚幻引擎为各种项目类型提供了更加复杂的输入映射。参见增强输入来了解更多。
项目设置
-
创建一个新的 游戏(Games) > 空白(Blank) > 蓝图(Blueprint) 项目命名为 "SettingUpInput"。
-
在编辑器中,找到 编辑(Edit) > 项目设置(Project Settings) > 输入(Input) > 绑定(Bindings)。
-
创建一个新的 游戏(Games) > 空白(Blank) > C++ 项目命名为 "SettingUpInput"。
-
在编辑器中,找到 编辑(Edit) > 项目设置(Project Settings) > 输入(Input) > 绑定(Bindings)。

动作和坐标轴映射设置
输入通常通过用户定义的 动作(Actions) 和 坐标轴映射(Axis Mappings) 的 绑定(Bindings) 来定义。这两种映射提供了一种方便的机制,能够在输入行为和触发它的按键之间插入一个间接层,从而将按键和坐标轴映射到输入行为。
动作映射用于按键的按下和抬起,而轴映射对应有持续范围的输入。定义完映射后,你可以将其在蓝图或者C++中绑定到行为。
-
点击 动作映射(Action Mappings) 旁边的 添加(+),创建一个新的动作命名为 Jump。
-
点击下拉箭头(1)或者点击 选择按键值(Select Key Value) 按钮(2),找到并选择 空格(Space Bar) 按键值。
-
找到 轴映射(Axis mappings) 并点击 添加(+) 来创建以下 轴映射(Axis Mapping) 名称、按键(Key) 值、 以及 缩放(Scale) 值:
轴映射名称 按键值 缩放值 MoveForward W 1.0 S -1.0 MoveRight A -1.0 D 1.0 Turn 鼠标X 1.0 LookUp 鼠标Y -1.0
创建示例角色
创建弹簧臂和摄像机组件
创建弹簧臂和摄像机组件
当 摄像机(Camera) 和 SpringArm组件 共同使用时,它们可以形成第三人称视角,并且能够动态根据游戏世界进行调节。摄像机组件包含一个摄像机,代表玩家的视角,作为玩家查看游戏世界的方式。SpringArm组件用作 "摄像机吊臂",防止玩家的摄像机与世界发生碰撞。
-
在 组件(Components) 选项卡中,点击 添加(+),然后从下拉菜单中找到并选择 弹簧臂(Spring Arm)。重命名你的弹簧臂组件为 CameraBoom。
-
重复第一步,但是找到并选择 摄像机(Camera)。将摄像机组件重命名为 FollowCamera。
-
在 组件(Components) 选项卡中,将你的 FollowCamera 拖动到 CameraBoom 来将其连接。
-
在组件选项卡中选中CameraBoom,然后前往 细节(Details) > 摄像机设置(Camera Settings),点击复选框来启用 使用Pawn控制旋转(Use Pawn Control Rotation) 变量。启用后,摄像机父级会使用pawn的视角/控制进行旋转 (ExampleCharacter)。
要了解更多用于角色视角的弹簧臂和摄像机设置,请参考使用摄像机文档。
-
编译(Compile) 并 保存(Save)。
当 摄像机(Camera) 和 弹簧臂(SpringArm)组件 共同使用时,它们可以形成第三人称视角,并且能够动态根据游戏世界进行调节。摄像机组件包含一个摄像机,代表玩家的视角,作为玩家查看游戏世界的方式。弹簧臂(SpringArm)组件用作 "摄像机吊臂",防止玩家的摄像机与世界发生碰撞。
- 在你的代码编辑器中,找到ExampleCharacter.h。在 类默认(Class defaults)中, 声明以下类。
protected: UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Components") class USpringArmComponent* CameraBoom; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Components") class UCameraComponent* FollowCamera; |
UProperty Specifiers 用于在蓝图编辑器中提供组件的可见性
- 前往你的
ExampleCharacter.cpp
文件,在include行添加以下库。#include "GameFramework/SpringArmComponent.h" #include "Camera/CameraComponent.h"
- 接下来,在
AExampleCharacter
构建器中应用以下内容。AExampleCharacter::AExampleCharacter() { //Initialize the Camera Boom CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom")); //Setup Camera Boom attachment to the Root component of the class CameraBoom->SetupAttachment(RootComponent); //Set the boolean to use the PawnControlRotation to true. CameraBoom->bUsePawnControlRotation = true; //Initialize the FollowCamera FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera")); //Set FollowCamera attachment to the Camera Boom FollowCamera->SetupAttachment(CameraBoom); }
组件会调用FObjectInitializer::CreateDefaultSubobject模板,然后使用SetupAttachment方法来附挂到一个父级场景组件。将Camera Boom设置为使用Pawn的控制旋转时,它会使用父级Pawn的旋转而不是自己的旋转。
- 编译你的代码。
设置角色网格体
-
在 组件(Components) 面板,选择 网格体(Mesh) 骨骼网格体组件。
-
前往 细节(Details) > 网格体(Mesh) > 骨骼网格体(Skeletal Mesh),展开下拉菜单。选择 浏览资产选择(Browse Asset Options) > 内容(Content) > 显示引擎内容(Show Engine Content)。
-
找到并选择 TutorialTPP 骨骼网格体。
-
找到 变形(Transform) 分类,然后将 位置(Location) 和 旋转(Rotation) 向量值设为 (0.0, 0.0, -90)。
-
编译(Compile) 并 保存(Save)。
向你的输入事件创建动作/轴函数
- 在你的
ExampleCharacter.h
类默认中,生命以下输入函数。protected: void MoveForward(float AxisValue); void MoveRight(float AxisValue);
- 找到你的
ExampleCharacter.cpp
并应用你的MoveForward
和MoveRight
方法。void AExampleCharacter::MoveForward(float AxisValue) { if ((Controller != NULL) && (AxisValue != 0.0f)) { // find out which direction is forward const FRotator Rotation = Controller->GetControlRotation(); const FRotator YawRotation(0, Rotation.Yaw, 0); // get forward vector const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X); AddMovementInput(Direction, AxisValue); } } void AExampleCharacter::MoveRight(float AxisValue) { if ((Controller != NULL) && (AxisValue != 0.0f)) { // find out which direction is right const FRotator Rotation = Controller->GetControlRotation(); const FRotator YawRotation(0, Rotation.Yaw, 0); // get right vector const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y); // add movement in that direction AddMovementInput(Direction, AxisValue); } }
- 找到SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)方法,然后应用以下代码。
void AExampleCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump); PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping); PlayerInputComponent->BindAxis("MoveForward", this, &AExampleCharacter::MoveForward); PlayerInputComponent->BindAxis("MoveRight", this, &AExampleCharacter::MoveRight); PlayerInputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput); PlayerInputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput); }
玩家输入组件将你的项目中的AxisMappings和ActionMappings链接到游戏动作。Pawn和角色类都包含继承的方法并且可以用于或者扩展你的自定义角色。 在我们的示例中,我们使用Pawn的AddControllerYawInput和AddControllerPitchInput函数,以及角色的Jump和StopJumping函数。
- 编译你的代码。
向你的输入事件创建动作/轴函数
-
前往 我的蓝图(My Blueprint) > 函数(Functions),点击 添加(+) 来添加两个新的函数。命名为 MoveForward 和 MoveRight。
-
选中 MoveForward 函数,前往 细节(Details) > 输入(Inputs),然后点击 添加(+) 来添加一个新的 浮点 值输入,命名为 AxisValue。
-
为 MoveForward 函数复制或者应用以下逻辑。
Begin Object Class=/Script/BlueprintGraph.K2Node_FunctionEntry Name="K2Node_FunctionEntry_0" ExtraFlags=201457664 FunctionReference=(MemberName="MoveForward") bIsEditable=True NodePosX=-32 NodePosY=16 NodeGuid=A0FF87524A53EDAA6CBEC48FEE0D9464 CustomProperties Pin (PinId=B427E05D444F66A59DA68E9A5D09AB7B,PinName="then",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_7346 B27FCDDF43B9261BD870CE965B82DF38,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=F01767A145595ED17A3E438A7F7BEFA2,PinName="AxisValue",Direction="EGPD_Output",PinType.PinCategory="real",PinType.PinSubCategory="double",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_7346 D95413A34BE985375A5C2F905CD8109F,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties UserDefinedPin (PinName="AxisValue",PinType=(PinCategory="real",PinSubCategory="double"),DesiredPinDirection=EGPD_Output) End Object Begin Object Class=/Script/BlueprintGraph.K2Node_CallFunction Name="K2Node_CallFunction_7346" FunctionReference=(MemberName="AddMovementInput",bSelfContext=True) NodePosX=384 ErrorType=1 NodeGuid=CE1F697649E08F668E46BFA6FF6FE134 CustomProperties Pin (PinId=B27FC -
选中 MoveRight 函数,然后按照第二步中添加一个新的 浮点 数值。
-
为 MoveRight 函数复制或者应用以下逻辑。
Begin Object Class=/Script/BlueprintGraph.K2Node_FunctionEntry Name="K2Node_FunctionEntry_0" ExtraFlags=201457664 FunctionReference=(MemberName="MoveRight") bIsEditable=True NodePosX=64 NodePosY=-48 NodeGuid=5846746C4FEEF77A895638939B0C845C CustomProperties Pin (PinId=09949021438E59AA6E23A8B112C93B0D,PinName="then",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_7346 B27FCDDF43B9261BD870CE965B82DF38,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=0FE0FC0344DE295574151E8BA52B9628,PinName="AxisValue",Direction="EGPD_Output",PinType.PinCategory="real",PinType.PinSubCategory="double",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_7346 D95413A34BE985375A5C2F905CD8109F,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties UserDefinedPin (PinName="AxisValue",PinType=(PinCategory="real",PinSubCategory="double"),DesiredPinDirection=EGPD_Output) End Object Begin Object Class=/Script/BlueprintGraph.K2Node_CallFunction Name="K2Node_CallFunction_7346" FunctionReference=(MemberName="AddMovementInput",bSelfContext=True) NodePosX=432 NodePosY=-64 ErrorType=1 NodeGuid=0A9F72574C55739F8ABF479B3DA34A3C CustomProperties Pin ( -
前往 事件图表(Event Graph)。你需要设置你的轴和动作输入来调用对应的函数。复制或者应用以下逻辑。
Begin Object Class=/Script/BlueprintGraph.K2Node_CallFunction Name="K2Node_CallFunction_0" FunctionReference=(MemberName="MoveForward",MemberGuid=C0341673464A891BBAB256A597CC129B,bSelfContext=True) NodePosX=752 NodePosY=96 NodeGuid=F58C25A840CC8F0AFBDAF29C9156738F CustomProperties Pin (PinId=0AB1925F4322FE3D3E6EB4A491889FC9,PinName="execute",PinToolTip="\nExec",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_InputAxisEvent_0 C6162D6E4C41B2636D72DB955E9701A2,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=75B681B34A8D4B3145A6B88572E666E2,PinName="then",PinToolTip="\nExec",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=A75F913B4741D285583415B3E8CFF56F,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "Target", "Target"),PinToolTip="Target\nSelf Object Reference",PinType.PinCategory="object",PinType.PinSubCategory="self",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUOb
完成的代码
ExampleCharacter.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "ExampleCharacter.generated.h"
UCLASS()
class SETTINGUPINPUT_API AExampleCharacter : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
AExampleCharacter();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
UPROPERTY(EditDefaultsOnly,BlueprintReadOnly)
class USpringArmComponent* CameraBoom;
UPROPERTY(EditDefaultsOnly,BlueprintReadOnly)
class UCameraComponent* FollowCamera;
void MoveForward();
void MoveRight();
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};
ExampleCharacter.cpp
// Sets default values
AExampleCharacter::AExampleCharacter()
{
//Initialize the Camera Boom
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
//Setup its attachment to the Root component of the class
CameraBoom->SetupAttachment(RootComponent);
//Set the boolean to use the PawnControlRotation to true.
CameraBoom->bUsePawnControlRotation = true;
//Initialize the Camera Comp
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
//Set its attachment to the Camera Boom
FollowCamera->SetupAttachment(CameraBoom);
}
// Called when the game starts or when spawned
void AExampleCharacter::BeginPlay()
{
Super::BeginPlay();
}
void AExampleCharacter::MoveForward(float AxisValue)
{
if ((Controller != NULL) && (AxisValue != 0.0f))
{
// find out which direction is forward
const FRotator Rotation = Controller->GetControlRotation();
const FRotator YawRotation(0, Rotation.Yaw, 0);
// get forward vector
const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
AddMovementInput(Direction, AxisValue);
}
}
void AExampleCharacter::MoveRight(float AxisValue)
{
if ((Controller != NULL) && (AxisValue != 0.0f))
{
// find out which direction is right
const FRotator Rotation = Controller->GetControlRotation();
const FRotator YawRotation(0, Rotation.Yaw, 0);
// get right vector
const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
// add movement in that direction
AddMovementInput(Direction, AxisValue);
}
}
// Called every frame
void AExampleCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void AExampleCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
// Set up gameplay key bindings
check(PlayerInputComponent);
PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);
PlayerInputComponent->BindAxis("Move Forward", this, &AExampleCharacter::MoveForward);
PlayerInputComponent->BindAxis("Move Right", this, &AExampleCharacter::MoveRight);
}
创建角色蓝图
-
前往你的 C++ Classes Folder 并且右键点击你的 ExampleCharacter,在下拉菜单中选择 根据ExampleCharacter创建蓝图类(Create Blueprint class based on ExampleCharacter)。将你的蓝图命名为 BP_ExampleCharacter。
-
在 组件(Components) 面板,选择 网格体(Mesh) 骨骼网格体组件。
-
前往 细节(Details) > 网格体(Mesh) > 骨骼网格体(Skeletal Mesh),展开下拉菜单。在浏览器部分,点击 设置(Settings) 图标。然后在菜单中,选择 内容(Content) > 显示引擎内容(Show Engine Content)。
-
找到并选择 TutorialTPP 骨骼网格体。
-
找到 变形(Transform) 分类,然后将 位置(Location) 和 旋转(Rotation) 向量值设为 (0.0, 0.0, -90)。
完成的蓝图
向前移动

向右移动

事件图表

创建游戏模式蓝图
游戏模式定义游戏的一组规则。这些规则包括游戏开始时玩家作为哪种默认Pawn生成。你需要设置这些规则来生成你创建的玩家角色。
-
在 内容浏览器(Content Drawer) 中,点击 添加(+) 来创建一个新的 蓝图类(Blueprint Class),然后在下拉菜单中选择 游戏模式基础(Game Mode Base) 作为你的 父级类(Parent Class)。将你的游戏模式命名为 "BP_InputGameMode"。
-
在 类(Class) 默认中,找到 类(Classes) > 默认Pawn类(Default Pawn Class),然后选择 BP_ExampleCharacter。
-
编译(Compile) 并 保存(Save)。
-
前往 编辑(Edit) > 项目设置(Project Settings) > 映射和模式(Maps and Modes)。将 默认游戏模式(Default GameMode) 设为 BP_InputGameMode。
-
前往 编辑器(Editor) 然后选择 游玩(Play) (编辑器内游玩(Play in Editor))
现在你可以用W、A、S、D键控制你的角色移动。移动鼠标可以控制摄像头,按下空格键会让角色跳跃。
游戏模式定义游戏的一组规则。这些规则包括游戏开始时玩家作为哪种默认Pawn生成。你需要设置这些规则来生成你创建的玩家角色。
-
在 内容浏览器(Content Drawer) 中,找到你的 C++ Classes 文件夹,右键点击 SettingUpInputGameModeBase然后在下拉菜单中选择 根据SettingUpInputGameModeBase创建蓝图(Create Blueprint Based on SettingUpInputGameModeBase)。将你的游戏模式蓝图命名为 "BP_InputGameMode"。
-
在 类(Class) 默认中,找到 类(Classes) > 默认Pawn类(Default Pawn Class),然后选择 BP_ExampleCharacter。
-
编译(Compile) 并 保存(Save)。
-
前往 编辑(Edit) > 项目设置(Project Settings) > 映射和模式(Maps and Modes)。将 默认游戏模式(Default GameMode) 设为 BP_InputGameMode。
-
前往 编辑器(Editor) 然后选择 游玩(Play) (编辑器内游玩(Play in Editor))
现在你可以用W、A、S、D键控制你的角色移动。移动鼠标可以控制摄像头,按下空格键会让角色跳跃。
最终结果
