この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
ページ更新者:T
更新日時:2026-06-11 07:10:02

タイトル: 毎秒実行するイベントの定義方法
SEOタイトル: UE5 毎秒実行 (Timer) 完全ガイド

この記事の要点
  • UE5 で「毎秒実行」は Set Timer by Event / Set Timer by Function Name で実装
  • パラメータ: Time = 1.0, Looping = true で 1 秒間隔ループ
  • FTimerHandle を保持して Clear Timer で停止
  • 毎フレーム実行は TickDeltaSeconds で時間正規化
  • 1 フレーム後の遅延実行は Set Timer for Next Tick(Latent ノード)

UE5 でタイマーを使う 3 つの方法

方法用途負荷
Set Timer by Event / Function Name一定間隔で実行 (1 秒毎、5 秒毎)軽い
Event Tick毎フレーム実行 (60〜120 回/秒)重い(軽い処理に限定)
Delay ノード (Latent)一回だけ N 秒後実行軽い

方法1: Set Timer by Event (Blueprint 推奨)

もっとも一般的。1 秒ごとにイベントを呼びたい場合:

Event BeginPlay
  → Set Timer by Event
    Event: [Custom Event "OnSecondTick"]
    Time: 1.0
    Looping: true
    → 戻り値の Handle 変数を保存

カスタムイベントを定義

Custom Event: OnSecondTick
  → Print String: "1 秒経過"
  → Stamina -= 1
  → Update HUD

方法2: Set Timer by Function Name (C++ 主流)

C++ では UWorld::GetTimerManager から取得する FTimerManager 経由で設定:

// MyCharacter.h
private:
    FTimerHandle SecondTickHandle;

    UFUNCTION()
    void OnSecondTick();

// MyCharacter.cpp
void AMyCharacter::BeginPlay()
{
    Super::BeginPlay();

    // 1 秒ごとに OnSecondTick() を呼ぶ
    GetWorld()->GetTimerManager().SetTimer(
        SecondTickHandle,
        this,
        &AMyCharacter::OnSecondTick,
        1.0f,    // 間隔 (秒)
        true     // ループ
    );
}

void AMyCharacter::OnSecondTick()
{
    UE_LOG(LogTemp, Log, TEXT("Tick at %.2f"), GetWorld()->GetTimeSeconds());
    Stamina = FMath::Max(0.0f, Stamina - 1.0f);
}

void AMyCharacter::EndPlay(const EEndPlayReason::Type Reason)
{
    // タイマー解除(リーク防止)
    if (UWorld* W = GetWorld())
    {
        W->GetTimerManager().ClearTimer(SecondTickHandle);
    }
    Super::EndPlay(Reason);
}

方法3: Set Timer for Next Tick

「1 フレームだけ遅延して実行」したい場合(次フレームに値を見たい等):

GetWorld()->GetTimerManager().SetTimerForNextTick(
    [this]()
    {
        // 次フレームで実行される
        UE_LOG(LogTemp, Log, TEXT("Next tick"));
    }
);

Tick イベント (毎フレーム実行)

1 秒に何度も実行したいなら Timer ではなく Tick。DeltaSeconds で正規化が必須:

void AMyActor::Tick(float DeltaSeconds)
{
    Super::Tick(DeltaSeconds);

    // ❌ 悪い例 (フレームレートで速度が変わる)
    // Position.X += 1.0f;

    // ✅ 良い例 (秒速で正規化)
    Position.X += Speed * DeltaSeconds;

    SetActorLocation(Position);
}

// Actor の Tick を有効化(コンストラクタで)
AMyActor::AMyActor()
{
    PrimaryActorTick.bCanEverTick = true;
    PrimaryActorTick.TickInterval = 0.0f; // 0 = 毎フレ
}

// 任意間隔の Tick (Timer 代替)
AMyActor::AMyActor()
{
    PrimaryActorTick.bCanEverTick = true;
    PrimaryActorTick.TickInterval = 0.5f; // 0.5 秒ごと
}

Timer の主要 API

関数説明
SetTimer(Handle, Obj, Func, Rate, bLoop, FirstDelay)タイマー開始
SetTimerForNextTick(Func)次フレーム実行
ClearTimer(Handle)停止
PauseTimer(Handle)一時停止
UnPauseTimer(Handle)再開
IsTimerActive(Handle)動作中か
GetTimerRemaining(Handle)残り時間
GetTimerElapsed(Handle)経過時間
GetTimerRate(Handle)設定間隔

具体的なユースケース

HP リジェネレーション

// 5 秒間ダメージを受けないと、1 秒ごとに +5 HP
void AMyCharacter::TakeDamageEvent(float Dmg)
{
    HP -= Dmg;

    // ダメージ受けたらリジェネ Timer 解除
    GetWorld()->GetTimerManager().ClearTimer(RegenHandle);

    // 5 秒後にリジェネ開始
    GetWorld()->GetTimerManager().SetTimer(
        RegenStartHandle,
        [this]()
        {
            GetWorld()->GetTimerManager().SetTimer(
                RegenHandle,
                this, &AMyCharacter::Regen,
                1.0f, true   // 1 秒ごとループ
            );
        },
        5.0f, false   // 5 秒後一回
    );
}

void AMyCharacter::Regen()
{
    HP = FMath::Min(MaxHP, HP + 5.0f);
}

スポーン処理 (3 秒ごとに敵生成)

void ASpawner::BeginPlay()
{
    Super::BeginPlay();

    GetWorld()->GetTimerManager().SetTimer(
        SpawnHandle,
        this, &ASpawner::SpawnEnemy,
        3.0f, true
    );
}

void ASpawner::SpawnEnemy()
{
    if (EnemyClass)
    {
        FActorSpawnParameters Params;
        GetWorld()->SpawnActor<AEnemy>(EnemyClass, GetActorLocation(), FRotator::ZeroRotator, Params);
    }
}

カウントダウン UI

void AMyController::StartCountdown(int32 Seconds)
{
    RemainingSeconds = Seconds;

    GetWorld()->GetTimerManager().SetTimer(
        CountdownHandle,
        this, &AMyController::TickCountdown,
        1.0f, true
    );
}

void AMyController::TickCountdown()
{
    RemainingSeconds--;
    UpdateHUD(RemainingSeconds);

    if (RemainingSeconds <= 0)
    {
        GetWorld()->GetTimerManager().ClearTimer(CountdownHandle);
        OnCountdownFinished();
    }
}

Niagara System での Tick 制御

パーティクル側で「毎秒スポーン」は Niagara の Spawn Rate モジュールを使うのが正解。Blueprint Timer で Activate / Deactivate を切り替える方法も:

// 毎秒パーティクル発射
GetWorld()->GetTimerManager().SetTimer(
    FXHandle,
    [this]()
    {
        UNiagaraFunctionLibrary::SpawnSystemAtLocation(
            this, FXSystem, GetActorLocation()
        );
    },
    1.0f, true
);

パフォーマンス注意

  • Timer はTick より大幅に軽い(必要なときだけ呼ばれる)
  • ただし大量に作るとマネージャ自体の負荷になるので、1 アクタに数個まで
  • Tick は最終手段。毎フレ更新が本当に必要か再考
  • 不要になった Timer は必ず ClearTimer(リークでメモリ・CPU 共に圧迫)
  • キャラ EndPlay / Destroy では Timer 自動解除されるが、念のため明示的に

FAQ

Q: Timer と Tick、結局どちらを使うべき?
A: 0.1 秒以上の周期なら Timer、毎フレ位置更新やアニメ補間なら Tick。判断基準は「FPS に関係するか」。

Q: タイマーが止まらない
A: FTimerHandle を保存し損ねている可能性大。SetTimer の戻り値(out 引数)を確実にメンバ変数として保持する。

Q: ゲームを一時停止すると Timer も止まる?
A: デフォルトでは止まります。SetTimerInPausedState やカスタム TimerManager で動作継続可能。