官方文档:虚幻引擎C++编程教程 | 虚幻引擎 5.5 文档 | Epic Developer Community | Epic Developer Community
提前告知(文章也有告知):对于创建新的类其初始具有的函数如果需对其进行override则需要进行SUPER::
1.物体上下起伏并旋转
1.1第一种写法
创建一个继承于Actor的类,并为新的Actor命名为FloatingActor,然后点击Create Class
重新加载代码文件
在Games->(用户自定义工程文件名)->Source->FloatingActor.h
在头文件添加代码
public:
// 设置构造默认函数
AFloatingActor();
UPROPERTY(VisibleAnywhere)
//使用继承于UObject的指针UStaticMeshComponent*
UStaticMeshComponent* VisualMesh;
在源文件:
//设置默认值
AFloatingActor::AFloatingActor()
{
//将设置为每帧调用Tick()。如果你不需要它,你可以关闭它来提高性能。
PrimaryActorTick.bCanEverTick = true;
//创建Object,可在蓝图details查看
VisualMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
VisualMesh->SetupAttachment(RootComponent);//根组件
//根组件另一种写法:RootComponent = VisualMesh;
//不推荐此写法
//静态网格体Copy Reference:/Script/Engine.StaticMesh'/Game/StarterContent/Shapes/Shape_Cone.Shape_Cone'
static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Cone.Shape_Cone"));
//判断是否初始化成功
if (CubeVisualAsset.Succeeded())
{
VisualMesh->SetStaticMesh(CubeVisualAsset.Object);
VisualMesh->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f));
}
}
void AFloatingActor::BeginPlay()
{
Super::BeginPlay();
//注意BeginPlay一定要调用Super::BeginPlay()
}
//调用每一帧
void AFloatingActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//初始化
FVector NewLocation = GetActorLocation();
FRotator NewRotation = GetActorRotation();
float RunningTime = GetGameTimeSinceCreation();//得到在世界的时间从创建开始
float DeltaHeight = (FMath::Sin(RunningTime + DeltaTime) - FMath::Sin(RunningTime)); //设置高度变化呈现正弦曲线变化
float DeltaRotation = DeltaTime * 20.0f; //Rotate by 20 degrees per second旋转变化
NewLocation.Z += DeltaHeight * 20.0f; //高度变化,系数放大20倍
NewRotation.Yaw += DeltaRotation;
SetActorLocationAndRotation(NewLocation, NewRotation);
}
最后在编辑器创建蓝图子类,并将子类拖进场景即可。(下面示例最后一步与此操作相同就不在说明)
思路:在默认构造函数初始化网格体,运用引擎内置函数SetStaticMesh和SetRelativeLocation。在Tick时间函数内先初始化状态信息,并运用数学函数改变状态数值,最后用SetActorLocationAndRotation函数实现Actor位置变化。
1.2第二种写法(初始化网格体)
在上述头文件添加新的代码 :
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Name")
UStaticMesh* NewMesh;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "FloatingActor")
float FloatSpeed = 20.0f;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "FloatingActor")
float RotationSpeed = 20.0f;
此写法是运用宏从而在蓝图进行快速修改
从而不需要前一种方法默认构造函数的指定网格体的写法:
//静态网格体Copy Reference:/Script/Engine.StaticMesh'/Game/StarterContent/Shapes/Shape_Cone.Shape_Cone'
static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Cone.Shape_Cone"));
在源文件的BeginPlay()函数处代码:
void AFloatingActor::BeginPlay()
{
Super::BeginPlay();
//注意BeginPlay一定要调用Super::BeginPlay()
//将原默认构造函数的判断放在这里
if (NewMesh)
{
VisualMesh->SetStaticMesh(NewMesh);
VisualMesh->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f));
}
}
2.相机自动切换
2.1第一种自定义相机切换
创建一个继承于Actor的类,并为新的Actor命名为LearnGameCamera,然后点击Create Class
重新加载代码文件
在Games->(用户自定义工程文件名)->Source->LearnGameCamera.h
在头文件添加代码
protected:
UPROPERTY(EditAnywhere, Category = "learn")
AActor* CameraOne;
UPROPERTY(EditAnywhere, Category = "learn")
AActor* CameraTwo;
float TimeToNextCameraChange=0.f;
使用宏可以在details进行相机绑定
在源文件的Tick()函数处代码(引用帧参数):
注意Tick函数需要Super!
// Called every frame
void ALearnGameCamera::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
const float TimeBetweenCameraChanges = 2.0f;//硬编码写法,在摄像机停留2s
const float SmoothBlendTime = 0.75f;// 视图混合平滑切换时间
TimeToNextCameraChange -= DeltaTime;
//下次更换相机的时间(判断是否触发相机切换机制)
if (TimeToNextCameraChange <= 0.0f)
{
TimeToNextCameraChange += TimeBetweenCameraChanges;
//查找本地玩家控制的Actor
APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this, 0);
判断玩家是否存在
if (OurPlayerController)
{
//视角不是摄像机1的视角且摄像机1不是空指针
if((OurPlayerController->GetViewTarget()!=CameraOne)&&(CameraOne!=nullptr))
{
//立即切换到摄像机1
OurPlayerController->SetViewTarget(CameraOne);
}
else if ((OurPlayerController->GetViewTarget() != CameraTwo) && (CameraTwo != nullptr))
{
//平滑切换到摄像机2
OurPlayerController->SetViewTargetWithBlend(CameraTwo, SmoothBlendTime);
}
}
}
}
思路:在C++代码进行相机定义,用蓝图宏去将其暴露,从而可在details进行相机绑定,用自定义的浮点数TimeToNextCameraChange去判断是否可以触发相机切换,运用UGameplayStatics的GetPlayerController(const UObject* WorldContextObject, int32 PlayerIndex) 进行查找玩家是否存在,如果存在进一步用GetViewTarget()函数判断视角是否为指定的相机且相机指针要存在。切换到另一个相机用SetViewTargetWithBlend()函数进行切换。
引擎源码函数片段
GetPlayerController():
GetViewTarget():
SetViewTargetWithBlend():
2.2遍历场景中的摄影机并依次显示
创建一个继承于Actor的类,并为新的Actor命名为LearnCameraDiectorModify,然后点击Create Class
重新加载代码文件
在Games->(用户自定义工程文件名)->Source->LearnCameraDiectorModify
在头文件添加代码
//定义结构体,用于后面容器存放摄像机的指针
USTRUCT()
struct FLearnToggleCamerInfo
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, Category = "learn")
AActor* CameraOne = nullptr;
UPROPERTY(EditAnywhere, Category = "learn")
float CameraBlendTime = 0.2f;//作为切换时间0.2s
};
//在类内添加
private:
//用容器存放摄像机指针
TArray<FLearnToggleCamerInfo>CameraInfoList;
float TimeToNextCameraChange = 0.f;
//定义摄像机的索引
int32 CameraIndex = 0;
在源文件的BeginPlay()函数处代码:
注意BeginPlay函数需要Super!
void ALearnCameraDirectorModify::BeginPlay()
{
Super::BeginPlay();
//存放摄像机
TArray<AActor*>MyCameraActors;
//获取ACameraActor类的对象然后将其输入到自定义的MyCameraActors容器
UGameplayStatics::GetAllActorsOfClass(this,ACameraActor::StaticClass(),MyCameraActors);
CameraInfoList.Empty();//容器元素清空初始化,但索引还在
//下列代码可以单独抽取出来作为一个方法更新场景里相机信息
check(MyCameraActors.Num() > 1);//用check判断如果不成立则用崩溃报错
//遍历场景摄像机并给其添加索引
for(int32 Index=0;Index<MyCameraActors.Num();Index++)
{
//向 CameraInfoList 添加一个新元素,并使用 FLearnToggleCamerInfo引用进行初始化。
FLearnToggleCamerInfo& CameraInfo = CameraInfoList.AddDefaulted_GetRef();
CameraInfo.CameraOne = MyCameraActors[Index];
}
}
在源文件的Tick()函数处代码(引用帧参数):
注意Tick函数需要Super!
void ALearnCameraDirectorModify::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
const float TimeBetweenCameraChanges = 2.0f;//硬编码写法,在摄像机停留2s
TimeToNextCameraChange -= DeltaTime;
if (TimeToNextCameraChange <= 0.0f)
{
TimeToNextCameraChange += TimeBetweenCameraChanges;
++CameraIndex;
if (CameraIndex > CameraInfoList.Num() - 1)//判断是否超出最大值
{
CameraIndex = 0;//索引为0,再次重新进入循环
}
}
//查找本地玩家控制的Actor
APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this, 0);
//运用结构体,通过索引进行相机指定
AActor* NextCamera = CameraInfoList[CameraIndex].CameraOne;
float NextBlendTime = CameraInfoList[CameraIndex].CameraBlendTime;
//判断玩家和相机是否存在
if(OurPlayerController&&NextCamera)//此处也可以这样写(OurPlayerController->GetViewTarget()!=NextCamera)&&(NextCamera!=nullptr)
{
OurPlayerController->SetViewTargetWithBlend(NextCamera, NextBlendTime);
}
}
获取场景摄像机思路:用结构体存放摄像机的指针,用TArray容器存放多个自定义结构体,并在BeginPlay函数内部创建TArray容器存放AActor*元素,通过GetAllActorsOfClass()获取ACameraActor类的对象然后将其输入到自定义存放AActor*元素的容器,然后用for循环,用FLearnToggleCamerInfo的类型的引用来获取CameraInfoLis容器t的索引,从而CameraInfo.CameraOne = MyCameraActors[Index]依次赋值。
引擎源码函数片段
GetAllActorsOfClass()
AddDefaulted_GetRef()
3.控制摄像机(放大、缩小、旋转、同时控制Pawn移动)
3.1第一种写法(全部动作在一个类实现)
先在编辑器进行映射绑定
Edit->Project Setting->Input(Engine)
注意:在MoveForward中-1.0表示反方向。
创建一个继承于Pawn的类,并为新的Actor命名为LearnPawnWithCamera,然后点击Create Class
重新加载代码文件
在Games->(用户自定义工程文件名)->Source->LearnPawnWithCamera.h
在头文件添加代码
protected:
// 输入函数(呈现承前启后的作用)处理动作映射
void MoveForward(float AxisValue);
void MoveRight(float AxisValue);
void PitchCamera(float AxisValue);//摄像机俯仰
void YawCamera(float AxisValue);//摄像机左右旋转
void ZoomIn();
void ZoomOut();
protected:
//对相机进行初始化定义
//前向声明class可以避免头文件重复而导致的冲突,或者在UCLASS()上一行加class UStaticMeshComponent,这样就不用在UStaticMeshComponent前加class
UPROPERTY(EditAnywhere)
class UStaticMeshComponent* StaticMeshComp;
UPROPERTY(EditAnywhere)
class USpringArmComponent* SpringArmComp;
UPROPERTY(EditAnywhere)
class UCameraComponent* CameraComp;
//输入变量
FVector2D MovementInput;
FVector2D CameraInput;
float ZoomFactor=1.0f;
bool bZoomingIn=false;
};
在类源文件中:
//添加头文件
#include "PlayerCamera/LearnPawnWithCamera.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include"Components/StaticMeshComponent.h"
#include "LearnPawnWithCamera.h"
对函数声明:
//对映射事件进行定义(此处还没与之前在编辑器设置的Input有关),此处只是对我们所命名的函数进行定义。
void ALearnPawnWithCamera::MoveForward(float AxisValue)
{
MovementInput.X = FMath::Clamp<float>(AxisValue, -1.0f, 1.0f);
}
void ALearnPawnWithCamera::MoveRight(float AxisValue)
{
MovementInput.Y = FMath::Clamp<float>(AxisValue, -1.0f, 1.0f);
}
void ALearnPawnWithCamera::PitchCamera(float AxisValue)
{
CameraInput.Y = AxisValue;
}
void ALearnPawnWithCamera::YawCamera(float AxisValue)
{
CameraInput.X = AxisValue;
}
void ALearnPawnWithCamera::ZoomIn()
{
bZoomingIn = true;
}
void ALearnPawnWithCamera::ZoomOut()
{
bZoomingIn = false;
}
将函数与我们在Input中设置的操作进行绑定:
注意SetupPlayerInputComponent()函数需要Super!
void ALearnPawnWithCamera::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
//承前操作{
// 绑定"ZoomIn"的事件
InputComponent->BindAction("ZoomIn", IE_Pressed, this, &ALearnPawnWithCamera::ZoomIn);
InputComponent->BindAction("ZoomOut", IE_Released, this, &ALearnPawnWithCamera::ZoomOut);
//为四条轴绑定事件(每帧调用)
InputComponent->BindAxis("MoveForward", this, &ALearnPawnWithCamera::MoveForward);
InputComponent->BindAxis("MoveRight", this, &ALearnPawnWithCamera::MoveRight);
InputComponent->BindAxis("CameraPitch", this, &ALearnPawnWithCamera::PitchCamera);
InputComponent->BindAxis("CameraYaw", this, &ALearnPawnWithCamera::YawCamera);
//}
}
此处绑定运用到引擎源码模板BindAxis(),观察此处的参数与我们在Input的命名,然后去看源码以理解参数。
在Tick()函数进行调用:
注意Tick函数需要Super!
void ALearnPawnWithCamera::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//如果按下了放大按钮则放大,否则就缩小(启后的操作)
if (bZoomingIn)
{
ZoomFactor += DeltaTime /0.5f; //Zoom in over half a second
}
else
{
ZoomFactor -= DeltaTime /0.25f; //Zoom out over a quarter of a second
}
ZoomFactor = FMath::Clamp<float>(ZoomFactor, 0.0f, 1.0f);//放大缩小视角限制
//根据ZoomFactor来设置摄像机的视场和弹簧臂的长度
CameraComp->FieldOfView = FMath::Lerp<float>(90.0f, 60.0f, ZoomFactor);
SpringArmComp->TargetArmLength = FMath::Lerp<float>(400.0f, 300.0f, ZoomFactor);
//此处花括号不能省去,否则会报错
{
//旋转Actor的偏转角度,这样摄像机也能旋转,因为摄像机与Actor相互绑定
FRotator NewRotation = GetActorRotation();
NewRotation.Yaw += CameraInput.X;
SetActorRotation(NewRotation);
}
{
// 旋转摄像机的俯仰角度,但要对其进行限制,这样我们就能始终俯视Actor
FRotator NewRotation = SpringArmComp->GetComponentRotation();
NewRotation.Pitch = FMath::Clamp(NewRotation.Pitch + CameraInput.Y, -80.0f, -15.0f);
SpringArmComp->SetWorldRotation(NewRotation);
}
// 基于"MoveX"和 "MoveY"坐标轴来处理移动
{
if (!MovementInput.IsZero())
{
// 把移动轴的输入数值放大100倍
MovementInput = MovementInput.GetSafeNormal() * 100.0f;
FVector NewLocation = GetActorLocation();
NewLocation += GetActorForwardVector() * MovementInput.X * DeltaTime;
NewLocation += GetActorRightVector() * MovementInput.Y * DeltaTime;
SetActorLocation(NewLocation);
}
}
}
此操作相当于三部分“声明——绑定——调用”(调用为承上启下的作用)
最后对相机组件进行定义:
ALearnPawnWithCamera::ALearnPawnWithCamera()
{
// 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;
//创建组件实例
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
StaticMeshComp = CreateDefaultSubobject <UStaticMeshComponent>(TEXT("MeshComponent"));
SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArmComponent"));
CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent"));
//绑定组件,注意其之间的联系
//在细节(Details)/子类蓝图处:LearnPawnWithCamera(Instance)->RootComponent(RootComponent)->StaticMeshComp(MeshComponent)->SpringArmComp(SpringArmComponent)->CameraComp(CameraComponent)
StaticMeshComp->SetupAttachment(RootComponent);
SpringArmComp->SetupAttachment(StaticMeshComp);
CameraComp->SetupAttachment(SpringArmComp, USpringArmComponent::SocketName);
//为SpringArm类的变量赋值。(设置弹簧臂)
SpringArmComp->SetRelativeLocationAndRotation(FVector(0.0f, 0.0f, 50.0f), FRotator(-60.0f, 0.0f, 0.0f));//注意-60.f为Y轴
SpringArmComp->TargetArmLength = 400.f;
SpringArmComp->bEnableCameraLag = true;
SpringArmComp->CameraLagSpeed = 3.0f;//延迟3s
//控制默认玩家
AutoPossessPlayer = EAutoReceiveInput::Player0;
}
此操作可在蓝图进行查看或修改:
思路:对摄像机进行属性定义,对移动映射进行定义绑定调用。
引擎源码片段
BindAction()
BindAxis()
FMath::Clamp<float>()
FMath::Lerp<float>()
3.2将处理函数独立出来作为一个组件类 (功能多了一个空格显示特效)
先在编辑器进行映射绑定
Edit->Project Setting->Input(Engine)
注意:在MoveForward中-1.0表示反方向。
创建一个继承于Pawn的类,并为新的Actor命名为LearnCollisionPawn,然后点击Create Class
重新加载代码文件
在Games->(用户自定义工程文件名)->Source->LearnCollisionPawn.h
在LearnCollisionPawn头文件添加代码
public:
virtual UPawnMovementComponent* GetMovementComponent() const override;
public:
UPROPERTY()
class UParticleSystemComponent* OurParticleSystem;
UPROPERTY()
class UCollisionPawnMovementComponent* OurMovementComponent;
//绑定方法
void MoveForward(float AxisValue);
void MoveRight(float AxisValue);
void Turn(float AxisValue);
void ParticleToggle();
创建一个继承于PawnMovementComponent的类,并为新的PawnMovementComponent命名为CollisionPawnMovementComponent,然后点击Create Class
重新加载代码文件
在Games->(用户自定义工程文件名)->Source->CollisionPawnMovementComponent.h
在CollisionPawnMovementComponent头文件添加代码:
public:
UPROPERTY()
class UParticleSystemComponent* OurParticleSystem;
UPROPERTY()
class UCollisionPawnMovementComponent* OurMovementComponent;
此组件相当于第一种写法示例的“处理函数”。
注意TickComponent函数需要Super!
//此函数相当于一个处理组件
void UCollisionPawnMovementComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
// 确保所有事物持续有效,以便进行移动。
if (!PawnOwner || !UpdatedComponent || ShouldSkipUpdate(DeltaTime))
{
return;
}
// 获取(然后清除)ACollidingPawn::Tick中设置的移动向量
FVector DesiredMovementThisFrame = ConsumeInputVector().GetClampedToMaxSize(1.0f) * DeltaTime * 150.0f;
if (!DesiredMovementThisFrame.IsNearlyZero())
{
FHitResult Hit;
SafeMoveUpdatedComponent(DesiredMovementThisFrame, UpdatedComponent->GetComponentRotation(), true, Hit);
// 若发生碰撞,尝试滑过去
if (Hit.IsValidBlockingHit())
{
SlideAlongSurface(DesiredMovementThisFrame, 1.f - Hit.Time, Hit.Normal, Hit);
}
}
}
在LearnCollisionPawn类源文件中,先确保组件头文件存在
#include "ComponentAndCollision/LearnCollisionPawn.h"
#include "UObject/ConstructorHelpers.h"
#include "Particles/ParticleSystemComponent.h"
#include "Components/SphereComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include"CollisionPawnMovementComponent.h"
在 LearnCollisionPawn类源文件中,先在默认构造函数进行网格体、摄像机、粒子系统等声明定义
// Sets default values
ALearnCollisionPawn::ALearnCollisionPawn()
{
// 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;
// 根组件将成为对物理反应的球体(此写法没有在头文件声明,不建议这样写)
USphereComponent* SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));
RootComponent = SphereComponent;
SphereComponent->InitSphereRadius(40.0f);
SphereComponent->SetCollisionProfileName(TEXT("Pawn"));
// 创建并放置网格体组件,以便查看球体位置
UStaticMeshComponent* SphereVisual = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));
SphereVisual->SetupAttachment(RootComponent);
//基于硬编码的资产路径一般不太推荐,例如这个示例中的球体静态网格体的路径;
static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));
if (SphereVisualAsset.Succeeded())
{
SphereVisual->SetStaticMesh(SphereVisualAsset.Object);
SphereVisual->SetRelativeLocation(FVector(0.0f, 0.0f, -40.0f));
SphereVisual->SetWorldScale3D(FVector(0.8f));
}
// 创建可激活或停止的粒子系统
OurParticleSystem = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("MovementParticles"));
OurParticleSystem->SetupAttachment(SphereVisual);
OurParticleSystem->bAutoActivate = false;
OurParticleSystem->SetRelativeLocation(FVector(-20.0f, 0.0f, 20.0f));
static ConstructorHelpers::FObjectFinder<UParticleSystem> ParticleAsset(TEXT("/Game/StarterContent/Particles/P_Fire.P_Fire"));
if (ParticleAsset.Succeeded())
{
OurParticleSystem->SetTemplate(ParticleAsset.Object);
}
// 使用弹簧臂给予摄像机平滑自然的运动感。
USpringArmComponent* SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraAttachmentArm"));
SpringArm->SetupAttachment(RootComponent);
SpringArm->SetRelativeRotation(FRotator(-45.f, 0.f, 0.f));
SpringArm->TargetArmLength = 400.0f;
SpringArm->bEnableCameraLag = true;
SpringArm->CameraLagSpeed = 3.0f;
// 创建摄像机并附加到弹簧臂
UCameraComponent* Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("ActualCamera"));
Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);
// 创建移动组件的实例,并要求其更新根组件。
OurMovementComponent = CreateDefaultSubobject<UCollisionPawnMovementComponent>(TEXT("CustomMovementComponent"));
OurMovementComponent->UpdatedComponent = RootComponent;
// 控制默认玩家
AutoPossessPlayer = EAutoReceiveInput::Player0;
}
同时对移动函数进行声明定义
void ALearnCollisionPawn::MoveForward(float AxisValue)
{
if (OurMovementComponent && (OurMovementComponent->UpdatedComponent == RootComponent))
{
OurMovementComponent->AddInputVector(GetActorForwardVector() * AxisValue);
}
}
void ALearnCollisionPawn::MoveRight(float AxisValue)
{
if (OurMovementComponent && (OurMovementComponent->UpdatedComponent == RootComponent))
{
OurMovementComponent->AddInputVector(GetActorRightVector() * AxisValue);
}
}
void ALearnCollisionPawn::Turn(float AxisValue)
{
FRotator NewRotation = GetActorRotation();
NewRotation.Yaw += AxisValue;
SetActorRotation(NewRotation);
}
//粒子系统
void ALearnCollisionPawn::ParticleToggle()
{
if (OurParticleSystem && OurParticleSystem->Template)
{
OurParticleSystem->ToggleActive();
}
}
然后进行移动映射绑定:
// Called to bind functionality to input
void ALearnCollisionPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
//作为中间连接
PlayerInputComponent->BindAction("ParticleToggle", IE_Pressed, this, &ALearnCollisionPawn::ParticleToggle);
PlayerInputComponent->BindAxis("MoveForward", this, &ALearnCollisionPawn::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &ALearnCollisionPawn::MoveRight);
PlayerInputComponent->BindAxis("Turn", this, &ALearnCollisionPawn::Turn);
}
对获取移动组件添加返回值即可
UPawnMovementComponent* ALearnCollisionPawn::GetMovementComponent() const
{
return OurMovementComponent;
}
大致思路和第一种写法类似,只是将移动处理函数独立出来作为移动组件,这种做法使得多个类可使用此移动组件。