原视频地址:调整视角_哔哩哔哩_bilibili
MyPawn头文件
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "MyPawn.generated.h"
UCLASS()
class TEST_API AMyPawn : public APawn
{
GENERATED_BODY()
public:
// Sets default values for this pawn's properties
AMyPawn();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
UPROPERTY(VisibleAnywhere)
class UStaticMeshComponent* MyMesh;//模型
UPROPERTY(VisibleAnywhere)
class UCameraComponent* Camera;//摄像机
/*UPROPERTY(EditAnywhere)
FVector CurrentVelocity;//当前向量
UPROPERTY(EditAnywhere)
float MaxSpeed;//最大速度*/
UPROPERTY(VisibleAnywhere)
class USphereComponent* SphereComp;//球形组件
UPROPERTY(VisibleAnywhere)
class USpringArmComponent* SprintArmComp;//弹簧臂
UPROPERTY(VisibleAnywhere)
class UMyMovementComponent* MovementComp;
virtual UPawnMovementComponent* GetMovementComponent() const override;//重写
private:
void MoveForward(float Value);//向前函数
void MoveRight(float Value);//向右函数
void CameraPitch(float Value);//抬头低头
void CameraYaw(float Value);//左右看
FVector2D CameraInput;//记录CameraPitch和CameraYaw
};
MyPawn代码文件
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyPawn.h"
#include "Components/StaticMeshComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/SphereComponent.h"//球体头文件
#include "UObject/ConstructorHelpers.h"//help帮助
#include "GameFramework/SpringArmComponent.h"//弹簧臂头文件
#include "MyMovementComponent.h"
// Sets default values
AMyPawn::AMyPawn()
{
//RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));//设定根组件
// Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
/// <summary>
/// 根组件
/// </summary>
SphereComp = CreateDefaultSubobject<USphereComponent>(TEXT("Sphere"));//对象创建为球体
SphereComp->SetSphereRadius(80);//设置球体半径
SphereComp->SetCollisionProfileName(TEXT("BlockAll"));//设置球体碰撞
SphereComp->SetHiddenInGame(false);//设置可见性
SetRootComponent(SphereComp);
/// <summary>
/// 移动物体
/// </summary>
MyMesh = CreateDefaultSubobject<UStaticMeshComponent >(TEXT("Mesh"));//设定一个静态网格体
MyMesh->SetupAttachment(GetRootComponent());//将静态网格体绑定到根组件下
//将网格资源赋值给静态网格对象
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshComponentAsset(TEXT("StaticMesh'/Engine/EditorMeshes/ArcadeEditorSphere.ArcadeEditorSphere'"));
if (MeshComponentAsset.Succeeded()) {
MyMesh->SetStaticMesh(MeshComponentAsset.Object);//将资产赋值给模型
MyMesh->SetRelativeLocation(FVector(0, 0, -50));//设置在对象的相对位置
MyMesh->SetRelativeScale3D(FVector(0.2, 0.2, 0.2));//物体大小设置为0.2,0.2,0.2
}
/// <summary>
/// 弹簧臂组件
/// 更好的模拟运动
/// </summary>
SprintArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SprintArm"));
SprintArmComp->SetupAttachment(GetRootComponent());
SprintArmComp->TargetArmLength = 400;//弹簧臂长度
SprintArmComp->SetRelativeRotation(FRotator(-45.f, 0, 0));
SprintArmComp->bEnableCameraLag = true;//打开弹簧臂功能
SprintArmComp->CameraLagSpeed = 3;//弹簧臂速度
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));//摄像机实例化
Camera->SetupAttachment(SprintArmComp, USpringArmComponent::SocketName);//将摄像机插入弹簧臂的插槽中
//Camera->SetupAttachment(GetRootComponent());
//Camera->SetRelativeLocation(FVector(-300,0,300));
//Camera->SetRelativeRotation(FRotator(-45.f,0,0));
//CurrentVelocity = FVector(0.f);//当前速度
//MaxSpeed = 200.f;//最大速
AutoPossessPlayer = EAutoReceiveInput::Player0;//0号玩家
MovementComp = CreateDefaultSubobject <UMyMovementComponent>(TEXT("UMyMovementComponent"));
MovementComp->UpdatedComponent = RootComponent;//运动更新的组件设置为 “根组件”
CameraInput = FVector2D(0.f, 0);
}
// Called when the game starts or when spawned
void AMyPawn::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMyPawn::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//建议是下面这种写法,其他两种写法试过不行
//左右看
FRotator NewRotation = GetActorRotation();
NewRotation.Yaw += CameraInput.X;
SetActorRotation(NewRotation);
//上下看
FRotator NewSprintArmRotationUp = SprintArmComp->GetComponentRotation();
NewSprintArmRotationUp.Pitch += CameraInput.Y;
NewSprintArmRotationUp.Pitch = FMath::Clamp(NewSprintArmRotationUp.Pitch, -80.f, 80.f);
SprintArmComp->SetWorldRotation(NewSprintArmRotationUp);
//设定对象位置
SetActorLocation(GetActorLocation() + MovementComp->Velocity * DeltaTime);//设定对象位置
}
// Called to bind functionality to input
void AMyPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
/// <summary>
/// 绑定玩家输入
/// 橙色字——对应UE4的轴映射的字
/// this——应该是这个对象
/// 最后——UE4按键响应后传值给到这个方法
/// </summary>
PlayerInputComponent->BindAxis("MoveForward", this, &AMyPawn::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &AMyPawn::MoveRight);
PlayerInputComponent->BindAxis("CameraPitch", this, &AMyPawn::CameraPitch);
PlayerInputComponent->BindAxis("CameraYaw", this, &AMyPawn::CameraYaw);
}
#if 1
UPawnMovementComponent* AMyPawn::GetMovementComponent() const
{
//重写了移动组件,因为引用了mymovementcomponent的贴墙走
return MovementComp;
}
#endif
//前后左右移动
void AMyPawn::MoveForward(float Value)
{
//AddInputVector生产者,增加燃料。对应mymovementcomponent中的ConsumeInputVector()(消费者)
if (MovementComp) {
MovementComp->AddInputVector(GetActorForwardVector()*Value);
//UE_LOG(LogTemp, Warning, TEXT("@@s Hit@:x=%s,y=%s,z=%s"), *FString::SanitizeFloat(GetActorForwardVector().X), *FString::SanitizeFloat(GetActorForwardVector().Y), *FString::SanitizeFloat(GetActorForwardVector().Z));
}
//clamp约束数值在-1到1
//CurrentVelocity.X = FMath::Clamp(Value, -1.f, 1.f) * MaxSpeed;
}
void AMyPawn::MoveRight(float Value)
{
if (MovementComp) {
MovementComp->AddInputVector(GetActorRightVector()*Value);
}
}
//上下左右看
void AMyPawn::CameraPitch(float Value)
{
CameraInput.X = Value;
}
void AMyPawn::CameraYaw(float Value)
{
CameraInput.Y = Value;
}
MyMovementComponent头文件
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PawnMovementComponent.h"
#include "MyMovementComponent.generated.h"
/**
*
*/
UCLASS()
class TEST_API UMyMovementComponent : public UPawnMovementComponent
{
GENERATED_BODY()
public:
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)override;
};
MyMovementComponent代码文件
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyMovementComponent.h"
void UMyMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
//没有运动组件拥有者||运动更新时的依据组件||是否跳过更新(如果对象被遮挡就不会计算进行)
if (!PawnOwner||!UpdatedComponent|| ShouldSkipUpdate(DeltaTime)) {
return;
}
FVector DeltaMovement
= ConsumeInputVector().GetClampedToMaxSize(2) * DeltaTime * 150;
if (!DeltaMovement.IsNearlyZero()) {//检查DeltaMovement是否接近0
FHitResult HitResult;//碰撞结果
SafeMoveUpdatedComponent(DeltaMovement,
UpdatedComponent->GetComponentRotation(), true, HitResult);//开启了避险
//如果撞到东西,贴墙走
if (HitResult.IsValidBlockingHit()) {
/// <summary>
///
/// </summary>
/// <param name="DeltaTime">运动变化量</param>
/// <param name="1 - HitResult.Time">(照抄)</param>
/// <param name="HitResult.Normal">法向量</param>
/// <param name="HitResult">撞击信息</param>
SlideAlongSurface(DeltaMovement,
1 - HitResult.Time, HitResult.Normal, HitResult);
}
}
}