十九、完成玩家移动

在动画基类中添加更新属性方法

SlAiPlayerAnim

#pragma once

#include "CoreMinimal.h"
#include "Animation/AnimInstance.h"
#include "SlAiPlayerAnim.generated.h"

/**
 * 
 */
UCLASS()
class SLAICOURSE_API USlAiPlayerAnim : public UAnimInstance
{
    
    
	GENERATED_BODY()
	

public:

	USlAiPlayerAnim();

	virtual void NativeUpdateAnimation(float DeltaSeconds) override;
	
public:

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = PlayAnim)
		float Speed;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = PlayAnim)
		FRotator SpineRotator;

protected:

	//获取角色指针
	void InitSPCharacter();

	//更新属性
	virtual void UpdateParameter();

protected:

	//角色指针
	class ASlAiPlayerCharacter* SPCharacter;

};

#include "SlAiPlayerAnim.h"
#include "Player/SlAiPlayerCharacter.h"

USlAiPlayerAnim::USlAiPlayerAnim()
{
    
    
	Speed = 0.f;
	SpineRotator = FRotator(0.f, 0.f, 0.f);
}

void USlAiPlayerAnim::NativeUpdateAnimation(float DeltaSeconds)
{
    
    
	//初始化角色指针
	InitSPCharacter();
	//更新蓝图数据
	UpdateParameter();

}

void USlAiPlayerAnim::InitSPCharacter()
{
    
    
	if (!SPCharacter)
		SPCharacter = Cast<ASlAiPlayerCharacter>(TryGetPawnOwner());
}

void USlAiPlayerAnim::UpdateParameter()
{
    
    
	//如果不存在直接返回,避免空指针产生中断
	if (!SPCharacter) return;
	//设置速度
	Speed = SPCharacter->GetVelocity().Size();
	//定义上半身的旋转
	float SpineDir = SPCharacter->GetActorRotation().Yaw - 90.f;
	if (SpineDir > 180.f) SpineDir -= 360.f;
	if (SpineDir < -180.f) SpineDir += 360.f;
	SpineRotator = FRotator(0.f, SpineDir, 90.f);
}

子类中重写

SlAiThirdPlayerAnim

#include "CoreMinimal.h"
#include "Player/SlAiPlayerAnim.h"
#include "SlAiThirdPlayerAnim.generated.h"

/**
 * 
 */
UCLASS()
class SLAICOURSE_API USlAiThirdPlayerAnim : public USlAiPlayerAnim
{
    
    
	GENERATED_BODY()
	
	
public:
	USlAiThirdPlayerAnim();

protected:

	//重写更新属性方法
	virtual void UpdateParameter() override;

public:

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = PlayAnim)
		bool IsInAir;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = PlayAnim)
		float Direction;
	
};

#include "SlAiThirdPlayerAnim.h"
#include "Player/SlAiPlayerCharacter.h"
#include"GameFramework/CharacterMovementComponent.h"

USlAiThirdPlayerAnim::USlAiThirdPlayerAnim()
{
    
    
	//给方向赋值
	Direction = 0.f;
	//给是否在空中赋值
	IsInAir = false;
}

void USlAiThirdPlayerAnim::UpdateParameter()
{
    
    
	Super::UpdateParameter();

	//如果不存在直接返回,避免指针产生中断
	if (!SPCharacter) return;
	//获取是否在跳跃
	IsInAir = SPCharacter->GetCharacterMovement()->IsFalling();
	//速度朝向的Yaw旋转减去Actor朝向其实就是摄像机朝向的Yaw旋转得到的相对方向
	//修改前的角度
	float PreDir = SPCharacter->GetVelocity().ToOrientationRotator().Yaw - SPCharacter->GetActorRotation().Yaw;
	
	//修改后的角度
	if (PreDir > 180.f) PreDir -= 360.f;
	if (PreDir < -180.f) PreDir += 360.f;
	Direction = PreDir;
}

完成玩家移动

在角色类完成动作方法

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "SlAiPlayerCharacter.generated.h"

UCLASS()
class SLAICOURSE_API ASlAiPlayerCharacter : public ACharacter
{
    
    
	GENERATED_BODY()

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

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

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



public:	

	UPROPERTY(VisibleDefaultsOnly, Category = "SlAi")
		class USpringArmComponent* CameraBoom;

	UPROPERTY(VisibleDefaultsOnly, Category = "SlAi")
		class UCameraComponent* ThirdCamera;

	UPROPERTY(VisibleDefaultsOnly, Category = "SlAi")
		UCameraComponent* FirstCamera;

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


private:

	void MoveForward(float Value);
	void MoveRight(float Value);
	void LookUpAtRate(float Value);
	void Turn(float Value);
	void TurnAtRate(float Value);
	void OnStartJump();
	void OnStopJump();
	void OnStartRun();
	void OnStopRun();

private:

	//第一人称的骨骼模型
	UPROPERTY(VisibleDefaultsOnly, Category = "SlAi")
		class USkeletalMeshComponent* MeshFirst;

	//旋转比率
	float BaseLookUpRate;
	float BaseTurnRate;
	
};
#include "SlAiPlayerCharacter.h"
#include"ConstructorHelpers.h"
#include"Engine/SkeletalMesh.h"
#include"Components/SkeletalMeshComponent.h"
#include"Components/CapsuleComponent.h"
#include"GameFramework/SPringArmComponent.h"
#include"Camera/CameraComponent.h"
#include"GameFramework/CharacterMovementComponent.h"

// Sets default values
ASlAiPlayerCharacter::ASlAiPlayerCharacter()
{
    
    
 	// 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;


	//开始设置人物碰撞体的属性为PlayerProfile,下面的骨骼模型的碰撞都可以设置为无碰撞
	GetCapsuleComponent()->SetCollisionProfileName(FName("PlayerProfile"));

	//添加第一人称骨骼模型
	static ConstructorHelpers::FObjectFinder<USkeletalMesh> StaticMeshFirst(TEXT("SkeletalMesh'/Game/Res/PolygonAdventure/Mannequin/FirstPlayer/SkMesh/FirstPlayer.FirstPlayer'"));
	MeshFirst = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("MeshFirst"));
	MeshFirst->SetSkeletalMesh(StaticMeshFirst.Object);
	MeshFirst->SetupAttachment((USceneComponent*)GetCapsuleComponent());
	MeshFirst->bOnlyOwnerSee = true;
	MeshFirst->bReceivesDecals = false;
	MeshFirst->bCastDynamicShadow = false;
	//更新频率衰落
	//查一下
	MeshFirst->MeshComponentUpdateFlag = EMeshComponentUpdateFlag::OnlyTickMontagesWhenNotRendered;
	MeshFirst->PrimaryComponentTick.TickGroup = TG_PrePhysics;
	//设置碰撞属性
	MeshFirst->SetCollisionObjectType(ECC_Pawn);
	MeshFirst->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	MeshFirst->SetCollisionResponseToAllChannels(ECR_Ignore);
	//设置位移
	MeshFirst->SetRelativeLocation(FVector(0.f, 0.f, -95.f));
	MeshFirst->SetRelativeRotation(FQuat::MakeFromEuler(FVector(0.f, 0.f, -90.f)));

	

	//给默认Mesh添加骨骼模型
	static ConstructorHelpers::FObjectFinder<USkeletalMesh> StaticMeshThird(TEXT("SkeletalMesh'/Game/Res/PolygonAdventure/Mannequin/Player/SkMesh/Player.Player'"));
	//USkeletalMesh* Mesh = StaticMeshThird.Object;
	GetMesh()->SetSkeletalMesh(StaticMeshThird.Object);
	GetMesh()->bOnlyOwnerSee = true;
	GetMesh()->bReceivesDecals = false;
	GetMesh()->SetCollisionObjectType(ECC_Pawn);
	GetMesh()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	GetMesh()->SetCollisionResponseToAllChannels(ECR_Ignore);
	GetMesh()->SetRelativeLocation(FVector(0.f, 0.f, -95.f));
	GetMesh()->SetRelativeRotation(FQuat::MakeFromEuler(FVector(0.f, 0.f, -90.f)));


	//获取第三人称的动作蓝图
	static ConstructorHelpers::FClassFinder<UAnimInstance> StaticAnimThird(TEXT("AnimBlueprint'/Game/Blueprints/Player/ThirdPlayer_Animation.ThirdPlayer_Animation_C'"));
	GetMesh()->AnimClass = StaticAnimThird.Class;
	//获取第一人称的动作蓝图
	static ConstructorHelpers::FClassFinder<UAnimInstance> StaticAnimFirst(TEXT("AnimBlueprint'/Game/Blueprints/Player/FirstPlayer_Animation.FirstPlayer_Animation_C'"));
	MeshFirst->AnimClass = StaticAnimFirst.Class;

	//摄像机手臂
	CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
	CameraBoom->SetupAttachment(RootComponent);
	//设置距离
	CameraBoom->TargetArmLength = 300.f;
	//设置偏移
	CameraBoom->TargetOffset = FVector(0.f, 0.f, 60.f);
	//绑定Controller的旋转
	CameraBoom->bUsePawnControlRotation = true;

	//初始化第三人称摄像机
	ThirdCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("ThirdCamera"));
	ThirdCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);
	//设置ThirdCamera不跟随控制器的旋转
	ThirdCamera->bUsePawnControlRotation = false;

	//初始化第一人称摄像机
	FirstCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstCamera"));
	FirstCamera->SetupAttachment((USceneComponent*)GetCapsuleComponent());
	//设置跟随Controller的旋转
	FirstCamera->bUsePawnControlRotation = true;
	//设置位移
	FirstCamera->AddLocalOffset(FVector(0.f, 0.f, 60.f));

	//默认第三人称
	//SetOwnerNoSee设置所有者不可见
	ThirdCamera->SetActive(true);
	GetMesh()->SetOwnerNoSee(false);
	//不显示第一人称
	FirstCamera->SetActive(false);
	MeshFirst->SetOwnerNoSee(true);

	//初始化参数
	BaseTurnRate = 45.f;
	BaseLookUpRate = 45.f;
	//设置初始速度为150.f
	GetCharacterMovement()->MaxWalkSpeed = 150.f;
	
}

// Called when the game starts or when spawned
void ASlAiPlayerCharacter::BeginPlay()
{
    
    
	Super::BeginPlay();
	
}

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

}

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

	check(PlayerInputComponent);

	PlayerInputComponent->BindAxis("MoveForward", this, &ASlAiPlayerCharacter::MoveForward);
	PlayerInputComponent->BindAxis("MoveRight", this, &ASlAiPlayerCharacter::MoveRight);
	PlayerInputComponent->BindAxis("Turn", this, &ASlAiPlayerCharacter::Turn);
	PlayerInputComponent->BindAxis("LookUp", this, &ASlAiPlayerCharacter::LookUpAtRate);
	PlayerInputComponent->BindAxis("TurnRate", this, &ASlAiPlayerCharacter::TurnAtRate);

	PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ASlAiPlayerCharacter::OnStartJump);
	PlayerInputComponent->BindAction("Jump", IE_Released, this, &ASlAiPlayerCharacter::OnStopJump);
	PlayerInputComponent->BindAction("Run", IE_Pressed, this, &ASlAiPlayerCharacter::OnStartRun);
	PlayerInputComponent->BindAction("Run", IE_Released, this, &ASlAiPlayerCharacter::OnStopRun);

}



//前后移动
void ASlAiPlayerCharacter::MoveForward(float Value)
{
    
    
	if(Value != 0.f && Controller){
    
    
		const FRotator Rotation = Controller->GetControlRotation();
		FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X);
		AddMovementInput(Direction, Value);
	
	}
}

//左右移动
void ASlAiPlayerCharacter::MoveRight(float Value)
{
    
    
	if (Value != 0) {
    
    
		const FQuat Rotation = GetActorQuat();
		FVector Direction = FQuatRotationMatrix(Rotation).GetScaledAxis(EAxis::Y);
		AddMovementInput(Direction, Value);
	}
	
}

//视口移动
void ASlAiPlayerCharacter::LookUpAtRate(float Value)
{
    
    
	AddControllerPitchInput(Value * BaseLookUpRate * GetWorld()->GetDeltaSeconds());
}

void ASlAiPlayerCharacter::TurnAtRate(float Value)
{
    
    
	AddControllerYawInput(Value * BaseTurnRate * GetWorld()->GetDeltaSeconds());
}

void ASlAiPlayerCharacter::Turn(float Value)
{
    
    
	AddControllerYawInput(Value);
}

void ASlAiPlayerCharacter::OnStartJump()
{
    
    
	bPressedJump = true;
}

void ASlAiPlayerCharacter::OnStopJump()
{
    
    
	bPressedJump = false;
	StopJumping();
}

void ASlAiPlayerCharacter::OnStartRun()
{
    
    
	GetCharacterMovement()->MaxWalkSpeed = 375.f;
}

void ASlAiPlayerCharacter::OnStopRun()
{
    
    
	GetCharacterMovement()->MaxWalkSpeed = 150.f;
}

在控制类中设置输入模式

void ASlAiPlayerController::BeginPlay()
{
    
    
	Super::BeginPlay();
	//获取角色
	if (!SPCharacter)
	{
    
    
		SPCharacter = Cast<ASlAiPlayerCharacter>(GetCharacter());
	}

	//鼠标不显示
	bShowMouseCursor = false;
	//设置输入模式
	//不能设置为UIOnly
	//如果设置成UIOnly就不能转换成其他输入模式
	FInputModeGameOnly InputMode;
	InputMode.SetConsumeCaptureMouseDown(true);
	SetInputMode(InputMode);

	
}

注意

崩溃到代码构造函数跟BeginPlay中找问题
动画抖动到蓝图中找问题
移动方向不匹配 代码,项目设置

猜你喜欢

转载自blog.csdn.net/m0_51032168/article/details/121518361