UE4_C++_002

玩家输入与Pawn

这个是组件和碰撞的提前知识预备,最好在之前了解组件相关东西,重要的概念对于轴映射和操作映射。

首先介绍两个概念

  1. Actor类——可以放到游戏场景中的游戏对象的基本类型。你如果想放置任何东西到游戏场景中,必须继承Actor类
  2. Pawn类——代表或者代表电脑的人工智能的游戏对象,它是可以在屏幕上控制的游戏对象。Pawn类是从Actor类中继承的,它可以通过玩家的设备(键盘、鼠标等)控制或者被人工智能脚本控制。如果它是被玩家控制的,我们通常称之为controller(控制器);如果它是被人工智能脚本控制的,我们通常称之为AI(Artificial Intelligence,人工智能),如果你经常玩游戏,那些NPC(Non-player Characters,非玩家角色)就通常具有AI行为

自己定义Pawn

  1. 打开UE4的C++项目,添加C++类,命名为MyPawn
  2. 在cpp中设置玩家控制
// 将该Pawn设为由最小编号玩家控制
AutoPossessPlayer = EAutoReceiveInput::Player0;
  1. 构建几个组件,在MyPawn.h底部添加
UPROPERTY(EditAnywhere)
USceneComponent* OurVisibleComponent;

《Inside UE4》-GamePlay架构系列博客
首先要知道一个对象要在3D世界中的表示,必然要携带一个Transform来表示其位置。但是在UE看来,Actor并不只是3D中的表示,一些不在世界中展示的“不可见对象”也可以是Actor,比如AInfo的派生类等,所以Actor也就没有自带Transform了。

而SceneComponent则封装了Transform,当作RootComponent,所以需要位置表示的Actor就可以向Actor中添加SceneComponent作为其RootComponent.比如,pawn就自动创建了SceneComponent.

还有一点需要注意的是,实际中大部分的Actor是有Transform的,所以我们会经常设置获取它的坐标,常理来说,我们的需要先获取下SceneComponent,然后才能操作其Transform等相应接口,但是这样太过繁琐,因此UE为我们直接提供了基于Actor的接口,如Get/Set ActorLocation,但其实这些接口内部也是转发到RootComponent(SceneComponent)的。

  1. 将下面代码添加到cpp中构造函数AMyPawn::AMyPawn

这里需要在开头添加#include "Camera/CameraComponent.h"

// 创建可附加内容的虚拟根组件。
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
// 创建相机和可见对象
UCameraComponent* OurCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("OurCamera"));
OurVisibleComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("OurVisibleComponent"));
// 将相机和可见对象附加到根组件。偏移并旋转相机。
OurCamera->SetupAttachment(RootComponent);
OurCamera->SetRelativeLocation(FVector(-250.0f, 0.0f, 250.0f));
OurCamera->SetRelativeRotation(FRotator(-45.0f, 0.0f, 0.0f));
OurVisibleComponent->SetupAttachment(RootComponent);
  1. 现在便拥有响应游戏输入的自定义Pawn,需定义此输入的内容。为此,将在 虚幻编辑器 中配置项目的 输入设置

配置游戏输入

输入的映射有两种——操作

操作映射
适用于"是/否"输入,例如鼠标或手柄上的按钮。被按下、松开、双击或短时长按时,其将进行报告。跳跃、射击或与物体互动等离散操作是这类映射的理想对象。

轴映射
是连续的,可将其视为"程度"输入,例如手柄上的摇杆,或者鼠标光标的位置。其会逐帧报告自身的值,即使未移动也进行报告。通常使用此方法处理如行走、四处查看和操纵车辆等有量级或方向的对象。

虽然可直接在代码中定义输入映射,但常用方法是在 虚幻引擎 编辑器中定义,本教程也将使用此方法。

  1. 在 虚幻引擎编辑器中,在 编辑 下拉菜单下,点击 项目设置(Project Settings) 选项。
  2. 在此界面左侧的 引擎(Engine) 部分中选择 输入 选项。之后,展开右侧显示的 绑定 类别,添加 操作映射(Action Mapping) 和两个轴映射(Axis Mappings)
    在这里插入图片描述
  3. 输入现已配置完成,接下来在关卡中设置MyPawn。MyPawn 类将在 内容浏览器 中显示,并可被拖入 关卡编辑器在这里插入图片描述
  4. 设置MyPawn还需一个步骤。需向其指定 静态网格体,以便其可在游戏中显示。具体操作:选择刚创建的MyPawn,在 细节面板 中选择名为 OurVisibleComponent (Inherited) 的组件,并利用 静态网格体 类别中的下拉框向其指定资源。在本教程中,Shape_Cylinder 为现成资源。 在这里插入图片描述
  5. 现在保存关卡,返回 Visual Studio 编写代码,使刚刚放置的MyPawn对定义的输入做出反应。

编写和绑定游戏操作

  1. Visual Studio 中,打开MyPawn.h并将以下代码添加到MyPawn类定义的底部:

四个输入函数将被绑定到输入事件。其运行时,将对新输入变量中存储的值进行更新,MyPawn将使用此类值决定游戏期间应执行的操作。

//输入函数
    void Move_XAxis(float AxisValue);
    void Move_YAxis(float AxisValue);
    void StartGrowing();
    void StopGrowing();

    //输入变量
    FVector CurrentVelocity;
    bool bGrowing;
  1. 切换到MyPawn.cpp,并对刚才声明的四个函数编码。

使用 FMath::Clamp 约束输入中得到的值,将其约束在-1到+1的范围内。虽然本例中不存在此问题,但若有会对轴产生相同影响的多个键,则玩家同时按下此类输入时会将累加这些值。例如,如W键和向上方向键均映射到MoveX,且缩放均为1.0,同时按下这两个键会得到2.0的AxisValue。如不进行限制,玩家将以两倍速度移动。

void AMyPawn::Move_XAxis(float AxisValue)
{
    // 以100单位/秒的速度向前或向后移动
    CurrentVelocity.X = FMath::Clamp(AxisValue, -1.0f, 1.0f) * 100.0f;
}

void AMyPawn::Move_YAxis(float AxisValue)
{
    // 以100单位/秒的速度向右或向左移动
    CurrentVelocity.Y = FMath::Clamp(AxisValue, -1.0f, 1.0f) * 100.0f;
}

void AMyPawn::StartGrowing()
{
    bGrowing = true;
}

void AMyPawn::StopGrowing()
{
    bGrowing = false;
}

可以看到,两个"Move"函数将轴值视作浮点,而"Grow"则不同。这是因为其映射到MoveX和MoveY,均为轴映射,因此拥有浮点参数。操作映射无此参数。

  1. 现在已定义输入函数,接下来需进行绑定,以便对相应输入做出反应。将以下代码添加到 AMyPawn::SetupPlayerInputComponent 中:
// 在按下或松开"Grow"键时做出响应。
InputComponent->BindAction("Grow", IE_Pressed, this, &AMyPawn::StartGrowing);
InputComponent->BindAction("Grow", IE_Released, this, &AMyPawn::StopGrowing);

// 对两个移动轴"MoveX"和"MoveY"的值逐帧反应。
InputComponent->BindAxis("MoveX", this, &AMyPawn::Move_XAxis);
InputComponent->BindAxis("MoveY", this, &AMyPawn::Move_YAxis);
  1. 变量现在将根据配置的输入进行更新。接下来只需编写代码使其完成部分操作。将以下代码添加到 AMyPawn::Tick
// 根据"Grow"操作处理增长和缩减
{
    float CurrentScale = OurVisibleComponent->GetComponentScale().X;
    if (bGrowing)
    {
        // 一秒内增长到两倍大小
        CurrentScale += DeltaTime;
    }
    else
    {
        // 以增长速度缩减一半
        CurrentScale -= (DeltaTime * 0.5f);
    }
    // 确保不会降至初始大小以下,或者增至两倍大小以上。
    CurrentScale = FMath::Clamp(CurrentScale, 1.0f, 2.0f);
    OurVisibleComponent->SetWorldScale3D(FVector(CurrentScale));
}

// 根据"MoveX"和"MoveY"轴处理移动
{
    if (!CurrentVelocity.IsZero())
    {
        FVector NewLocation = GetActorLocation() + (CurrentVelocity * DeltaTime);
        SetActorLocation(NewLocation);
    }
}
  1. 编译代码后,可返回 虚幻编辑器 并按 运行。应可使用WASD键控制 Pawn,同时可通过长按 空格 键来使其增长,松开空格键时看到缩小。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
dynamic_cast是C++中的一个类型转换运算符,用于在继承关系中进行类型转换。它要求操作数必须是多态类型,即父类必须存在虚函数。\[1\]在使用dynamic_cast时,如果转换成功,则返回指向目标类型的指针或引用;如果转换失败,则返回nullptr。\[2\]dynamic_cast的使用需要注意以下几点: 1. dynamic_cast只能用于指针或引用类型的转换,不能用于基本类型的转换。 2. dynamic_cast只能用于具有继承关系的类型之间的转换,即父类和子类之间的转换。 3. dynamic_cast在进行类型转换时,会进行运行时类型检查,因此会带来一定的性能开销。 4. dynamic_cast只能用于向下转型,即将父类指针或引用转换为子类指针或引用。如果尝试将子类指针或引用转换为父类指针或引用,dynamic_cast会返回nullptr。 总之,dynamic_cast是C++中用于在继承关系中进行类型转换的运算符,它要求操作数必须是多态类型,并且只能用于具有继承关系的类型之间的转换。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [c++——dynamic_cast的使用](https://blog.csdn.net/www_dong/article/details/124873017)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [dynamic_cast的详细用法,typeid运算符简介](https://blog.csdn.net/A_With_better/article/details/121862072)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [C++中static_cast和dynamic_cast强制类型转换](https://blog.csdn.net/a1013642808/article/details/80429061)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值