十九、完成玩家移动
在动画基类中添加更新属性方法
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中找问题
动画抖动到蓝图中找问题
移动方向不匹配 代码,项目设置