ゲーム開発
Unity
UnrealEngine
C++
ゲーム数学
ゲームAI
サウンド
アニメーション
GBDK
制作日記
3DCG
Houdini
Blender
USD
グラフィックス
テクノロジ
ツール開発
フロントエンド関連
サーバサイド関連
ソフトウェア設計
ハードウェア関連
おすすめ技術書
音楽
DTM
楽器・機材
ピアノ
その他
都会のエレキベア
ラーメン日記
四コマ漫画
おすすめアイテム
おもしろコラム
  • ゲーム開発
    • Unity
    • UnrealEngine
    • C++
    • ゲーム数学
    • ゲームAI
    • サウンド
    • アニメーション
    • GBDK
    • 制作日記
  • 3DCG
    • Houdini
    • Blender
    • USD
    • グラフィックス
  • テクノロジ
    • ツール開発
    • フロントエンド関連
    • サーバサイド関連
    • ソフトウェア設計
    • ハードウェア関連
    • おすすめ技術書
  • 音楽
    • DTM
    • 楽器・機材
    • ピアノ
  • その他
    • 都会のエレキベア
    • ラーメン日記
    • 四コマ漫画
    • おすすめアイテム
    • おもしろコラム
  1. ホーム
  2. 20240519_01_ue5_cpp_basic

【UE5】第一回 ミニゲーム制作で学ぶUnrealC++ 〜UnrealC++の概要 編〜

UnrealEngineC++制作日記ミニゲームUE5
2024-05-18

マイケル
マイケル
みなさんこんにちは! マイケルです!
エレキベア
エレキベア
こんにちクマ〜〜〜
マイケル
マイケル
これまでUnity記事をメインに執筆してきましたが、 ついに仕事の関係上UnrealEngineの学習を行っておりました...。
エレキベア
エレキベア
まあどこかで触るだろうとは思っていたクマが・・・
マイケル
マイケル
というわけで、今回から学習も兼ねてUnrealEngine5でのミニゲーム制作について紹介していきます! ブループリントでなくC++メインで開発したゲームとなっていて、「ミニゲームの制作過程を通してUnrealC++で開発する際の方法をざっくり知ろう」という趣旨になっております。
エレキベア
エレキベア
UEはブループリントの情報ばかりで、C++で開発した適度なサンプルが無いのが悩みどころクマね・・・
マイケル
マイケル
今回の記事とサンプルが、これからUnrealEngineのC++開発を学習する方の役に立ってくれれば幸いです・・・。 実際に作ったゲームは猫のエンドレスランゲームで、プレイ動画は下記になります!
エレキベア
エレキベア
おお〜〜ちゃんとゲームになってるクマ
マイケル
マイケル
画面遷移やUI・スコア表示など、ゲームでよく使う機能をなるべく入れたサンプルとなっています。 作成したプロジェクトは下記のGitHubリポジトリにあげているので、こちらも合わせてご参照ください!

▼GitHubリポジトリ
GitHub - plasmo310 / ue5-cat-runner

▼UnrealEngineバージョン
5.3.2

エレキベア
エレキベア
これくらいの量なら把握もしやすいクマね
マイケル
マイケル
今回は第一回ということで作ったゲームの中身には触れずに、UnrealEngineでのC++開発を行う上での基礎知識について紹介していきます!
エレキベア
エレキベア
楽しみクマ〜〜〜

参考書籍

マイケル
マイケル
今回実装・情報整理するにあたり、下記書籍を参考にさせていただきました!

C++でつくるUnreal Engineアプリ開発 for Windows & ...

Unreal Engine 5で極めるゲーム開発:サンプルデータと動画で学ぶゲー...

マイケル
マイケル
C++でつくるUnreal Engineアプリ開発は、UE4の情報にはなりますが数少ないC++について触れられた書籍です。 Unreal Engine 5で極めるゲーム開発は通称極め本と呼ばれていて、業界内では定番書籍として扱われています。 量はありますが、一度見ておいて損はないと思います!
エレキベア
エレキベア
極め本はUE4版もあったクマが、UE5になってまたボリュームが大きくなったクマね

アクタを作ってみる

マイケル
マイケル
UnrealC++の細かい話に入っていく前に、 まずはとりあえず簡単なコードを書いてみます!
エレキベア
エレキベア
雰囲気をつかむクマね

ThirdPersonテンプレートで作成

マイケル
マイケル
UnrealEngineのテンプレートは複数ありますが、ここではThirdPersonテンプレートを使用してプロジェクトを作成します。
20240519_01_ue5_cpp_basic_02
▲ThirdPersonテンプレートからC++プロジェクトを作成

マイケル
マイケル
こちらのテンプレートは基本的な移動処理やカメラなども設定されており、3Dゲームの開発が始めやすいものになっています。
20240519_01_ue5_cpp_basic_03
▲作成直後でキャラクターを動かせる

20240519_01_ue5_cpp_basic_04
▲移動処理やカメラも設定されている

エレキベア
エレキベア
定番のテンプレートクマね

CubeアクタのBPを作成

マイケル
マイケル
そして「BP_Cube」という名称でActorを親としたブループリントを作成し、 こちらに対してCubeオブジェクトを追加しておきます。
20240519_01_ue5_cpp_basic_06
▲ActorのBlueprintを作成

20240519_01_ue5_cpp_basic_07
▲Cubeを追加

エレキベア
エレキベア
Unityでいうプレハブ的な感じクマね
マイケル
マイケル
今回はこちらのCubeが自動で前進するよう、C++のコードを書いてみます。

Actorクラスを作成

マイケル
マイケル
「CubeActor」という名称でAActorクラスを親としたクラスを作成します。 Public/Privateという指定もありますが、こちらは他モジュールへの公開設定になっています。 独自のモジュールを作成するなどしていない限りは、基本的にPrivateを選択して問題ないです。
20240519_01_ue5_cpp_basic_05
▲「CubeActor」という名称でプライベートクラスを作成

マイケル
マイケル
初期生成されたコードは下記のようになっています。 BeginPlay、Tick関数がそれぞれ開始/更新でゲームループ処理となっています。
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

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

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

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

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

};

▲初期生成コード(ヘッダ)
// Fill out your copyright notice in the Description page of Project Settings.


#include "CubeActor.h"

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

}

// Called when the game starts or when spawned
void ACubeActor::BeginPlay()
{
	Super::BeginPlay();
	
}

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

}

▲初期生成コード(実装)
エレキベア
エレキベア
AActorはUnityでいうMonoBehaviour的なクラスになっているクマね
マイケル
マイケル
こちらのクラスに対して、「MoveSpeed」という名称で移動スピードの変数を追加し、Tick関数内に移動処理を実装してみます。
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

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

UCLASS()
class ACubeActor : public AActor
{
	GENERATED_BODY()
	
public:	
	ACubeActor();
	virtual void Tick(float DeltaTime) override;

private:
	/** move forward speed */
	UPROPERTY(EditAnywhere)
	float MoveSpeed = 5.0f;

};

▲移動スピードのプロパティを追加
// Fill out your copyright notice in the Description page of Project Settings.


#include "CubeActor.h"

ACubeActor::ACubeActor()
{
	PrimaryActorTick.bCanEverTick = true;
}

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

	// move forward.
	FVector CurrentLocation = GetActorLocation();
	CurrentLocation += MoveSpeed * GetActorForwardVector();
	SetActorLocation(CurrentLocation);
}

▲Tick関数内で前進させる
エレキベア
エレキベア
UPROPERTYがUnityでいうSerializedFieldみたいな感じクマか

BPの親クラスに設定

マイケル
マイケル
あとはCubeのブループリント画面 > クラス設定から親クラスを作成したクラスに変更します。 変更後にコンパイルすると、コードに追加したMoveSpeed変数がプロパティとして表示されると思います。
20240519_01_ue5_cpp_basic_08
▲クラス設定から親クラスを変更

20240519_01_ue5_cpp_basic_09
▲追加したプロパティも表示されるようになっている

エレキベア
エレキベア
ブループリントとの紐付けはクラス設定から行うのクマね

レベルに配置して確認

マイケル
マイケル
最後に、Cubeのブループリントをレベル上に配置します。 ゲームを開始すると前進するのが確認できるかと思います!
20240519_01_ue5_cpp_basic_10
▲BPをレベル上に配置

20240519_01_ue5_cpp_basic_11
▲ゲームを開始すると前進することが確認できる

エレキベア
エレキベア
やったクマ〜〜〜 なんというかUnityと似たような感じで実装できるのクマね

UnrealC++の概要

マイケル
マイケル
UnrealEngineでのC++開発のイメージが分かったところで、少し踏み込んで概要をまとめてみます。

UnrealEngineオブジェクトの構成

マイケル
マイケル
まずUnrealEngineでの世界の構成についてですが、下記のように ワールド - レベル - アクタ - コンポーネント の含合関係になっています。
20240519_01_ue5_cpp_basic_01
▲UnrealEngineオブジェクトの構成

参考:
UObjectの原理 - RootSetから全て繋がっている
UnrealEngineドキュメント - UWorld

  • UWorld
    • トップレベルのオブジェクト
    • スタンドアロンゲームでは通常1つのワールドが存在する
  • ULevel
    • 複数のアクタを持つ、Unityでいうシーン的存在
    • レベルの中でもパーシスタントレベルとその中に含むサブレベルがある
エレキベア
エレキベア
なるほどクマ・・・ レベルがUnityでいうSceneにあたるのクマね
20240519_01_ue5_cpp_basic_12
▲レベルの中にアクタを含む形式となる

アクタとオブジェクト

マイケル
マイケル
そしてアクタ(AActor)の他によく使用するクラスとしてUObjectがあります。 アクタ自身もUObjectを継承していて、UEでの全てのオブジェクトの基本クラスとなっています。
  • AActor
    • ワールドに配置可能な全てのゲームプレイオブジェクト
    • ゲームループによる処理が可能(BeginPlay、Tick)
  • UObject
    • アクタを含め、UnrealEngine全てのオブジェクトの基本クラス

参考:
UnrealEngineドキュメント - UnrealArchitecture

エレキベア
エレキベア
ワールドに配置できるのがアクタ全ての基本クラスがUObjectクマね
マイケル
マイケル
その他、よく使用するクラスとしては下記のようなものがあります。 クラス名の頭には接頭辞を付与するルールになっていて、「A」「U」といった文字でどのクラスを継承しているかが判断できるようになっています。
その他主要クラス
クラス
概要
APawn
入力を受け取ることができるアクタ(プレイヤー)
ACharacter
人間の形をしたPawnで、CapsuleComponent、CharacterMovementComponentがデフォルトで付いている
APlayerCharacter
Pawnを操作するためのインタフェース
AGameMode
ゲームルールや勝敗条件などを含めたゲームの定義
ALevelScriptActor
レベルを管理するためのクラス
UUserWidget
UMG(UIシステム)にてWidgetの親となるクラス
マイケル
マイケル
このようなアクタやUObjectを生成したり、取得する処理は下記のようになります。 それぞれ用意された関数経由で処理を行うことで、後述するガベージコレクションの仕組みに乗せることができます。
// Componentの追加(コンストラクタ内にて)
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
 
// UObjectの生成
HitDetectManager = NewObject<UHitDetectManager>();
 
// アクタのSpawn
StageFloor = World->SpawnActor<AStageFloor>(StageFloorActor, SpawnLocation, SpawnRotator, SpawnParams);
 
// プレイヤー取得
APawn* PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
const auto PlayerCharacter = Cast<ACatCharacter>(PlayerPawn);
if (PlayerCharacter != nullptr)
{
...
}
 
// 特定のアクタ取得
const auto LevelScriptActor = UGameplayStatics::GetActorOfClass(Player->GetWorld(), ARunGameLevelScript::StaticClass());
const auto RunGameLevelScript = Cast<ARunGameLevelScript>(LevelScriptActor);
if (RunGameLevelScript != nullptr)
{
...
}
▲よく使うオブジェクト操作処理
エレキベア
エレキベア
プレイヤーなんかは専用の取得処理が付いているのクマね

コンポーネント

マイケル
マイケル
アクタが保有するコンポーネントにも大きく2つの種類があり、トランスフォームを含むSceneコンポーネントと含まないActorコンポーネントがあります。
  • Actorコンポーネント
    • トランスフォームを含まないコンポーネント
  • Sceneコンポーネント
    • トランスフォームを含むコンポーネント

参考:
UnrealEngineドキュメント - Component

20240519_01_ue5_cpp_basic_13
▲アクタはコンポーネントを保有できる

エレキベア
エレキベア
コンポーネントもこれらのクラスを継承して作成するクマね

UPROPERTYとガベージコレクション

マイケル
マイケル
次によく使用するのは「UPROPERTY」の指定です。 これにはガベージコレクションの仕組みも関係するため、まずはそこから触れていきます。
UEのガベージコレクション
マイケル
マイケル
UnrealEngineのガベージコレクションは、先ほど紹介したオブジェクト構成をたどりながら不要になったUObjectを破棄する仕組みになっています。 そのため、標準C++で記載したクラスを作成しない限りは基本的にメモリ管理は任せることができます。

UEのガベージコレクションの仕組み

  • ルートセットから辿って不要になった(参照が無くなった)UObjectを破棄する
  • アクタはDestroy関数を呼び出すことで明示的にマーク付けできる
  • ガベージコレクションの頻度等もプロジェクト設定から変更することができる
エレキベア
エレキベア
不要になったかどうかは参照されているかどうかで判断するクマね
UPROPERTY
マイケル
マイケル
そしてUPROPERTYについてですが、基本的には下記のようにエディタやブループリントに公開したい変数に対して付与する指定になっています。
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
	TObjectPtr<UCameraComponent> FollowCamera;
▲UPROPERTYの指定
マイケル
マイケル
UnityのSerializedFieldに近いものになっていますが、注意点として参照カウンタ的な役割も担っていることがあります。 UObjectに対してUPROPERTYを付与していないと、意図しないタイミングで破棄されたりなどガベージコレクション関連の不具合に繋がる可能性があるためご注意ください。
  • 基本はレベルエディタやBlueprintに公開するための指定
  • Unityでいう単なるSerializedFieldではなく、参照カウンタとしての役割も担っている
    • キーワードを指定せずに UPROPERTY() を付与することにも意味がある
    • UEオブジェクトの変数には付与しておかないと、GCされない・もしくは勝手に破棄されるといった不具合に繋がるため注意

参考:
UnrealEngineドキュメント - Optimizations
UObjectの原理 - docswell

	UPROPERTY()
	TObjectPtr<UAudioService> AudioService;
▲引数無しのUPROPERTYにも意味がある
エレキベア
エレキベア
エディタ等に公開しない場合にも付けないといけないのクマね
マイケル
マイケル
UPROPERTYに指定するキーワードとして、よく使用するレベルエディタ/ブループリントへの公開設定は下記があります。 その他にも指定できるものが多々あるので、この辺りは公式ドキュメントをご参照ください!
よく使うキーワード
キーワード
概要
VisibleAnywhere
レベルエディタやBlueprint上で閲覧できる
EditAnywhere
レベルエディタから閲覧・編集できる
BlueprintReadWrite
Blueprintから閲覧・編集できる
BlueprintReadOnly
Blueprintから閲覧できる

UnrealEngineドキュメント - Optimizations

エレキベア
エレキベア
UPROPERTYが段々分かってきたクマ〜〜〜

デリゲート

マイケル
マイケル
デリゲートには シングルキャスト or マルチキャストで選べる他、動的 or 静的からも選択できます。 動的デリゲートはシリアライズ可能で、Blueprintから参照することができるその分動作は遅くなるため、C++のみで使用する場合には静的デリゲートの選択を検討しましょう。

参考:
UnrealEngineドキュメント - デリゲート

DECLARE_MULTICAST_DELEGATE...
DECLARE_DYNAMIC_DELEGATE...
DECLARE_DYNAMIC_MULTICAST_DELEGATE...
DECLARE_DYNAMIC_DELEGATE...
DECLARE_DYNAMIC_MULTICAST_DELEGATE...
▲決められたマクロを変数に付与することで使用できる
	/** アクタ衝突時のイベント */
	DECLARE_DELEGATE_TwoParams(FHitActorDelegate, ACatCharacter*, AActor*);
	FHitActorDelegate OnHitActorDelegate;
▲静的シングルデリゲートの例(引数2つ)
void ACatCharacter::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
	UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	// イベント発行
	if (OnHitActorDelegate.IsBound())
	{
		OnHitActorDelegate.Execute(this, OtherActor);
	}
}
▲静的シングルデリゲートの例(引数2つ)
エレキベア
エレキベア
デリゲートは依存関係を制御するのにも便利クマね

Unreal特有のライブラリ

マイケル
マイケル
最後に、コンテナ、スマートポインタに限らず、C++標準のstdライブラリはほぼ独自でラップされています。 UnrealEngineに特化した処理内容になっていると思われますので、基本的にはUnrealのライブラリを使用するようにしましょう。
主要のUnrealライブラリ
 
Unrealライブラリ
類似のstdライブラリ
コンテナ
TArray
std::vector
TMap
std::map
スマートポインタ
TSharedPtr
std::shared_ptr
TWeakPtr
std::weak_ptr
TUniquePtr
std::unique_ptr
関数オブジェクト
TFunction
std::function

参考:
UnrealEngineドキュメント - スマートポインタ
UnrealEngineドキュメント - コンテナ(TArray)

エレキベア
エレキベア
スマートポインタ周りも一通り用意されているクマね

UnrealC++のコーディング規約

マイケル
マイケル
最後におまけにはなりますが、UnrealEngineには独自のコーディング規約が存在しています。 下記のような内容になっていて、いろいろ思うところもあると思いますが、エンジンのコードやコミュニティはこの形式が多いと思うのでなるべく合わせるようにしましょう!

UnrealEngineドキュメント - コーディング規約

  • 変数名の頭は全て大文字にする
  • クラス名の頭には所定の接頭辞を付ける
  • ブール変数の頭にはbを付ける
  • constを正しく設定する
  • アクセス修飾子はpublic->privateの順で記述する
  • autoは基本的に使用しない
  • インクルードより前方宣言を優先する
エレキベア
エレキベア
変数名大文字は特になんとも言えないクマね・・・

おわりに

マイケル
マイケル
というわけで、今回はUnrealC++の概要についてでした! どうだったかな??
エレキベア
エレキベア
大体イメージは分かった気がするクマ〜〜〜 でもやっぱり実際に書いてみないとパッとしないクマね
マイケル
マイケル
次回からは実際に制作したゲームでの実装内容を見ていきます! Unity等で開発経験があれば大体のイメージは掴めると思いますので、お楽しみに!
エレキベア
エレキベア
早くC++を書きたいクマ〜〜〜
マイケル
マイケル
それでは今回はこの辺で! アデューー!!
エレキベア
エレキベア
クマ〜〜〜〜

【UE5】第一回 ミニゲーム制作で学ぶUnrealC++ 〜UnrealC++の概要 編〜 〜完〜

【UE5】第一回 ミニゲーム制作で学ぶUnrealC++ 〜UnrealC++の概要 編〜
2024-05-18
【UE5】第二回 ミニゲーム制作で学ぶUnrealC++ 〜キャラクター・ゲーム実装 編〜
2024-05-18
【UE5】第三回 ミニゲーム制作で学ぶUnrealC++ 〜UI・仕上げ実装 編〜
2024-05-18

UnrealEngineC++制作日記ミニゲームUE5
2024-05-18
記事をSNSで共有する
X
Facebook
LINE
はてなブックマーク
Pocket
LinkedIn
Reddit

著者の各種アカウント
フォローいただけると大変励みになります!
X
GitHub

関連記事
【UE5.5】Nanite、Lumen、VSMの概要についてまとめる
2025-05-12
【UE5】Niagara SimulationStageによるシミュレーション環境構築
2024-05-30
【UE5】第三回 ミニゲーム制作で学ぶUnrealC++ 〜UI・仕上げ実装 編〜
2024-05-18
【UE5】第二回 ミニゲーム制作で学ぶUnrealC++ 〜キャラクター・ゲーム実装 編〜
2024-05-18
【JUCE】DTMプラグインを作ってみる 〜ディストーション編〜【VST/AU】
2024-03-22
【Unity】「怪盗チョコレート」をリリース!工夫点や反省点をざっと振り返る【バレンタイン】
2023-02-12
【DirextX12】第四回 DirextX12を使ったゲーム開発 〜FBX SDKを使用した3Dモデル描画〜
2022-12-07
【DirextX12】第三回 DirextX12を使ったゲーム開発 〜座標変換と3Dオブジェクト表示〜
2022-11-27