UE5.1.1 C++ 从0开始 (1.人物移动)

开个天坑,UE5.1.1的移动代码做了一个大更新,对于我这种万年蓝图然后正在转C++的人来说可以说是个挑战也可以说是个更方便我去工作的一个点。同时斯坦福大学的那个教程的开头几个章节就不适用了,对于学习UE5.1.1的同学来说。所以我这里会尽量每天跟着斯坦福的教程走同时把学习到的东西(包括但不限于课堂的作业和ue的新特性如何使用的问题)写到博客上。

废话少说,先上对于我来说较为重磅的一个点:增强上下文输入

我在B站上面看到没人写,也没有人讲这个东西,所以干脆自己从官方的第三人称游戏入手,先看看官方的代码是怎么写的以及是怎么设置的。

官方的代码我这里就不重复输入了,我的博客里面有用中文注释写过一个我对于官方代码的理解,链接在这里

UE5.1.1版本第三人称模板Character C++文件分析

我分析完代码之后,想着自己上手先照着代码抄一遍加深理解,于是开了个空的项目从头开始实现这些功能。但是遇到了一个大问题,那就是一个报错。

请添加图片描述

解决方案:

错误原因一:

报错原因是组件的BlueprintReadOnly属性只能在private状态内声明,不然就会出错。

请添加图片描述

错误原因二:

我们的空项目内的Build.cs文件内是不会有EnhancedInput这个插件包的声明的,我们需要在AddRange函数后面加上这个包的包名。

请添加图片描述

以上两个问题是我在自己尝试重现功能的时候遇到的问题。

下面是我的创建的character类的.h文件以及.cpp文件

SCharacter.h文件

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
//需要在Build.cs文件中添加EnhancedInput路径,UE才能识别到InputActionValue.h头文件
#include "InputActionValue.h"
#include "SCharacter.generated.h"




UCLASS(config = Game)
class ACTIONROGUELIKE_API ASCharacter : public ACharacter
{
	GENERATED_BODY()

	UPROPERTY(VisibleAnywhere)
	class USpringArmComponent* SpringArmComp;

	UPROPERTY(VisibleAnywhere)
	class UCameraComponent* CameraComp;

	UPROPERTY(EditAnywhere, Category = Input)
	class UInputMappingContext* DefaultMappingContext;

	UPROPERTY(EditAnywhere,  Category = Input)
	class UInputAction* MoveAction;

	UPROPERTY(EditAnywhere,  Category = Input)
	class UInputAction* JumpAction;

public:
	// Sets default values for this character's properties
	ASCharacter();

protected:

		// Called when the game starts or when spawned
	virtual void BeginPlay() override;

protected:
	void Move(const FInputActionValue& Value);

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

};

SCharacter.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "SCharacter.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/Controller.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
//#include "../../../../../UE_5.1/Engine/Plugins/EnhancedInput/Source/EnhancedInput/Public/EnhancedInputSubsystems.h"
//#include "../../../../../UE_5.1/Engine/Plugins/EnhancedInput/Source/EnhancedInput/Public/EnhancedInputComponent.h"


// Sets default values
ASCharacter::ASCharacter()
{
 	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
	SpringArmComp->SetupAttachment(RootComponent);

	CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
	CameraComp->SetupAttachment(SpringArmComp);

}

// Called when the game starts or when spawned
void ASCharacter::BeginPlay()
{
	Super::BeginPlay();
	if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
	{
		if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
		{
			Subsystem->AddMappingContext(DefaultMappingContext, 0);
		}
	}

	
}

void ASCharacter::Move(const FInputActionValue& Value)
{
	FVector2D MovementVector = Value.Get<FVector2D>();

	if (Controller!=nullptr)
	{
		const FRotator Rotation = Controller->GetControlRotation();
		const FRotator YawRotation(0, Rotation.Yaw, 0);

		const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
		const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);

		AddMovementInput(ForwardDirection, MovementVector.Y);
		AddMovementInput(RightDirection, MovementVector.X);
	}
}

// Called every frame
void ASCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

// Called to bind functionality to input
void ASCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
	{
		EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ASCharacter::Move);
	}

}


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
对不起,我的回答中有误。在UE5.1.1中,uperarm_r的旋转坐标是由四个值构成的,分别是Roll、Pitch、Yaw和W。因此,需要将mediapipe的坐标系转换为UE5.1.1的左手坐标系,然后计算uperarm_r的四元数值,最后将四元数值赋给uperarm_r的旋转坐标。 具体的计算方法如下: 1. 将mediapipe的坐标系转换为UE5.1.1的左手坐标系。具体来说,需要将y坐标和z坐标取负,即将(0.546142, 0.315784, -0.148612)转换为(0.546142, -0.315784, 0.148612)。 2. 计算uperarm_r的旋转四元数值。具体来说,可以使用UE5.1.1中的FQuat::FindBetweenVectors函数来计算uperarm_r的方向向量和转换后的坐标的四元数值。具体的计算方法如下: ``` FVector ShoulderPos(0.546142, -0.315784, 0.148612); // 转换后的坐标 FVector UperarmDir(1.0f, 0.0f, 0.0f); // uperarm_r的方向向量 FQuat UperarmQuat = FQuat::FindBetweenVectors(UperarmDir, ShoulderPos.GetSafeNormal()); ``` 3. 将计算得到的uperarm_r的四元数值赋给uperarm_r的旋转坐标。具体来说,需要使用UE5.1.1中的USkeletalMeshComponent::SetBoneRotationByName函数来设置uperarm_r的旋转坐标。具体的代码如下: ``` USkeletalMeshComponent* SkeletalMeshComponent; // 需要替换成实际的SkeletalMeshComponent SkeletalMeshComponent->SetBoneRotationByName(TEXT("uperarm_r"), UperarmQuat, EBoneSpaces::WorldSpace); ``` 需要注意的是,以上计算过程中需要考虑坐标系的转换和旋转角度的顺序等因素,因此具体的计算方法可能会有所不同。建议在实际使用过程中,根据具体的需求和场景进行调整和优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楚江_wog1st

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值