传统输入系统更方便修改按键,如果想把鼠标左键触发改为空格键触发,只需要在引擎中修改,无需修改C++.
传统输入系统中的两种映射:
操作映射Action Mapping
轴映射Axis Mapping
操作映射关心有没有发生,而不是发生了多少,适合处理按了一次的输入,如:
- 鼠标左键按下
- 鼠标右键按下
- 滚轮向上滚动一次
- 滚轮向下滚动一次
操作映射可检测:
IE_Pressed // 按下时执行
IE_Released // 松开时执行
IE_Repeat // 按住时重复执行
IE_DoubleClick // 双击时执行
操作映射可以给同一个Action添加多个按键,这些按键触发相同功能。
轴映射适合产生数值的输入,它关心的是输入值是多少,通常带有一个float参数如:
- 鼠标水平移动
- 鼠标垂直移动
- 鼠标滚轮轴
轴映射中非常重要的一个参数是Scale,它表示输入值乘以多少。
UE 的输入设置中,Action Mapping 用于按下和松开事件,Axis Mapping 用于连续范围输入。
对于鼠标滚轮,UE同时提供:
EKeys::MouseScrollUp
EKeys::MouseScrollDown
EKeys::MouseWheelAxis
滚轮既可以作两个离散按键,也可以作一个带有正负值的轴。
在项目设置中创建鼠标映射
编辑 Edit
→ 项目设置 Project Settings
→ 引擎 Engine
→ 输入 Input
→ 绑定 Bindings
映射名称可以自己设置,但必须和 C++ 中的名称完全一致,包括大小写。
案例如下:
// Fill out your copyright notice in the Description page of Project Settings. #include "MouseCpp.h" #include "Components/InputComponent.h" #include "Engine/Engine.h" #include "GameFramework/PlayerController.h" #include "Components/SceneComponent.h" #include "Components/StaticMeshComponent.h" // Sets default values AMouseCpp::AMouseCpp() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; MyScene=CreateDefaultSubobject<USceneComponent>( TEXT("MyScene") ); SetRootComponent(MyScene); MyStaticMesh=CreateDefaultSubobject<UStaticMeshComponent>( TEXT("MyStaticMeshComponent") ); MyStaticMesh->SetupAttachment(MyScene); } // Called when the game starts or when spawned void AMouseCpp::BeginPlay() { Super::BeginPlay(); // 获取第一个本地玩家的 PlayerController APlayerController* PlayerController = GetWorld()->GetFirstPlayerController(); if (!PlayerController) { return; } // 让当前 Actor 可以接收这个玩家的输入 EnableInput(PlayerController); // EnableInput 后,Actor 会拥有用于绑定输入的 InputComponent if (!InputComponent) { return; } InputComponent->BindAction( TEXT("MouseLeft"), IE_Pressed, this, &AMouseCpp::OnLeftMousePressed ); InputComponent->BindAction( TEXT("MouseLeft"), IE_Released, this, &AMouseCpp::OnLeftMouseReleased ); InputComponent->BindAction( TEXT("MouseRight"), IE_Pressed, this, &AMouseCpp::OnRightMousePressed ); InputComponent->BindAction( TEXT("MouseMiddle"), IE_Pressed, this, &AMouseCpp::OnMiddleMousePressed ); InputComponent->BindAction( TEXT("MouseWheelUP"), IE_Pressed, this, &AMouseCpp::OnMouseWheelUp ); InputComponent->BindAction( TEXT("MouseWheelDown"), IE_Pressed, this, &AMouseCpp::OnMouseWheelDown ); InputComponent->BindAxis( TEXT("MouseWheel"), this, &AMouseCpp::OnMouseWheelAxis ); PlayerController->bShowMouseCursor = true; } // Called every frame void AMouseCpp::Tick(float DeltaTime) { Super::Tick(DeltaTime); } void AMouseCpp::OnLeftMousePressed() { if (GEngine) { GEngine->AddOnScreenDebugMessage( -1, 2.0f, FColor::Red, TEXT("鼠标左键按下") ); } } void AMouseCpp::OnLeftMouseReleased() { if (GEngine) { GEngine->AddOnScreenDebugMessage( -1, 2.0f, FColor::Red, TEXT("鼠标左键松开") ); } } void AMouseCpp::OnRightMousePressed() { if (GEngine) { GEngine->AddOnScreenDebugMessage( -1, 2.0f, FColor::Red, TEXT("鼠标右键按下") ); } } void AMouseCpp::OnMiddleMousePressed() { SetActorScale3D(FVector(1.0f)); if (GEngine) { GEngine->AddOnScreenDebugMessage( -1, 2.0f, FColor::Cyan, TEXT("鼠标中键:恢复默认缩放") ); } } void AMouseCpp::OnMouseWheelUp() { const FVector NewScale = GetActorScale3D() * 1.1f; SetActorScale3D(NewScale); if (GEngine) { GEngine->AddOnScreenDebugMessage( -1, 1.0f, FColor::Green, TEXT("滚轮向上:Actor 放大") ); } } void AMouseCpp::OnMouseWheelDown() { // 每次缩小约 10% const FVector NewScale = GetActorScale3D() / 1.1f; SetActorScale3D(NewScale); if (GEngine) { GEngine->AddOnScreenDebugMessage( -1, 1.0f, FColor::Red, TEXT("滚轮向下:Actor 缩小") ); } } void AMouseCpp::OnMouseWheelAxis(float Value) { if (FMath::IsNearlyZero(Value)) { return; } if (GEngine) { GEngine->AddOnScreenDebugMessage( -1, 1.0f, FColor::White, FString::Printf( TEXT("鼠标滚轮轴值:%.2f"), Value ) ); } }