赞
踩
这里有官方文档介绍比较详细,我这边简单描述,重在实践。
时间轴(Timeline)可以实现从事件中播放基于时间的动画,这些事件可以沿着时间轴在关键帧处触发。可以使用时间轴来处理简单的非动画任务,例如开门、更改光源或对场景中的Actor执行其他以时间为中心的操纵。
关键组件:UTimelineComponent
包含一系列的 事件(events)、 浮点数(floats)、向量(vectors) 或 颜色(colors) 及其关联的关键帧。这些内容继承自UActorComponents
双击后可以添加浮点曲线等
创建一个继承于Actor的C++类 MyTimelineActor,在这个类里写Timeline相关逻辑。
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"))); }
编译之后,创建浮点曲线
这里添加的浮点曲线,相当于蓝图中添加的浮点曲线
右键,添加关键帧
保存之后,创建MyTimelineActor的蓝图类
添加刚才创建的浮点曲线
编译,保存之后,拖到场景中运行,打印日志
拷贝引用 门模型:/Script/Engine.StaticMesh’/Game/StarterContent/Architecture/Wall_400x400.Wall_400x400’
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<UStaticMesh> 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 ,调整一下
然后拖到场景中,摆放一下位置
点击运行,人物接触时门自动打开
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。