第 5 天:Tick() 函数揭秘,让你的游戏对象动起来!

🎯 目标:

掌握 UE5 中的 Tick() 函数,学习如何让 Actor 动态移动、旋转、缩放,实现游戏对象的实时更新!

1️⃣ 什么是 Tick() 函数?

Unreal Engine 5(UE5) 中,Tick(float DeltaTime) 是 Actor 每一帧都会执行的函数,用于持续更新对象状态,如:

  • 移动(不断调整位置)
  • 旋转(物体持续转动)
  • 动画更新(实时改变外观)
  • AI 行为(控制敌人移动、追踪玩家)

🔹 Tick() 的核心概念

  • DeltaTime:当前帧的时间间隔(秒),用于 帧率无关的平滑运动
  • 默认情况下,Tick 是禁用的,需要在 构造函数中启用

2️⃣ 如何在 C++ 中启用 Tick()

🔹 创建一个新的 Actor

  1. 在 UE5 中,点击 “工具” → “新建 C++ 类”
  2. 选择 Actor 作为基类,命名为 MovingActor。
  3. 创建并添加到项目,等待 UE5 生成代码并打开 Visual Studio
  4. 找到MovingActor,并将其拖入到场景中

🔹 在 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() 已成功启用!

3️⃣ 使用 Tick() 让 Actor 移动

现在,我们让 MovingActor 沿 X 轴前进,实现 持续移动

void AMovingActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

    FVector NewLocation = GetActorLocation();  
    NewLocation.X += 100 * DeltaTime;  // 每秒前进 100 单位
    SetActorLocation(NewLocation);
}

💡 解释:

  • GetActorLocation() 获取当前坐标。
  • NewLocation.X += 100 * DeltaTime; 每秒移动 100 单位。
  • SetActorLocation(NewLocation); 设置新位置。

运行游戏,Actor 将自动向前移动! 🎮

4️⃣ 使用 Tick() 让 Actor 旋转

如果想让 Actor 不断旋转,可以这样做:

void AMovingActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

    FRotator NewRotation = GetActorRotation();
    NewRotation.Yaw += 90 * DeltaTime;  // 每秒旋转 90 度
    SetActorRotation(NewRotation);
}

运行游戏,Actor 将持续旋转! 🔄

5️⃣ 使用 Tick() 让 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 将周期性地变大变小!

6️⃣ 优化 Tick() 性能

🔹 什么时候不应该使用 Tick()?
过度使用 Tick() 可能会影响游戏性能,尤其是在有 大量 Actor 需要更新时。如果 Actor 不需要每帧更新,可以使用:

  1. 定时器(Timers) 让对象 间隔执行,减少 Tick 负担:
GetWorldTimerManager().SetTimer(TimerHandle, this, &AMovingActor::SomeFunction, 2.0f, true); //

每 2 秒执行一次 SomeFunction(),而不是每帧调用 Tick()!

  1. 基于事件触发(Event-Driven),如 Overlap、输入等,而不是持续计算。

🔹 关闭 Tick() 以提升性能
如果对象 不再需要更新,可以 禁用 Tick

SetActorTickEnabled(false);

💡 这样可以显著提升游戏性能!

7️⃣ 常见问题 & 解决方案

问题解决方案
Tick() 没有触发确保 PrimaryActorTick.bCanEverTick = true;
Actor 速度太快或太慢调整 DeltaTime 乘数(如 X += 100 * DeltaTime;)
Actor 移动或旋转不正确检查 GetActorLocation() / GetActorRotation() 的使用方式
Tick() 影响性能使用定时器或事件触发代替 Tick()

🎯 总结:今天你学到了什么?

理解 Tick() 的作用(每帧执行更新)
让 Actor 移动、旋转、缩放
优化 Tick(),避免不必要的性能开销

👏 恭喜你完成 Tick() 学习! 🎮 明天我们将探索 输入控制(Input)让玩家控制游戏对象! 🚀

📌 记得收藏专栏,每天进步一点,最终独立开发属于你的 UE5 游戏! 🔥

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bluesonli

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值