LoginSignup
0
0

More than 3 years have passed since last update.

[UE4] チュートリアル時の試行錯誤 (変数、タイマー、イベント)

Last updated at Posted at 2020-08-21

背景

こちらの変数、タイマー、イベントのチュートリアルを見ながら実装したところ、コンパイルエラーが起きたので、直し方を書きます。

結論

  • GetWorldTimerManager()使う時は#include "TimerManager.h"を追加する
  • UTextRenderComponentなどコンポーネント使う時は、.hファイルにinclude忘れずに
  • .generated.hはincludeヘッダー群の一番最後に書く

コンパイルエラーがでたコード

CppTurorial2というプロジェクトにCountDown.hとCountDown.cppを実装しました。(チュートリアルではCountdown.cppと小文字である)

CountDown.h
// Copyright 1998-2018 Epic Games, Inc.All Rights Reserved.

#pragma once

#include "GameFramework/Actor.h"
#include "CountDown.generated.h"

UCLASS()
class CPPTUTORIAL2_API ACountDown : public AActor
{
    GENERATED_BODY()
public:
    // Sets default values for this actor's properties
    ACountDown();

protected:
    // Called when the game starts or when spawned (ゲーム開始時またはスポーン時に呼び出されます)
    virtual void BeginPlay() override;
public:

    // Called every frame (フレーム毎に呼び出されます)
    virtual void Tick(float DeltaSeconds) override;

    //How long, in seconds, the countdown will run
    int32 CountdownTime;

    UTextRenderComponent* CountdownText;

    void UpdateTimerDisplay();

    void AdvanceTimer();

    void CountdownHasFinished();

    FTimerHandle CountdownTimerHandle;
};
CountDown.cpp
// Copyright 1998-2018 Epic Games, Inc.All Rights Reserved.

#include "Components/TextRenderComponent.h"
#include "Countdown.h"

// Sets default values
ACountDown::ACountDown()
{
    // Set this actor to call Tick() every frame.You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = false;
    CountdownText = CreateDefaultSubobject<UTextRenderComponent>(TEXT("CountdownNumber"));

    CountdownText->SetHorizontalAlignment(EHTA_Center);
    CountdownText->SetWorldSize(150.0f);
    RootComponent = CountdownText;

    CountdownTime = 3;
}

// Called when the game starts or when spawned (ゲーム開始時またはスポーン時に呼び出されます)
void ACountDown::BeginPlay()
{
    Super::BeginPlay();
    UpdateTimerDisplay();

    GetWorldTimerManager().SetTimer(CountdownTimerHandle, this, &ACountDown::AdvanceTimer, 1.0f, true);
}

// Called every frame (フレーム毎に呼び出されます)
void ACountDown::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

}

void ACountDown::UpdateTimerDisplay()
{
    CountdownText->SetText(FString::FromInt(FMath::Max(CountdownTime, 0)));
}

void ACountDown::AdvanceTimer()
{
    --CountdownTime;
    UpdateTimerDisplay();
    if (CountdownTime < 1)
    {
        // We're done counting down, so stop running the timer.
        GetWorldTimerManager().ClearTimer(CountdownTimerHandle);
        //Perform any special actions we want to do when the timer ends.
        CountdownHasFinished();
    }
}

void ACountDown::CountdownHasFinished()
{
    //Change to a special readout
    CountdownText->SetText(TEXT("GO!"));
}

エラー内容

image.png

これを見ると

GetWorldTimerManager()UTextRenderComponentにエラーが出ています。

チュートリアル通りなのになぜ?調べてみた

GetWorldTimerManager()について

不完全な型は使用できません。でググると
https://docs.microsoft.com/ja-jp/cpp/c-language/incomplete-types?view=vs-2019

... わからん、メンバーがまだ指定されていない構造体型。なのか?

GetWorldTimerManager()でググると、

ちゃんと、#include "GameFramework/Actor.h"してるんだけどな...

UE4.20の記事、期待できそう。

サンプルコードを見てみると

#include "TimerManager.h"

お?試しに、CountDown.cppに追加して、ビルドしてみる。

image.png

不完全な型は使用できません。がなくなった!

UTextRenderComponentについて

同じく、includeのし忘れを疑ってみる。文字化けしてみれない...

UTextRenderComponentでググる

#include "Components/TextRenderComponent.h"かぁ、そういえばCountDown.hになかったな、追加してみよう。ビルド。

image.png

#include "CountDown.generated.h"はincludeヘッダの最後でなければならないらしい

#include "GameFramework/Actor.h"
#include "CountDown.generated.h"
#include "Components/TextRenderComponent.h"

ほんとだ

#include "GameFramework/Actor.h"
#include "Components/TextRenderComponent.h"
#include "CountDown.generated.h"

これでビルド。

やった正常終了!

image.png

再生すると?

image.png

ちゃんとGO!が表示されました。

最終コード

残りのチュートリアルもやってみた後のコード

CountDown.h
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/TextRenderComponent.h"
#include "CountDown.generated.h"

UCLASS()
class CPPTUTORIAL2_API ACountDown : public AActor
{
    GENERATED_BODY()

public: 
    // Sets default values for this actor's properties
    ACountDown();

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

public: 
    // Called every frame
    virtual void Tick(float DeltaTime) override;

    //How long, in seconds, the countdown will run
    UPROPERTY(EditAnywhere)
    int32 CountdownTime;
    UTextRenderComponent* CountdownText;
    void UpdateTimerDisplay();
    void AdvanceTimer();

    UFUNCTION(BlueprintNativeEvent)
    void CountdownHasFinished();
    virtual void CountdownHasFinished_Implementation();
    FTimerHandle CountdownTimerHandle;
};

CountDown.cpp



// Fill out your copyright notice in the Description page of Project Settings.


#include "CountDown.h"
#include "Components/TextRenderComponent.h"
#include "TimerManager.h"

// Sets default values
ACountDown::ACountDown()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = false;

    CountdownText = CreateDefaultSubobject<UTextRenderComponent>(TEXT("CountdownNumber"));
    CountdownText->SetHorizontalAlignment(EHTA_Center);
    CountdownText->SetWorldSize(150.0f);
    RootComponent = CountdownText;
    CountdownTime = 3;

}

// Called when the game starts or when spawned
void ACountDown::BeginPlay()
{
    Super::BeginPlay();
    UpdateTimerDisplay();
    GetWorldTimerManager().SetTimer(CountdownTimerHandle, this, &ACountDown::AdvanceTimer, 1.0f, true);

}

// Called every frame
void ACountDown::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

}

void ACountDown::UpdateTimerDisplay()
{
    CountdownText->SetText(FString::FromInt(FMath::Max(CountdownTime, 0)));
}

void ACountDown::AdvanceTimer()
{

    --CountdownTime;
    UpdateTimerDisplay();
    if (CountdownTime < 1) {
        GetWorldTimerManager().ClearTimer(CountdownTimerHandle);
        CountdownHasFinished();
    }
}

void ACountDown::CountdownHasFinished_Implementation() {
    CountdownText->SetText(TEXT("GO!"));

}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0