1.实现角色移动,查看,跳跃.md
2025/12/16预计阅读 13 分钟
1.创建一个AMyCharacterc++类
它继承虚幻角色类,类名是ACharacter
2.重写父类SetupPlayerInputComponent函数绑定输入,添加动作监听
1.在角色类中定义2个属性,(输入映射UInputMappingContext)和(动作UInputAction)
class DEMO2_API AMyCharacter : public ACharacter{
GENERATED_BODY()
public:
//...
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
UInputMappingContext* MyDefaultMappingContext;//输入映射
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
UInputAction* MyLookAction;//代表动作
};
这两个属性后面要在蓝图中的详情面板中配置.
2.获取玩家的输入子系统添加输入映射
在函数SetupPlayerInputComponent下编写
1.获取玩家控制器
APlayerController* PlayController = Cast<APlayerController>(GetController());
2.获取输入子系统
auto SubSystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayController->GetLocalPlayer());
3.添加输入映射
SubSystem -> AddMappingContext(MyDefaultMappingContext,0);//单人玩家:0
3.注册鼠标动态监听
1.获取输入组件
UEnhancedInputComponent* InputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent);
2.绑定动作
InputComponent->BindAction(MyLookAction,ETriggerEvent::Triggered,this,&AMyCharacter::SetCameraRotation);
3.实现鼠标转动函数
//设置鼠标的移动
void AMyCharacter::SetCameraRotation(const FInputActionValue& Value)
{
const auto Vector = Value.Get<FVector2d>();//获取鼠标的2d向量
if(Controller != nullptr)
{
AddControllerYawInput(Vector.X);//偏航值
AddControllerPitchInput(Vector.Y);
}
}
完整的代码
AMyCharacter.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "InputAction.h"
#include "InputMappingContext.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/Character.h"
#include "GameFramework/SpringArmComponent.h"
#include "MyCharacter.generated.h"
struct FInputActionValue;
UCLASS()
class DEMO2_API AMyCharacter : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
AMyCharacter();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
UPROPERTY(VisibleAnywhere)
UCameraComponent* MyCameraComponent;
UPROPERTY(VisibleAnywhere)
USpringArmComponent* MySpringArmComponent;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// 调用将功能绑定到输入
virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
UInputMappingContext* MyDefaultMappingContext;
//左看右看,上看下看
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
UInputAction* MyLookAction;
//左右移动,上下移动
UPROPERTY(EditAnywhere,BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
UInputAction* MyMoveAction;
// 设置鼠标的移动
UFUNCTION(BlueprintCallable, Category="梁典典的函数",DisplayName="控制鼠标旋转")
void SetCameraRotation(const FInputActionValue& Value);
// 设置前进方向
UFUNCTION(BlueprintCallable,Category="梁典典的函数",DisplayName="控制任务移动")
void Move(const FInputActionValue& Value);
//跳
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
UInputAction* MyJumpAction;
};
AMyCharacter.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyCharacter.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "GameFramework/CharacterMovementComponent.h"
// 设置默认值
AMyCharacter::AMyCharacter()
{
// 设置此字符每帧调用 Tick()。 如果不需要,您可以将其关闭以提高性能。
PrimaryActorTick.bCanEverTick = true;
//创建摄像机杆子
MySpringArmComponent = CreateDefaultSubobject<USpringArmComponent>(TEXT("LddSpringArmComponent"));
MySpringArmComponent->bUsePawnControlRotation = true;//跟随角色旋转
MySpringArmComponent->SetupAttachment(RootComponent);
//创建摄像机
MyCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("LddCameraComponent"));
MyCameraComponent->SetupAttachment(MySpringArmComponent);//附加到杆子
MyCameraComponent->SetRelativeLocation(FVector(0,0,50.f));
MyCameraComponent->bUsePawnControlRotation = true;
//让角色的朝向始终和当前的移动方向一致
GetCharacterMovement()->bOrientRotationToMovement = true;
//保证角色平滑的旋转
bUseControllerRotationYaw = false;
bUseControllerRotationPitch = false;
}
// 游戏开始或生成时调用
void AMyCharacter::BeginPlay()
{
Super::BeginPlay();
}
// 调用每一帧
void AMyCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// 调用将功能绑定到输入
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
//添加输入上下文映射
if(APlayerController* PlayController = Cast<APlayerController>(GetController()))
{
if(auto SubSystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayController->GetLocalPlayer()))
{
SubSystem -> AddMappingContext(MyDefaultMappingContext,0);
}
}
if (UEnhancedInputComponent* InputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
{
// Jumping
InputComponent->BindAction(MyJumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);
InputComponent->BindAction(MyJumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
InputComponent->BindAction(MyLookAction,ETriggerEvent::Triggered,this,&AMyCharacter::SetCameraRotation);
InputComponent->BindAction(MyMoveAction,ETriggerEvent::Triggered,this,&AMyCharacter::Move);
}
UE_LOG(LogTemp,Log,TEXT("AMyCharacter::SetupPlayerInputComponent"));
}
//设置鼠标的移动
void AMyCharacter::SetCameraRotation(const FInputActionValue& Value)
{
const auto Vector = Value.Get<FVector2d>();
UE_LOG(LogTemp,Log,TEXT("AMyCharacter::SetCameraRotation:x:%.2f,y:%.2f"),Vector.X,Vector.Y);
if(Controller != nullptr)
{
AddControllerYawInput(Vector.X);
AddControllerPitchInput(Vector.Y);
}
}
//让角色移动
void AMyCharacter::Move(const FInputActionValue& Value)
{
const auto Vector = Value.Get<FVector2d>();
if(Controller != nullptr)
{
//获取方向
const FRotator Rotation = Controller->GetControlRotation();
//获取左右的方向
const FRotator YawNewRotator = FRotator(0,Rotation.Yaw,0);
const FRotationMatrix Matrix = FRotationMatrix(YawNewRotator);
//获取向前的向量
const FVector X = Matrix.GetUnitAxis(EAxis::X);
//获取左右的向量
const FVector Y = Matrix.GetUnitAxis(EAxis::Y);
UE_LOG(LogTemp,Log,TEXT("角色移动:输入X:%.2f,输入Y:%.2f,保持左右的旋转角度:%.2f(不关心上下角度)"),Vector.X,Vector.Y,Rotation.Yaw);
AddMovementInput(X,Vector.Y);
AddMovementInput(Y,Vector.X);
}
}
chatgpt
问题1:这些概念太难了,对我来说,很难很难
理解这些概念确实有点复杂,尤其是在你刚开始学习 Unreal Engine 的时候。不要担心,这是一个正常的过程,随着时间和练习,你会逐渐掌握它们。我们可以一起慢慢来,逐步简化这些概念,帮助你更好地理解。
我会试着用更简单的方式解释,看看是否能帮你更容易理解:
1. 输入向量(FVector2d)
你可以把输入向量想象成一个手柄或键盘输入的方向。假设你在用手柄操作:
Vector.X代表左右方向,值越大代表往右移动,越小代表往左移动。Vector.Y代表前后方向,值越大代表往前移动,越小代表往后移动。
所以这个 Vector 就是表示玩家的输入方向。
2. 控制器旋转
控制器的旋转简单来说,就是你角色朝向的方向。假设你在游戏里用鼠标或者右摇杆控制角色的视角旋转,这就是控制器的“旋转角度”。旋转分为:
- Yaw:左右旋转(水平转头)。
- Pitch:上下旋转(抬头或低头)。
在这个例子里,我们只关心角色左右转头的方向(
Yaw),所以忽略了上下抬头的部分。
3. 前进和左右的方向
- 前进方向:假设角色现在面对一个方向,这就是“前进方向”。前进方向对应着
X轴。 - 左右方向:想象一下,如果你站着不动,左右方向就是你的身体的两侧。这个方向对应着
Y轴。
4. 移动逻辑
当你输入方向时:
Vector.Y代表你是往前走还是往后退,程序就让你根据“前进方向”去移动。Vector.X代表你是往左移还是往右移,程序就让你根据“左右方向”去移动。
最终,这段代码就是让角色根据你输入的方向移动,无论你是用键盘、鼠标还是手柄。
你可以慢慢分步骤去理解这些代码,并用简单的例子去测试效果。每次理解一个小概念,尝试把它和实际操作联系起来,就会变得更容易。有什么具体的部分你想再深入理解的,或者需要更简单的解释,告诉我,我可以继续帮助你!
问题2FRotationMatrix这个是什么东西?
FRotationMatrix 是 Unreal Engine 中的一个类,用来表示旋转矩阵。旋转矩阵是数学中的一个工具,用来描述物体在三维空间中的旋转。虽然它在背后有复杂的数学原理,但我们可以用简单的方式来理解它在游戏开发中的用途。
简单解释
你可以把 FRotationMatrix 想象成一个工具,它可以根据给定的旋转角度(例如角色的朝向)生成一个矩阵,这个矩阵可以用来计算角色在这个旋转角度下的前进方向、左右方向等信息。
具体怎么用?
在游戏中,角色不仅有位置,还会有方向(旋转角度)。当你让角色旋转后,你需要知道这个新的旋转角度下,角色的前是哪边,左又是哪边。
FRotationMatrix(YawNewRotator).GetUnitAxis(EAxis::X):获取角色朝向的前进方向(前)。FRotationMatrix(YawNewRotator).GetUnitAxis(EAxis::Y):获取角色的左右方向(左或右)。
实例讲解
在你提供的代码中,FRotationMatrix 是根据角色当前的旋转角度创建的,然后用它来获取角色的“前进”和“左右”方向。这个过程相当于告诉程序:
- 前进方向(
X轴):角色现在面朝的方向。 - 左右方向(
Y轴):角色左右两边的方向。
为什么需要 FRotationMatrix?
举个例子,如果角色面朝北方(0度),那么:
- 前进方向就是正北(+X)。
- 左右方向就是正东(+Y)。
但是如果角色转向了东边(90度),那么:
- 前进方向变成了正东(+X)。
- 左右方向变成了正南(+Y)。
你无法仅用一个简单的数字(角度)去描述这些复杂的方向变化,这时就需要通过 FRotationMatrix 来帮助计算这些方向。
核心理解
FRotationMatrix是用来处理物体旋转方向的工具。- 它会根据一个旋转角度,告诉你在这个角度下的“前进”和“左右”方向。
进一步解释
在数学中,矩阵是一种表示数据的方式,可以用来执行各种操作(比如旋转、缩放等)。在三维空间里,物体的旋转可以通过一个 3x3 的矩阵来表示。FRotationMatrix 背后的数学细节涉及矩阵的运算和线性代数,但你只需要知道它帮你计算了方向,你就可以利用这些方向来让角色移动。
不需要深入理解复杂的数学,你只需要知道它是用来帮助你根据角色的朝向,计算出前、后、左、右的方向。如果你有更多问题,或者想看看具体的例子,我可以进一步解释!
参考文档