UE5 C++(十六)— Timeline的使用

文章目录

  • 介绍
  • 创建Timeline时间轴
    • 在蓝图中创建
    • 在C++中创建
  • 使用Timeline实现开关门

介绍

这里有官方文档介绍比较详细,我这边简单描述,重在实践。

时间轴(Timeline)可以实现从事件中播放基于时间的动画,这些事件可以沿着时间轴在关键帧处触发。可以使用时间轴来处理简单的非动画任务,例如开门、更改光源或对场景中的Actor执行其他以时间为中心的操纵。

关键组件:UTimelineComponent
包含一系列的 事件(events)、 浮点数(floats)、向量(vectors) 或 颜色(colors) 及其关联的关键帧。这些内容继承自UActorComponents

创建Timeline时间轴

在蓝图中创建

UE5 C++(十六)— Timeline的使用_第1张图片
双击后可以添加浮点曲线等
UE5 C++(十六)— Timeline的使用_第2张图片

在C++中创建

创建一个继承于Actor的C++类 MyTimelineActor,在这个类里写Timeline相关逻辑。UE5 C++(十六)— Timeline的使用_第3张图片
MyTimelineActor.h

#pragma once

#include "CoreMinimal.h"
#include "Components/TimelineComponent.h"
#include "GameFramework/Actor.h"
#include "MyTimelineActor.generated.h"

UCLASS()
class DEMO_API AMyTimelineActor : public AActor
{
	GENERATED_BODY()

public:
	// Sets default values for this actor's properties
	AMyTimelineActor();

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

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

	// 浮点数曲线
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MyCurve")
	UCurveFloat *MyCurveFloat;
	// 时间轴组件
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MySceneComponent")
	UTimelineComponent *MyTimeline;

	// 声明时间轴回调函数
	FOnTimelineFloat TimelineCallback;
	// 声明时间轴结束事件  时间轴事件(FOnTimelineEvent)是动态委托,为时间轴组件提供处理事件的能力
	FOnTimelineEvent TimelineFinishedCallback;

	// 时间轴开始函数
	UFUNCTION(BlueprintCallable, Category = "MyTimeline")
	void TimelineStart(float Value);
	// 时间轴结束函数
	UFUNCTION(BlueprintCallable, Category = "MyTimeline")
	void TimelineFinished();
};

MyTimelineActor.cpp


#include "MyTimelineActor.h"

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

	MyTimeline = CreateDefaultSubobject<UTimelineComponent>(TEXT("MyTimeline"));

}

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

	TimelineCallback.BindUFunction(this, FName("TimelineStart"));
	TimelineFinishedCallback.BindUFunction(this, FName("TimelineFinished"));
	// 绑定时间轴曲线
	MyTimeline->AddInterpFloat(MyCurveFloat, TimelineCallback);
	// 
	MyTimeline->SetLooping(false);
	MyTimeline->PlayFromStart();
	MyTimeline->Play();
	MyTimeline->SetTimelineFinishedFunc(TimelineFinishedCallback);
}

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

void AMyTimelineActor::TimelineStart(float Value)
{
	UE_LOG(LogTemp, Warning, TEXT("TimelineStart"));
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("TimelineStart")));
}
void AMyTimelineActor::TimelineFinished()
{
	UE_LOG(LogTemp, Warning, TEXT("TimelineFinished"));
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("TimelineFinished")));
}

编译之后,创建浮点曲线
UE5 C++(十六)— Timeline的使用_第4张图片
这里添加的浮点曲线,相当于蓝图中添加的浮点曲线
UE5 C++(十六)— Timeline的使用_第5张图片
右键,添加关键帧
UE5 C++(十六)— Timeline的使用_第6张图片
保存之后,创建MyTimelineActor的蓝图类
UE5 C++(十六)— Timeline的使用_第7张图片
添加刚才创建的浮点曲线
UE5 C++(十六)— Timeline的使用_第8张图片
编译,保存之后,拖到场景中运行,打印日志
UE5 C++(十六)— Timeline的使用_第9张图片

UE5 C++(十六)— Timeline的使用_第10张图片

使用Timeline实现开关门

拷贝引用 门模型:/Script/Engine.StaticMesh’/Game/StarterContent/Architecture/Wall_400x400.Wall_400x400’
UE5 C++(十六)— Timeline的使用_第11张图片
MyTimelineActor.h


#pragma once

#include "CoreMinimal.h"
#include "Components/TimelineComponent.h"
// 引入组件
#include "Components/SceneComponent.h"
#include "Components/StaticMeshComponent.h"
#include "Components/BoxComponent.h"
#include "MyCharacter.h"
#include "GameFramework/Actor.h"
#include "MyTimelineActor.generated.h"

UCLASS()
class DEMO_API AMyTimelineActor : public AActor
{
	GENERATED_BODY()

public:
	// Sets default values for this actor's properties
	AMyTimelineActor();

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

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

	// 浮点数曲线
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MyCurve")
	UCurveFloat *MyCurveFloat;
	// 时间轴组件
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MyScene")
	UTimelineComponent *MyTimeline;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MyScene")
	USceneComponent *MyScene;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MyScene")
	UStaticMeshComponent *MyStaticMesh;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MyScene")
	UBoxComponent *MyBox;

	//声明绑定碰撞函数
	UFUNCTION()
	void BeginOverlapFunction(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult);
	UFUNCTION()
	void EndOverlapFunction(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex);

	// 声明时间轴回调函数
	FOnTimelineFloat TimelineCallback;
	// 声明时间轴结束事件  时间轴事件(FOnTimelineEvent)是动态委托,为时间轴组件提供处理事件的能力
	FOnTimelineEvent TimelineFinishedCallback;

	// 时间轴开始函数
	UFUNCTION(BlueprintCallable, Category = "MyTimeline")
	void TimelineStart(float Value);
	// 时间轴结束函数
	UFUNCTION(BlueprintCallable, Category = "MyTimeline")
	void TimelineFinished();

	
};

MyTimelineActor.h

// Fill out your copyright notice in the Description page of Project Settings.

#include "MyTimelineActor.h"

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

	MyTimeline = CreateDefaultSubobject<UTimelineComponent>(TEXT("MyTimeline"));
	MyScene = CreateDefaultSubobject<USceneComponent>(TEXT("MyScene"));
	MyStaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MyStaticMesh"));
	MyBox = CreateDefaultSubobject<UBoxComponent>(TEXT("MyBox"));
	RootComponent = MyScene;
	MyStaticMesh->SetupAttachment(MyScene);
	MyBox->SetupAttachment(MyScene);
	MyBox->SetRelativeLocation(FVector(200.f, 0.f, 0.f));
	MyBox->SetBoxExtent(FVector(200.f, 80.f, 100.f));

	// note: 这段代码会导致UE5崩溃,原因未知 所以静态Mesh我在蓝图手动添加
	//  	// 添加门的模型
	//  	static ConstructorHelpers::FObjectFinder TempStaticMesh(TEXT("/Script/Engine.StaticMesh'/Game/StarterContent/Architecture/Wall_400x400.Wall_400x400'"));
	//  	if (TempStaticMesh.Succeeded())
	//  	{
	//  		MyStaticMesh->SetStaticMesh(TempStaticMesh.Object);
	//  	}
}

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

	TimelineCallback.BindUFunction(this, FName("TimelineStart"));
	TimelineFinishedCallback.BindUFunction(this, FName("TimelineFinished"));
	// 绑定时间轴曲线
	MyTimeline->AddInterpFloat(MyCurveFloat, TimelineCallback);
	//
	// MyTimeline->SetLooping(false);
	// MyTimeline->PlayFromStart();
	// MyTimeline->Play();
	MyTimeline->SetTimelineFinishedFunc(TimelineFinishedCallback);

	MyBox->OnComponentBeginOverlap.AddDynamic(this, &AMyTimelineActor::BeginOverlapFunction);
	MyBox->OnComponentEndOverlap.AddDynamic(this, &AMyTimelineActor::EndOverlapFunction);
}

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

void AMyTimelineActor::TimelineStart(float Value)
{
	UE_LOG(LogTemp, Warning, TEXT("TimelineStart"));
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("TimelineStart")));
	// 旋转门 动画
	float YawRotation = FMath::Lerp(0.f, 90.f, Value);
	MyStaticMesh->SetRelativeRotation(FRotator(0.f, YawRotation, 0.f));
}
void AMyTimelineActor::TimelineFinished()
{
	UE_LOG(LogTemp, Warning, TEXT("TimelineFinished"));
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("TimelineFinished")));
}

void AMyTimelineActor::BeginOverlapFunction(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult)
{
	AMyCharacter *MyCharacter = Cast<AMyCharacter>(OtherActor);
	UE_LOG(LogTemp, Warning, TEXT("BeginOverlapFunction"));
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("BeginOverlapFunction")));
	if (MyCharacter)
	{
		MyTimeline->PlayFromStart();
	}
}
void AMyTimelineActor::EndOverlapFunction(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex)
{
	AMyCharacter *MyCharacter = Cast<AMyCharacter>(OtherActor);
	if (MyCharacter)
	{
		MyTimeline->ReverseFromEnd();
	}
}

编译之后,打开蓝图BP_MyTimelineActor ,调整一下
UE5 C++(十六)— Timeline的使用_第12张图片
UE5 C++(十六)— Timeline的使用_第13张图片
然后拖到场景中,摆放一下位置
UE5 C++(十六)— Timeline的使用_第14张图片
点击运行,人物接触时门自动打开
UE5 C++(十六)— Timeline的使用_第15张图片

你可能感兴趣的:(UE5,C++,入门开发,ue5,c++,开发语言)