一、曲线的基本概念和表现形式
关于曲线的定义、方程等长度等基本概念请移步百度百科《曲线》,这些都不是本文讨论的重点。本文将详细讨论如何在 UE4 中创建和应用曲线。
曲线是动画中非常重要的概念,可以表示物体的移动速度,加速度;可以表示物体颜色的变化;还可以表示物体的位置、旋转和缩放等等信息。曲线从本质上表示某些值随时间变化而变化,或者说,在某一时间点某一个值的大小。
曲线在 UE4 中也分为不同的类型,默认支持的主要有三种类型:
- CurveFloat
- CurveLinearColor
- CurveVector
分别表示浮点、线性颜色和向量三种数据类型组成的曲线。在 UE4 中创建曲线也非常简单,直接在 Content Browser 中右击> Miscelleneous > Curve 菜单中创建,见下图
创建完曲线后,双击即可编辑,此处以 CurveFloat 为例,横轴表示时间,纵轴表示值,在曲线上右击添加关键帧。
曲线已经创建好,那么如何在 UE4 中使用呢?
二、在蓝图中曲线资源
在蓝图中使用曲线比较简单,直接定义对应类型的变量即可,指定曲线,之后调用即可。
打开任意一个关卡蓝图(或者类蓝图)定义 CurveFloat 类型的变量((soft) class reference 和 (soft) object reference 的区别此处就不详细讲解啦)
然后指定要操作的曲线资源
接下来就是调用曲线资源的值。对于曲线资源都有一个 GetXXXValue 的方法(其中的XXX表示数据类型),如 CurveFloat 有一个 GetFloatValue 的方法,CurveVector 有一个 GetVectorValue 的方法。所以我们想要获取某一个时间点上的值直接调用该方法即可,具体的蓝图节点如下(此处为了测试只是打印出 0.5 秒处的值,只要能拿到这个值做什么都可以,哈哈哈哈哈)
三、在 C++ 中使用蓝图资源
上面我们讲解了在蓝图中使用曲线资源需要借助的类型分别是 CurveFloat 、 CurveLinearColor 和 CurveVector 三种类型,那么对应的 C++ 类又是什么类型呢?
如果熟悉 UE4 C++ 的明明方式的话很容易猜到,类前缀一般为 U 或者 A,此处我们想一下 Curve 类型继承自 UObject 更合情合理,所以猜测的结果是,三种曲线对应的类型分别为 UCurveFloat、UCurveLinearColor 和 UCurveVector。那么我们来验证一下,打开官方 API 文档,搜索即可找到如下图结果,
UCurveFloatapi.unrealengine.com/INT/API/Runtime/Engine/Curves/UCurveFloat/index.html
在 UE4 最新版本中更改了头文件的包含方式,所以我们需要知道某一个类型所在的头文件,上述链接中的文档内列出了需要包含的头文件和主要方法
接下来我们就要测试曲线资源啦,此处笔者新建了一个 Actor 子类,并借助 UPROPERTY 宏定义三种曲线属性,方便在编辑器中指定曲线资源。之后再 cpp 文件中调用了不同曲线资源的基本方法。具体的代码文件如下:
MyActor.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
UCLASS()
class REALTIME_API AMyActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMyActor();
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 = "Mantra|Tools")
class UCurveFloat* YourCurve;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Mantra|Tools")
class UCurveLinearColor* ColorCurve;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Mantra|Tools")
class UCurveVector* VectorCurve;
};
MyActor.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyActor.h"
#include "Kismet/GameplayStatics.h"
#include "Engine/World.h"
#include "Components/ActorComponent.h"
#include "Components/SceneComponent.h"
#include "Components/ArrowComponent.h"
#include "Curves/CurveFloat.h"
#include "Curves/CurveLinearColor.h"
#include "Curves/CurveVector.h"
// Sets default values
AMyActor::AMyActor()
{
// 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;
}
// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
Super::BeginPlay();
if (YourCurve != nullptr)
{
float value = YourCurve->GetFloatValue(.5f);
UE_LOG(LogTemp, Warning, TEXT("Value: %f"), value);
}
if (ColorCurve != nullptr)
{
FLinearColor CurrentColor = ColorCurve->GetLinearColorValue(.5f);
UE_LOG(LogTemp, Warning, TEXT("Value: %s"), *(CurrentColor.ToString()));
}
if (VectorCurve != nullptr)
{
FVector CurrentValue = VectorCurve->GetVectorValue(.5f);
UE_LOG(LogTemp, Warning, TEXT("Value: %s"), *(CurrentValue.ToString()));
}
}
// Called every frame
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
\