本文介绍了如何创建一个能够改变颜色的光源Actor,并且在我们靠近后逐渐熄灭。
我们将用到点光源组件,该组建包含一个作为触发器的盒体组件,以及一个用于操控点光源Actor的时间轴组件。

创建能够熄灭的光源Actor
-
首先,点击 新建(New) > 游戏(Games) > 空白(Blank) > 蓝图(Blueprint) 创建名为 FadingLights 的项目。
-
点击 添加/导入(Add/Import) 按钮,新建一个蓝图 Actor 类,将其命名为 BP_LightActor。
-
在内容浏览器中双击该BP_LightActor,在蓝图编辑器中打开它,然后打开 类默认值(Class Defaults)。
-
点击"添加组件(Add Component)",在下拉菜单中选择 盒体碰撞(Box Collision),将其重命名为 OverlapCollision。
-
在组件(Components)选项卡中,选中碰撞体积,将他拖动到DefaultSceneRoot上,使OverlapCollision成为新的根组件。
-
点击添加组件(Add Component),搜索并选择 点光源(Point Light)。
-
打开 事件图表(Event Graph),右关键帧点击图表,然后在 蓝图上下文菜单(Blueprint Context Menu) 中选择 添加时间轴(Add Timeline)。将时间轴命名为 PointLightTimeline。
-
导航至 我的蓝图(My Blueprint) 选项卡,然后在 变量(Variables) 类别中点击 +变量(+ Variable) 按钮添加 浮点(float) 类型的新变量。将变量命名为 BrightnessMultiplier,进行编译并将其 默认值(Default Value) 设置为 20.0。
-
编译 并 保存。
设置亮度轨道
当玩家与光源Actor的盒体组件重叠时,时间轴组件将需要使用浮点曲线来操控点光源组件的亮度值。
亮度初始值5000,并将在5秒钟时间内下降到0。
-
双击 PointLightTimeline节点,打开时间轴编辑器,添加浮点曲线轨道。
-
将浮点曲线轨道命名为 LightBrightnessFloatTrack,然后按住 shift 关键帧再点击,将两个关键帧添加到轨道。为一个关键帧分配时间值 (0,5000),为另一个关键帧分配时间值 (5,0)。
-
完成后的LightBrightnessFloat轨道将如下所示。
设置颜色轨道
当玩家与光源Actor的盒体组件边界重叠时,PointLight时间轴将使用线性颜色曲线轨道来操控点光源组件的颜色属性。
-
在 时间轴编辑器(Timeline Editor) 中添加颜色曲线轨道。
-
将新颜色轨道命名为 LightLinearColorTrack。
-
双击第一个颜色关关键帧帧,将其时间值修改为 0,将 RGB 值修改为:(R:1,G:0.665,B:0.015)。
-
将第二个颜色关键帧的时间值修改为 5,将 RGB 值修改为:(R:0,G:0,B:0)。
-
编译 并 保存 蓝图。
-
完成后的颜色轨道将如下所示。
蓝图阶段成果

创建碰撞事件以及更新逻辑
我们需要能在盒体组件遇到Actor时触发TimelineComponent。
此外,PointLightTimeline需要更新逻辑来更改亮度和颜色。
-
在BP_LightActor的蓝图编辑器中,找到组件(Components)选项卡,选择OverlapCollision盒体组件。在细节面板中,向下滚动到"事件"类别,点击 在组件开始重叠时(On Component Begin Overlap) 事件旁的 + 图标。
-
拖动 On Component Begin Overlap(OverlapCollision) 节点的执行引脚,连接到PointTimelineComponent节点的播放引脚。
-
在组件(Components)选项卡中,选择 PointLight 组件并拖入 事件图表(Event Graph)。
-
拖动 PointLight 的引脚,在操作菜单搜索并选择 设置强度(Set Intensity)。
-
拖动 PointLightTimeline 节点的 光源亮度浮点轨道(Light Brightness Float Track) 引脚,在操作菜单搜索并选择 float * float。
-
在 我的蓝图(My Blueprint) 选项卡中,点击 BrightnessMultiplier 浮点变量并拖动到事件图表中,选择 获得亮度乘数(Get Brightness Multiplier),然后连接到 float float** 节点。
-
将 更新执行(Update Execution) 引脚连接到 Set Intensity 节点,然后将 float * float 节点的结果连到 新强度(New Intensity) 输入引脚。
-
拖动 PointLight 节点,然后在操作菜单中搜索并选择 设置光源颜色(Set Light Color)。
-
在 PointLightTimeline 节点中,拖动 光源线性(Light Linear) 颜色轨道(Color Track) 引脚,连接到 Set Light Color 节点的 新光源颜色(New Light Color) 引脚。然后,将 Set Intensity 节点中的 执行引脚(execution pin) 连接到 Set Light Color 节点。
-
编译 并 保存。
完成后的蓝图

关卡设置
为了充分演示代码的作用,请在关卡中删除所有光源。
-
首先,将你的 BP_LightActor 实例放入关卡。
-
导航至 世界大纲视图(World Outliner),然后选择 大气雾(Atmospheric Fog) Actor。从细节面板中导航至 太阳(Sun) 类别,将其 默认亮度(Default Brightness) 值设置为 0。
-
从世界大纲视图中删除 天空球体(Sky Sphere) Actor。
-
此外,从世界大纲视图中删除 光源Actor(Light Source Actor) 。
-
导航至 工具栏(Toolbar),然后选择 构建(Build),在关卡中重新构建光照。
-
生成光照后,关卡应该看起来和下面差不多。
最终效果
现在光源Actor和关卡已经设置完成,点击 PIE 并自动获操控旁观者Pawn。
你可以控制旁观者Pawn了,试着走进光源Actor的盒体碰撞体积。
时间轴组件播放功能触发后,光源应该会开始改变颜色和亮度,并在5秒内完成改变。

本文将介绍如何建立能够在接触时变色并随时间闪烁的光源Actor。
使用点光源组件组件可以实现此目的,组件中包含用作重叠触发器的盒体组件和用于操控点光源Actor的时间轴组件。

创建能够熄灭的光源Actor
-
基于 空白(Blank) 模板新建一个 C++ 项目,将项目命名为 FadingLights 。
点击查看大图。
-
找到 内容浏览器(Content Browser) ,点击 C++ Classes 文件夹,然后点击 添加(+)(Add [+]) 按钮并选择 新建C++类(New C++ Class) 。
点击查看大图。
-
选择 Actor 作为 父类(Parent Class) 。
点击查看大图。
-
将创建的Actor命名为 LightActor 。
点击查看大图。
-
创建新Actor时, Visual Studio 会自动打开
LightActor.h
和LightActor.cpp
文件。找到LightActor.h
文件,并声明以下内容:LightActor.h
#include "Components/TimelineComponent.h"
-
接下来,在
LightActor
类定义中添加以下代码:LightActor.h
public: UPROPERTY(EditAnywhere) UCurveFloat* PointLightFloatCurve; UPROPERTY(EditAnywhere) UCurveLinearColor* PointLightColorCurve; protected: //用于生成点光源组件动画的TimelineComponent。 UPROPERTY(VisibleAnywhere, BlueprintReadWrite) UTimelineComponent* LightTimelineComp; //将用作我们的距离重叠体积的盒体组件。 UPROPERTY(EditAnywhere, BlueprintReadWrite) class UBoxComponent* LightOverlapVolume; UPROPERTY(EditAnywhere,BlueprintReadWrite) class UPointLightComponent* PointLightComp; //用于点光源亮度的轨道 FOnTimelineFloat UpdateBrightnessTrack; //用于点光源颜色的轨道 FOnTimelineLinearColor UpdateColorTrack; //用于更新光源相对于UpdateBrightnessTrack的亮度的函数 UFUNCTION() void UpdateLightBrightness(float BrightnessOutput); //用于更新光源相对于UpdateColorTrack的颜色的函数 UFUNCTION() void UpdateLightColor(FLinearColor ColorOutput); UPROPERTY(EditDefaultsOnly) float BrightnessMultiplier;
-
找到
LightActor.cpp
并添加以下类库。LightActor.cpp
#include "Components/BoxComponent.h" #include "Components/PointLightComponent.h"
-
在
ALightActor::ALightActor
的构造函数中声明以下内容:LightActor.cpp
ALightActor::ALightActor() { // 将此Actor设置为每帧调用更新函数()。 如果不需要此特性,可以关闭以提升性能。 PrimaryActorTick.bCanEverTick = true; //创建我们的默认组件 PointLightComp = CreateDefaultSubobject<UPointLightComponent>(TEXT("PointLightComp")); LightTimelineComp = CreateDefaultSubobject<UTimelineComponent>(TEXT("LightTimelineComp")); LightOverlapVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("LightOverlapVolume")); //设置我们的附件 RootComponent = LightOverlapVolume; PointLightComp->AttachToComponent(LightOverlapVolume, FAttachmentTransformRules::KeepRelativeTransform); //初始化亮度乘数 BrightnessMultiplier = 20.0f; }
-
接下来,实现点光源组件的
Ufunction
方法:LightActor.cpp
void ALightActor::UpdateLightBrightness(float BrightnessOutput) { PointLightComp->SetLightBrightness(BrightnessOutput * 20.0f); } void ALightActor::UpdateLightColor(FLinearColor ColorOutput) { PointLightComp->SetLightColor(ColorOutput); }
-
然后,在
BeginPlay
方法中,添加以下代码:LightActor.cpp
void ALightActor::BeginPlay() { Super::BeginPlay(); //将我们的浮点和颜色轨道绑定到各自的函数。 UpdateBrightnessTrack.BindDynamic(this, &ALightActor::UpdateLightBrightness); UpdateColorTrack.BindDynamic(this, &ALightActor::UpdateLightColor); //如果有浮点曲线,将其图表绑定到我们的更新函数 if (PointLightFloatCurve) { LightTimelineComp->AddInterpFloat(PointLightFloatCurve, UpdateBrightnessTrack); } //如果有线性颜色曲线,将其图表绑定到我们的更新函数 if (PointLightColorCurve) { LightTimelineComp->AddInterpLinearColor(PointLightColorCurve, UpdateColorTrack); } }
-
编译你的代码。
91.在 内容浏览器(Content Browser) 中,找到 C++ Classes 文件夹。
10.右键点击 LightActor ,选择 基于LightActor创建蓝图类(Create Blueprint Class based on LightActor) ,并将蓝图Actor命名为 BP_LightActor 。

BP_LightActor的类默认值将按照如下方式显示:
点击查看大图。
阶段性代码
LightActor.h
//版权所有 1998-2022 Epic Games, Inc。保留所有权利。
#pragma once
#include "Components/TimelineComponent.h"
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "LightActor.generated.h"
UCLASS()
class FADINGLIGHTS_API ALightActor : public AActor
{
GENERATED_BODY()
public:
// 为此Actor的属性设置默认值
ALightActor();
protected:
// 当游戏开始或重生(Spawn)时调用
virtual void BeginPlay() override;
public:
// 每一帧都调用
virtual void Tick(float DeltaTime) override;
public:
UPROPERTY(EditAnywhere)
UCurveFloat* PointLightFloatCurve;
UPROPERTY(EditAnywhere)
UCurveLinearColor* PointLightColorCurve;
protected:
//用于生成点光源组件动画的TimelineComponent。
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
UTimelineComponent* LightTimelineComp;
//将用作我们的距离重叠体积的盒体组件。
UPROPERTY(EditAnywhere, BlueprintReadWrite)
class UBoxComponent* LightOverlapVolume;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
class UPointLightComponent* PointLightComp;
//用于点光源亮度的轨道
FOnTimelineFloat UpdateBrightnessTrack;
//用于点光源颜色的轨道
FOnTimelineLinearColor UpdateColorTrack;
//用于更新光源相对于UpdateBrightnessTrack的亮度的函数
UFUNCTION()
void UpdateLightBrightness(float BrightnessOutput);
//用于更新光源相对于UpdateColorTrack的颜色的函数
UFUNCTION()
void UpdateLightColor(FLinearColor ColorOutput);
UPROPERTY(EditDefaultsOnly)
float BrightnessMultiplier;
};
LightActor.cpp
//版权所有 1998-2022 Epic Games, Inc。保留所有权利。
#include "LightActor.h"
#include "Components/BoxComponent.h"
#include "Components/PointLightComponent.h"
// 设置默认值
ALightActor::ALightActor()
{
// 将此Actor设置为每帧调用更新函数()。 如果不需要此特性,可以关闭以提升性能。
PrimaryActorTick.bCanEverTick = true;
//创建我们的默认组件
PointLightComp = CreateDefaultSubobject<UPointLightComponent>(TEXT("PointLightComp"));
LightTimelineComp = CreateDefaultSubobject<UTimelineComponent>(TEXT("LightTimelineComp"));
LightOverlapVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("LightOverlapVolume"));
//设置我们的附件
RootComponent = LightOverlapVolume;
PointLightComp->AttachToComponent(LightOverlapVolume, FAttachmentTransformRules::KeepRelativeTransform);
//初始化亮度乘数
BrightnessMultiplier = 20.0f;
}
// 当游戏开始或重生(Spawn)时调用
void ALightActor::BeginPlay()
{
Super::BeginPlay();
//将我们的浮点和颜色轨道绑定到各自的函数。
UpdateBrightnessTrack.BindDynamic(this, &ALightActor::UpdateLightBrightness);
UpdateColorTrack.BindDynamic(this, &ALightActor::UpdateLightColor);
//如果有浮点曲线,将其图表绑定到我们的更新函数
if (PointLightFloatCurve)
{
LightTimelineComp->AddInterpFloat(PointLightFloatCurve, UpdateBrightnessTrack);
}
//如果有线性颜色曲线,将其图表绑定到我们的更新函数
if (PointLightColorCurve)
{
LightTimelineComp->AddInterpLinearColor(PointLightColorCurve, UpdateColorTrack);
}
}
// 每一帧都调用
void ALightActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ALightActor::UpdateLightBrightness(float BrightnessOutput)
{
PointLightComp->SetLightBrightness(BrightnessOutput * 20.0f);
}
void ALightActor::UpdateLightColor(FLinearColor ColorOutput)
{
PointLightComp->SetLightColor(ColorOutput);
}
创建并绑定碰撞重叠事件
盒体组件需要拥有在Actor进入其碰撞边界时触发 TimelineComponent 的能力。
-
找到
LightActor.h
文件的类定义,并在BrightnessMultiplier
下声明以下内容:LightActor.h
protected: UFUNCTION() void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
-
然后,找到
LightActor.cpp
文件并实施OnOverlapBegin
函数。LightActor.cpp
void ALightActor::OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) { LightTimelineComp->Play(); }
-
在
BeginPlay
方法中绑定重叠函数:LightActor.cpp
//将我们的盒体组件绑定到我们的光源Actor的重叠函数 LightOverlapVolume->OnComponentBeginOverlap.AddDynamic(this, &ALightActor::OnOverlapBegin);
-
编译你的代码。
已完成代码
LightActor.h
//版权所有 1998-2022 Epic Games, Inc。保留所有权利。
#pragma once
#include "Components/TimelineComponent.h"
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "LightActor.generated.h"
UCLASS()
class FADINGLIGHTS_API ALightActor : public AActor
{
GENERATED_BODY()
public:
// 为此Actor的属性设置默认值
ALightActor();
protected:
// 当游戏开始或重生(Spawn)时调用
virtual void BeginPlay() override;
public:
// 每一帧都调用
virtual void Tick(float DeltaTime) override;
public:
UPROPERTY(EditAnywhere)
UCurveFloat* PointLightFloatCurve;
UPROPERTY(EditAnywhere)
UCurveLinearColor* PointLightColorCurve;
protected:
//用于生成点光源组件动画的TimelineComponent。
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
UTimelineComponent* LightTimelineComp;
//将用作我们的距离重叠体积的盒体组件。
UPROPERTY(EditAnywhere, BlueprintReadWrite)
class UBoxComponent* LightOverlapVolume;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
class UPointLightComponent* PointLightComp;
//用于点光源亮度的轨道
FOnTimelineFloat UpdateBrightnessTrack;
//用于点光源颜色的轨道
FOnTimelineLinearColor UpdateColorTrack;
//用于更新光源相对于UpdateBrightnessTrack的亮度的函数
UFUNCTION()
void UpdateLightBrightness(float BrightnessOutput);
//用于更新光源相对于UpdateColorTrack的颜色的函数
UFUNCTION()
void UpdateLightColor(FLinearColor ColorOutput);
UPROPERTY(EditDefaultsOnly)
float BrightnessMultiplier;
protected:
UFUNCTION()
void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
};
LightActor.cpp
//版权所有 1998-2022 Epic Games, Inc。保留所有权利。
//在项目设置(Project Settings)的描述(Description)页面中填写版权声明。
#include "LightActor.h"
#include "Components/BoxComponent.h"
#include "Components/PointLightComponent.h"
// 设置默认值
ALightActor::ALightActor()
{
// 将此Actor设置为每帧调用更新函数()。 如果不需要此特性,可以关闭以提升性能。
PrimaryActorTick.bCanEverTick = true;
//创建我们的默认组件
PointLightComp = CreateDefaultSubobject<UPointLightComponent>(TEXT("PointLightComp"));
LightTimelineComp = CreateDefaultSubobject<UTimelineComponent>(TEXT("LightTimelineComp"));
LightOverlapVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("LightOverlapVolume"));
//设置我们的附件
RootComponent = LightOverlapVolume;
PointLightComp->AttachToComponent(LightOverlapVolume, FAttachmentTransformRules::KeepRelativeTransform);
//初始化亮度乘数
BrightnessMultiplier = 20.0f;
}
// 当游戏开始或重生(Spawn)时调用
void ALightActor::BeginPlay()
{
Super::BeginPlay();
//将我们的浮点和颜色轨道绑定到各自的函数。
UpdateBrightnessTrack.BindDynamic(this, &ALightActor::UpdateLightBrightness);
UpdateColorTrack.BindDynamic(this, &ALightActor::UpdateLightColor);
//如果有浮点曲线,将其图表绑定到我们的更新函数
if (PointLightFloatCurve)
{
LightTimelineComp->AddInterpFloat(PointLightFloatCurve, UpdateBrightnessTrack);
}
//如果有线性颜色曲线,将其图表绑定到我们的更新函数
if (PointLightColorCurve)
{
LightTimelineComp->AddInterpLinearColor(PointLightColorCurve, UpdateColorTrack);
}
//将我们的盒体组件绑定到我们的光源Actor的重叠函数
LightOverlapVolume->OnComponentBeginOverlap.AddDynamic(this, &ALightActor::OnOverlapBegin);
}
// 每一帧都调用
void ALightActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ALightActor::UpdateLightBrightness(float BrightnessOutput)
{
PointLightComp->SetLightBrightness(BrightnessOutput * 20.0f);
}
void ALightActor::UpdateLightColor(FLinearColor ColorOutput)
{
PointLightComp->SetLightColor(ColorOutput);
}
void ALightActor::OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
LightTimelineComp->Play();
}
设置亮度轨道
当玩家与光源Actor的盒体组件边界重叠时,时间轴组件将需要使用浮点曲线来操控点光源组件的亮度值。
亮度将具有初始值 5000 ,并将在 5 秒钟时间内下降到 0 。
-
找到 内容浏览器(Content Browser) ,选择 添加(+)(Add [+])> 杂项(Miscellaneous)> 曲线(Curve) 。
-
选择 CurveFloat 并将资产命名为 BrightnessCurveFloat 。
-
双击 BrightnessCurveFloat ,打开 时间轴编辑器(Timeline Editor) 。
-
在 图表(Graph) 上点击右键,然后选择 添加键(Add Key) ,为浮动曲线添加两个键。将第一个键的时间值调整为 (0, 5000) 。将第二个键的时间值调整为 (5, 0) 。你的 BrightnessCurveFloat 内容应如下所示:
点击查看大图。
-
保存 BrightnessCurveFloat ,然后回到 内容浏览器(Content Browser) ,双击 BP_LightActor 打开 类默认值(Class Defaults) 。
-
找到 细节(Details) 面板,从 点光源浮点曲线(Point Light Float Curve) 下拉菜单中选择 亮度曲线浮点(Brightness Curve Float) 。
-
点击 编译(Compile) 和 保存(Save) 按钮。
设置颜色轨道
当玩家与光源Actor的盒体组件边界重叠时,PointLight时间轴将需要使用线性颜色曲线轨道来操控点光源组件的颜色属性。
-
找到 内容浏览器(Content Browser) ,选择 添加(+)(Add [+])> 杂项(Miscellaneous)> 曲线(Curve) 。
-
选择 CurveLinearColor 并将资产命名为 LinearColorCurve 。
-
双击 LinearColorCurve ,打开 时间轴编辑器(Timeline Editor) 。
-
双击第一个颜色键进行修改,将 RGB 值修改为:( R :1, G: 0.665, B :0.015)。
点击查看大图。
-
双击第二个颜色键进行修改,将 RGB 值修改为:( R :0, G: 0, B :0)。
点击查看大图。
-
点击选择 图表(Graph) 上的第二个 点(Point) ,并将时间设置为 5 秒。
点击查看大图。
-
你的 LinearColorCurve 内容应如下所示:
点击查看大图。
-
保存 LinearColorCurve ,然后回到内容浏览器,双击 BP_LightActor 打开类默认值。
-
找到 细节(Details) 面板,从 点光源浮点曲线(Point Light Float Curve) 下拉菜单中选择 亮度曲线浮点(Brightness Curve Float) 。
-
点击 编译(Compile) 和 保存(Save) 按钮。
关卡设置
为了充分展示你编写的代码的功能,需要从关卡中删除所有光源Actor。
-
在 内容浏览器(Content Browser) 中,找到 BP_LightActor 资产,选中它并将其拖入 关卡(Level) 。
点击查看大图。
-
在 世界大纲视图(World Outliner) 中选择 BP_LightActor ,找到 细节(Details) 面板并将 位置(Location) 设置设为 (0, 0, 300) ,将 缩放(Scale) 设置设为 (10, 10, 10) 。
-
在 世界大纲视图(World Outliner) 中删除 定向光源Actor(DirectionalLight Actor) 。
-
关卡内容应如下所示。
点击查看大图。
最终结果
现在,光源Actor和关卡已经完成设置,点击 运行(PIE)(Play [PIE]) 即可自动持有旁观者Pawn。
你可以控制旁观者Pawn,可以找到光源Actor的盒体组件边界。
触发时间轴组件的播放功能之后,光源应该开始在5秒的时间跨度内变换颜色和亮度。
