【Unreal Engine】BlueprintからC++への第一歩:回転する小物で3つのマクロを覚える

作成: 2025-12-12最終更新: 2026-09-07

Blueprint経験者向けに、最初のC++クラスを作る手順を図解。小物を回転させ、子Blueprintで速度を調整し、自作関数をノードから呼びます。.hと.cpp、UCLASS・UPROPERTY・UFUNCTION、ビルドとLive Codingを一つの実践でつなぎます。

C++で書いた変数は、いつもの詳細パネルに出せるのでしょうか。自分で書いた関数も、Blueprintのノードになるのでしょうか。

最初は、この2つを小さく試すところから始めましょう。この記事では 小物を回す処理をC++で作り、回転速度と止めるタイミングをBlueprintで決めます。 コードとノードが同じActorを動かすところまで、一つの題材で進めます。

C++の土台の上でBlueprintのノードを組み合わせるイメージ

この記事でわかること

  • 最初のC++クラスを作り、UEで使える形にビルドする
  • .hと.cpp、3つのマクロの役割を読み分ける
  • 子Blueprintの詳細パネルで、C++の回転速度を変える
  • 自作関数をノードから呼び、2秒後に止めて1秒後に再開する

BlueprintでActorを配置し、変数やイベントを使ったことがある人を想定しています。C++は初めてでも、まずは掲載した2ファイルを用意し、動きを見ながら読み解ける構成です。環境はWindowsとVisual Studioを使います。

Sponsored

今回は、C++とBlueprintで何を分けるか

完成すると、同じ形の小物が3つ並びます。1つはゆっくり、1つは速く回り、もう1つは止まったままです。回す計算は同じで、違うのは設定した速度だけです。

同じ小物が90度毎秒、360度毎秒、0度毎秒の3種類の速さで動く完成イメージ

親クラス は共通の作りを持つ設計図、子クラス はその作りを引き継いで調整する設計図です。今回はC++のRotatingItemを親にし、3つの子Blueprintを作ります。

担当今回書くこと
C++の親毎フレーム少しずつ回す。回す・止めるの切り替え口を用意する
子Blueprint見た目と速度を選ぶ。何秒後に止めるかをノードで組む
C++が回転処理を持ち、子Blueprintが速度と停止のタイミングを決める

この仕組み自体はBlueprintだけでも作れます。Blueprintにも継承・全体検索・差分表示があるので、「使い回したいから必ずC++」ではありません。

C++が役立つのは、たとえばBlueprintへ公開されていないAPIを使うときや、計算処理をテキストのコードで整理したいときです。速度の改善が目的なら、先に処理時間を測ることが大切です。ここでは速さの比較より、C++で書いた処理を、普段のBlueprintから使えるようにする ことを目標にします。

準備:最初のC++クラスを作る

1. C++をビルドする環境を用意する

Visual Studio Installerで「C++によるゲーム開発」など、利用中のUE版に必要な構成を入れます。Visual Studio・MSVC・Windows SDKには対応する組み合わせがあるため、Epicの環境構築ガイドでUEのバージョンを合わせて確認してください。

MSVCはC++のコードを実行できる形へ変換する道具、Windows SDKはWindows向けに作るための開発用部品です。初回はダウンロードとインストールがあるので、クラスを追加する前に済ませます。

2. Actorを親にして追加する

Third PersonのBlueprintプロジェクトを、名前 CppFirstStep で作ります。その中で「Tools → New C++ Class...」を開きます。

  1. 親クラスに「Actor」を選び、「Next」へ進む。
  2. 名前を RotatingItem にする。先頭にAは付けない。
  3. 配置先のモジュールはCppFirstStepを使う。モジュールは、まとめてビルドするコードのまとまりです。Publicを選ぶ場合は、そのまま生成された場所を使う。
  4. 「Create Class」を押し、自動ビルドが始まったら完了を待つ。

Actorを選ぶのは、レベルに置いて回したいから です。ウィザードには他の親もありますが、この実践では変更しません。Blueprintだけのプロジェクトも、C++クラスを追加するとビルドが必要なプロジェクトになります。

3. 2つのファイルを見つける

Visual Studioで RotatingItem.hRotatingItem.cpp を開きます。どちらもプロジェクトのSource以下にあります。

ファイル役割
.h:ヘッダーこのクラスが持つ変数と、呼べる関数を宣言する
.cpp:ソース関数を呼んだときに、実際に何をするかを書く
ヘッダーの宣言とソースの処理をビルドすると、UEで使えるクラスになる

たとえば「回すかどうかを変える関数があります」と書くのが.h、その関数の中で「回転中の印を書き換えます」と書くのが.cppです。2つで、1つのクラスを作ります。

生成されたコードのクラス名は ARotatingItem になります。先頭のAはActorを継承した型の目印です。ファイル名と、エディタで見えるRotatingItemにはAを付けません。

コードを書く:回転するActorの土台

自動ビルドが終わったらUEを保存して閉じ、Visual Studioは開いたままにします。生成された2ファイルを、次の内容へ置き換えます。別のプロジェクトで試す場合は、クラス宣言にある CPPFIRSTSTEP_API だけは、そのプロジェクトで生成された名前を残して ください。

表示する部品を指しておくのが MeshComponent、1秒あたりの回転角度が RotationSpeed、回転中かどうかが bSpinning です。ヘッダーでは、この3つと呼び出す関数を用意します。

RotatingItem.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "RotatingItem.generated.h"

class UStaticMeshComponent;

UCLASS(Blueprintable)
class CPPFIRSTSTEP_API ARotatingItem : public AActor
{
    GENERATED_BODY()

public:
    ARotatingItem();
    virtual void Tick(float DeltaTime) override;

    UFUNCTION(BlueprintCallable, Category = "Rotation")
    void SetItemSpinning(bool bEnabled);

protected:
    // 小物の見た目を表示する部品
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
    TObjectPtr<UStaticMeshComponent> MeshComponent;

    // 1秒あたりに回す角度
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Rotation")
    float RotationSpeed = 90.0f;

    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Rotation")
    bool bSpinning = true;
};

RotatingItem.cpp

#include "RotatingItem.h"
#include "Components/StaticMeshComponent.h"

ARotatingItem::ARotatingItem()
{
    PrimaryActorTick.bCanEverTick = true;

    MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
    SetRootComponent(MeshComponent);
    MeshComponent->SetMobility(EComponentMobility::Movable);
    MeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}

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

    if (bSpinning)
    {
        const float Angle = RotationSpeed * DeltaTime;
        AddActorLocalRotation(FRotator(0.0f, Angle, 0.0f));
    }
}

void ARotatingItem::SetItemSpinning(bool bEnabled)
{
    bSpinning = bEnabled;
}

処理を3つに分けて読む

最初の ARotatingItem::ARotatingItem()コンストラクタ です。オブジェクトを作るときの部品や初期設定を用意します。ここでは表示用のMeshComponentを作って中心の部品にし、動かせる状態にしています。今回は回転を見る小物なので、当たり判定は無効です。

Tick は、実行中に毎フレーム呼ばれる処理です。bCanEverTick=true で有効にし、Super::Tick で親Actorの処理も呼びます。続く if (bSpinning) は、「回転中なら中の処理へ進む」という条件です。

回転速度に前フレームからの経過秒を掛け、そのフレームで回す角度を決める

DeltaTimeは、前のフレームから経過した秒数 です。90度/秒にその秒数を掛けると、今回回す角度になります。60fps付近なら、1回で約1.5度。フレーム数が変わっても、経過時間に合う量を回せます。

FRotator は角度を持つ型で、C++の引数はPitch・Yaw・Rollの順です。今回は中央のYawへAngleを入れ、Actor自身の上方向の軸を中心に回します。小物は傾けずに配置して試します。

最後の SetItemSpinning は、渡されたtrue・falseをbSpinningへ入れるだけです。止める時刻は、この関数の外から決められます。 後でBlueprintからfalseを渡し、回転を止めます。

Sponsored

3つのマクロ:何をUEへ伝えているのか

コード中の UCLASSUPROPERTYUFUNCTION は、C++のクラス・変数・関数をUEに認識させるための印です。このように決まった処理へ展開される記述を マクロ と呼びます。

UEがクラスの構成を調べ、詳細パネルやBlueprintから扱えるようにする仕組みは リフレクション と呼ばれます。ここでは「C++で用意したものを、エディタへ伝える入口」と考えると読みやすくなります。

クラス・変数・関数にそれぞれのマクロを付け、使い方を指定してUEへ伝える
今回の記述この例でできること
UCLASS(Blueprintable)このクラスを元に子Blueprintを作る
UPROPERTY(EditAnywhere, BlueprintReadOnly)詳細パネルで速度を調整し、グラフでは値を読む
UFUNCTION(BlueprintCallable)SetItemSpinningをBlueprintのノードから呼ぶ

カッコ内の Blueprintable などを 指定子 と呼びます。「何を認識させるか」がマクロ、「どう使わせるか」が指定子です。UPROPERTYだけで詳細の編集やGet/Setが全部使えるわけではなく、必要な指定子を組み合わせます。

ほかの記号も、今回の読み方だけ押さえます。

記述今回の意味
: public AActorActorの機能を引き継ぐ
public: / protected:C++でのアクセス範囲。外から使う関数/自分と子で扱うメンバを分ける
float / bool小数を持つ型/true・falseを持つ型
90.0ffloat型の90。末尾のfはその型の印
void関数から値を返さない
ARotatingItem::RotatingItemの関数の中身を、ここに書くという指定

GENERATED_BODY().generated.h は、UEが生成するコードにつなぐために必要です。消さずに置き、.generated.hはヘッダー内の最後のinclude にします。CPPFIRSTSTEP_API は別のモジュールからこのクラスを使うための印で、最初は生成されたものをそのまま使います。

ビルドして、子Blueprintで回してみる

1. C++をビルドする

ビルド は、書いたコードを、UEが読み込んで実行できる形にする作業です。Blueprintの「Compile」ボタンとは別に行います。

  1. Visual Studioで2ファイルを保存する。UEが閉じていることを確認する。
  2. 構成を「Development Editor」、プラットフォームを「Win64」にする。
  3. Solution ExplorerでゲームのプロジェクトCppFirstStepを右クリックし、「Build」を実行する。
  4. Outputのビルド結果が成功になったら、CppFirstStep.uprojectを開く。
保存してUEを閉じ、Development EditorとWin64でビルドし、成功後に開き直す

Editorは「エディタから使うためのビルド」という意味です。失敗したらUEを開き直す前に、Outputに出た最初のエラーを確認します。コード上の赤い波線だけで判断せず、ビルド結果を見てください。

2. C++の子をBlueprintで作る

コンテンツブラウザの「C++ Classes → CppFirstStep」でRotatingItemを探します。見えない場合は設定の「Show C++ Classes」を有効にします。

RotatingItemを右クリックし、「Create Blueprint class based on RotatingItem」を選びます。Content以下に保存し、名前を BP_ItemSlow にします。

操作する場所設定
ComponentsのMeshComponent → Static MeshEngineのBasicShapesにあるCube
MeshComponent → TransformのScaleX=0.35、Y=0.6、Z=0.2を目安にする
MeshComponent → MobilityMovableになっていることを確認
Class Defaults → RotationRotation Speed=90

Cubeが見つからなければ、アセット選択欄の「Show Engine Content」を有効にします。形を横長にすると、回転して向きが変わる様子を見分けやすくなります。

Class Defaultsは、この子Blueprintから作る小物の初期設定 です。C++に書いたRotationSpeedが、ここでは「Rotation Speed」と表示されます。コンパイル・保存し、レベルの床から少し浮いた、Player Startの前方に配置してPlayします。

小物が回れば、C++の処理が子Blueprintでも動きました。止める実験はまだ追加していないので、90度/秒なら、360÷90=4秒で1回転します。

3. 同じ親から、速度の違う子を作る

BP_ItemSlowを複製して BP_ItemFastBP_ItemStill を作ります。どちらも親はC++のRotatingItemのままです。各Class Defaultsで速度を変え、3つを離して並べます。

子BlueprintRotation Speed期待する動き
BP_ItemSlow904秒で1回転
BP_ItemFast3601秒で1回転
BP_ItemStill0止まったまま

3つとも同じ回転処理を使っています。速度を変えるたびにC++をビルドする必要はなく、子Blueprintの値を変えて試せます。 別の見た目のアセットがあれば、Static Meshだけ差し替えてみても構いません。

EditとRead:編集する場所を分ける

RotationSpeedには、次の2つを付けました。

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Rotation")
float RotationSpeed = 90.0f;

EditAnywhereは詳細パネル、BlueprintReadOnlyはグラフ のための指定です。別々の場所を開く扉だと考えると、組み合わせる理由が分かります。

同じRotationSpeedでも、詳細で編集する指定とグラフで読む指定は別になる
詳細パネル側の指定子編集できる場所
EditAnywhereクラスの初期設定と、レベルに置いた個体
EditDefaultsOnlyクラスの初期設定だけ
EditInstanceOnlyレベルに置いた個体だけ
VisibleAnywhere表示して確認するだけ
グラフ側の指定子Blueprintでできること
BlueprintReadOnlyGetで読む
BlueprintReadWriteGetで読み、Setで書き換える

今回は「作るときに速度を調整し、実行中は勝手に書き換えない」という設定にしました。グラフでRotation Speedを探すとGetは使えますが、直接値を変えるSetは使えません。Category="Rotation" は、関連する項目をまとめる見出しです。

レベル上のBP_ItemSlowを選び、その個体だけRotation Speed=180にすると、2秒で1回転します。他の個体やBP_ItemSlowのClass Defaultsは90のままです。試した後は、値の横のリセット矢印で初期値へ戻してください。

MeshComponentのVisibleAnywhereは、参照する部品そのものを別の部品へ差し替えない 指定です。その部品を選び、中のStatic MeshやScaleを調整することとは別なので、先ほどの見た目の設定は行えます。

Sponsored

自作関数をノードから呼び、少しだけ止める

C++の SetItemSpinning を、BP_ItemSlowから呼びます。動かすと「2秒回る→1秒止まる→また回り続ける」小物になります。BP_ItemFastとBP_ItemStillはそのままです。

BP_ItemSlowのEvent Graphで、Event BeginPlayから次の白い線をつなぎます。既にBeginPlayがある場合は、それを使います。

  1. Delay(Duration=2.0)へつなぐ。
  2. Completedから「Set Item Spinning」を呼び、Enabledをfalseにする。
  3. 続けて別のDelay(Duration=1.0)へつなぐ。
  4. Completedからもう一度Set Item Spinningを呼び、Enabledをtrueにする。
BeginPlayから2秒待ち、自作のSet Item Spinningへfalseを渡す

止めたあとは、同じ関数で再開させます。

停止の続きで1秒待ち、自作関数へtrueを渡して再開する

2枚の図のAは、続く白い線の目印です。Aというノードは作りません。Set Item SpinningのTargetは Self、つまりこのBP_ItemSlow自身 です。別の小物を止めたい場合は、その小物をTargetとして渡す必要があります。

Enabledは、C++の引数 bEnabled に対応します。Blueprintではbが省かれた名前で表示されます。チェックなしがfalse、チェックありがtrueです。falseを渡すとbSpinningがfalseになり、Tickの中の回転処理を通らなくなります。trueを渡すと、また回ります。

コンパイル・保存してPlayし、開始から2秒後に止まり、さらに1秒後に動き出すことを確かめます。Delayの2.0を5.0へ変えれば、止まるまでの時間も変わります。C++は「どう止めるか」、Blueprintは「いつ止めるか」を担当 しているため、タイミングの調整はノードだけでできます。

関数が検索に出なければ、UFUNCTIONにBlueprintCallableがあるか、C++のビルドが成功したか、BP_ItemSlowの親がRotatingItemかを確認します。bSpinningを直接Setするノードではなく、今回作ったSet Item Spinningを選んでください。

変更を反映する:ビルドとLive Coding

慣れてきたら、C++の小さな変更を Live Coding で反映できます。これはUEを開いたままC++をビルドし、動作中のプログラムへ変更を取り込む仕組みです。有効な状態で Ctrl + Alt + F11 を押し、Live Codingの画面で成功を確認します。

関数内の小さな変更はLive Codingで試し、構成や初期設定の変更は閉じてビルドして確認する
変更するもの最初のうちの進め方
BPの回転速度やDelayBPをコンパイル・保存してPlay
.cppの関数内の計算Live Codingで反映して動きを確認
変数・関数・親クラスの追加や変更UEを閉じ、Development Editorでビルドして開き直す
コンストラクタでの部品・初期設定UEを閉じてビルドし、新しい個体でも確認

Live Codingにもクラス構成の変更を扱う仕組みがあるので、「.hは絶対に反映できない」という制限ではありません。 ここでは、初めての変更が反映されたかを判断しやすくするため、構成を変えたら閉じてビルドする手順にそろえています。

また、C++の初期値を直しても、子Blueprintや配置済みの個体で上書きした値が残ることがあります。「ビルドに失敗した」と決める前に、どの場所で値を設定しているかも確認します。

うまく動かないとき

症状確認するところ
ビルドが失敗するOutputの最初のエラー、APIマクロ名、ファイル名、.generated.hのinclude順、開いたままのUE
C++ Classesに見えないビルド成功、プロジェクトの開き直し、Show C++ Classes
小物が見えないStatic Meshの指定、Scale、配置位置、カメラの向き
回らないRotation Speedが0でないか、Movable、Tickの有効化、Spinningがtrueか
値を変えたのに速度が違う別の子BPを編集していないか、配置した個体で上書きしていないか
2秒後に止まらないEvent BeginPlayからの白い線、Enabled=false、Target=Self
再開しない2個目のDelayのCompleted、Enabled=true

おまけ:次に知っておくと役立つこと

部品への参照とTObjectPtr

TObjectPtr<UStaticMeshComponent> は、「作った表示部品を指しておく変数」です。毎回部品を作り直すのではなく、MeshComponentから同じ部品を指定できます。-> は、その参照先の機能を呼ぶときに使っています。

UObject系のオブジェクトをメンバ変数で保持する場合、UPROPERTYを付けたTObjectPtrを使うと、UEがその参照を追跡できます。これは不要なオブジェクトを回収する ガベージコレクション にも関わります。最初は、この例のように部品への参照を残す形を覚えると進めやすくなります。

関数から値を読む・Blueprintへ処理を任せる

UFUNCTIONには、今回のBlueprintCallableのほかに次の指定もあります。

指定子使う場面
BlueprintPure値を変えずに計算結果などを返す。白い実行線を使わない
BlueprintImplementableEventC++から呼ぶ処理の中身を、子Blueprintで作る

たとえば「回転を止めたときに光らせる」演出を子ごとに変えたいなら、C++で呼ぶタイミングを決め、Blueprint側へ演出を任せる形に広げられます。まずは今回のCallableで、C++の関数がノードになるところを押さえましょう。

既存のBlueprintへ広げる前に

今回のように新しい子を作るほか、既存Blueprintの親を変更する方法もあります。ただし同名の変数や初期値の引き継ぎを確認する必要があるため、最初はコピーで試します。共通部分をComponentへ分ける方法や、Data Assetの型からC++を使い始める方法もあります。

一つの小物を回し、値を変え、ノードから止められたら、C++とBlueprintの間を一周できています。どちらへ何を置くと作りやすいかは、BlueprintとC++の役割分担で扱います。

まとめ

  • 最初のC++クラスは、.h で宣言し .cpp で中身を書く
  • UCLASS UPROPERTY UFUNCTION の3つが、UEから見えるようにする印
  • EditAnywhere を付けた値は、子Blueprintの詳細パネルから変えられる
  • BlueprintCallable を付けた関数は、ノードとして呼べる

書く前の問いかけは、「この値や処理を、Blueprint側から触りたいか」 です。触りたいならマクロで印を付けます。

役割の分け方を詰めるなら BlueprintとC++の使い分け、C++で機能を分割する入口は Subsystem にあります。

参考:C++ Class WizardUPropertiesUFunctionsビルドLive Coding

Unreal Engine このセクションのノート98