任务:实现物体沿着二阶贝塞尔曲线运动
原理介绍参考链接:贝塞尔曲线 总结_PlayBoy's 部落格-CSDN博客_贝塞尔曲线
关键代码如下:
BezierCurve.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "BezierCurve.generated.h"
UCLASS()
class DATALEARN_API ABezierCurve : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ABezierCurve();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
private:
void SetMeshToBezierCurve(double curTime);
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "NPC|BezierCurve")
class UStaticMeshComponent* Mesh;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "NPC|BezierCurve")
class UStaticMeshComponent* StartMesh;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "NPC|BezierCurve")
class UStaticMeshComponent* FirstMesh;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "NPC|BezierCurve")
class UStaticMeshComponent* FinalMesh;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "NPC|BezierCurve")
FVector FirstPos;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "NPC|BezierCurve")
FVector FinalPos;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "NPC|BezierCurve")
float DurationTime;
private:
double StartTime;
};
BezierCurve.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "BezierCurve.h"
#include "Components/StaticMeshComponent.h"
#include "DrawDebugHelpers.h"
#include "Kismet/GameplayStatics.h"
// Sets default values
ABezierCurve::ABezierCurve()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
StartMesh = CreateDefaultSubobject<UStaticMeshComponent>("StartMesh");
RootComponent = StartMesh;
FirstMesh = CreateDefaultSubobject<UStaticMeshComponent>("FirstMesh");
FinalMesh = CreateDefaultSubobject<UStaticMeshComponent>("FinalMesh");
Mesh = CreateDefaultSubobject<UStaticMeshComponent>("Mesh");
DurationTime = 2000;
}
// Called when the game starts or when spawned
void ABezierCurve::BeginPlay()
{
Super::BeginPlay();
FirstPos = FirstMesh->GetRelativeLocation();
FinalPos = FinalMesh->GetRelativeLocation();
StartTime = FPlatformTime::ToMilliseconds64(FPlatformTime::Cycles64());
FVector actorLocation = GetActorLocation();
UWorld* myWorld = GetWorld();
DrawDebugLine(myWorld, actorLocation, actorLocation + FirstPos, FColor::Red, true);
DrawDebugLine(myWorld, actorLocation + FirstPos, actorLocation + FinalPos, FColor::Red, true);
}
// Called every frame
void ABezierCurve::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
double curTime = FPlatformTime::ToMilliseconds64(FPlatformTime::Cycles64());
SetMeshToBezierCurve(curTime);
}
void ABezierCurve::SetMeshToBezierCurve(double curTime)
{
float tmpT = fmod(curTime - StartTime, DurationTime) / DurationTime;
FVector resLocation;
resLocation.X = 2 * tmpT * (1 - tmpT) * FirstPos.X + tmpT * tmpT * FinalPos.X;
resLocation.Y = 2 * tmpT * (1 - tmpT) * FirstPos.Y + tmpT * tmpT * FinalPos.Y;
resLocation.Z = 2 * tmpT * (1 - tmpT) * FirstPos.Z + tmpT * tmpT * FinalPos.Z;
Mesh->SetRelativeLocation(resLocation);
FVector drawCenter = Mesh->GetRelativeLocation() + GetActorLocation();
UWorld* myWorld = GetWorld();
DrawDebugSphere(myWorld, drawCenter, 0.5, 10,FColor::Blue, false, 2);
}
效果如下图:
?
?
|