掌握 UE5 中的 Tick() 函数,学习如何让 Actor 动态移动、旋转、缩放,实现游戏对象的实时更新!
在 Unreal Engine 5(UE5) 中,Tick(float DeltaTime) 是 Actor 每一帧都会执行的函数,用于持续更新对象状态,如:
Tick() 的核心概念
创建一个新的 Actor
在 C++ 代码中启用 Tick
修改 MovingActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MovingActor.generated.h"
UCLASS()
class MYFIRSTCPPGAME_API AMovingActor : public AActor
{
GENERATED_BODY()
public:
AMovingActor();
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* MeshComponent;
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
};
修改 MovingActor.cpp
#include "MovingActor.h"
AMovingActor::AMovingActor()
{
PrimaryActorTick.bCanEverTick = true; // 启用 Tick()
MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
RootComponent = MeshComponent;
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Engine/BasicShapes/Cube.Cube"));
if (MeshAsset.Succeeded()) {
MeshComponent->SetStaticMesh(MeshAsset.Object);
}
}
void AMovingActor::BeginPlay()
{
Super::BeginPlay();
}
void AMovingActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
UE_LOG(LogTemp, Warning, TEXT("Ticking every frame! DeltaTime: %f"), DeltaTime);
}
运行后,你将在 Output Log 看到 “Ticking every frame!”,说明 Tick() 已成功启用!
现在,我们让 MovingActor 沿 X 轴前进,实现 持续移动:
void AMovingActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
FVector NewLocation = GetActorLocation();
NewLocation.X += 100 * DeltaTime; // 每秒前进 100 单位
SetActorLocation(NewLocation);
}
解释:
✅ 运行游戏,Actor 将自动向前移动!
如果想让 Actor 不断旋转,可以这样做:
void AMovingActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
FRotator NewRotation = GetActorRotation();
NewRotation.Yaw += 90 * DeltaTime; // 每秒旋转 90 度
SetActorRotation(NewRotation);
}
✅ 运行游戏,Actor 将持续旋转!
我们可以让 Actor 周期性地放大和缩小:
void AMovingActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
float Time = GetWorld()->GetTimeSeconds();
float ScaleFactor = FMath::Sin(Time) * 0.5f + 1.0f; // 生成 0.5 - 1.5 之间的缩放
SetActorScale3D(FVector(ScaleFactor));
}
✅ 运行游戏,Actor 将周期性地变大变小! ⚡
什么时候不应该使用 Tick()?
过度使用 Tick() 可能会影响游戏性能,尤其是在有 大量 Actor 需要更新时。如果 Actor 不需要每帧更新,可以使用:
GetWorldTimerManager().SetTimer(TimerHandle, this, &AMovingActor::SomeFunction, 2.0f, true); //
每 2 秒执行一次 SomeFunction(),而不是每帧调用 Tick()!
关闭 Tick() 以提升性能
如果对象 不再需要更新,可以 禁用 Tick:
SetActorTickEnabled(false);
这样可以显著提升游戏性能!
问题 | 解决方案 |
---|---|
Tick() 没有触发 | 确保 PrimaryActorTick.bCanEverTick = true; |
Actor 速度太快或太慢 | 调整 DeltaTime 乘数(如 X += 100 * DeltaTime;) |
Actor 移动或旋转不正确 | 检查 GetActorLocation() / GetActorRotation() 的使用方式 |
Tick() 影响性能 | 使用定时器或事件触发代替 Tick() |
✅ 理解 Tick() 的作用(每帧执行更新)
✅ 让 Actor 移动、旋转、缩放
✅ 优化 Tick(),避免不必要的性能开销
恭喜你完成 Tick() 学习! 明天我们将探索 输入控制(Input),让玩家控制游戏对象!
记得收藏专栏,每天进步一点,最终独立开发属于你的 UE5 游戏!