C++
ゲーム制作
UE4
UnrealEngine
UnrealC++
C++Day 18

脱BP!Unreal C++初心者の最初の一歩、カスタムクラスのコードを読んでみよう

最初に

本記事におけるUE4のバージョンは4.16となります。
IDEとしては、Visual Studio 2017を使用しております。

また、本記事は読者が基礎的なプログラムの知識とBPの知識があることを前提として執筆しています。
予めご了承ください。

この記事はC++ Advent Calendar 2017の参加記事となります。

Unreal C++ 公式リファレンスについて

Unreal C++に関して、Epicさんから以下のマニュアルが提示されています。

ですが、これらを読んでいくのは中々、なんというか、骨が折れると言いますか…。

なので、今回は「ブループリントある程度触った!でも、いざブループリントをnative化するとなると、腰が重い…。読み方がそもそもわからない…。」という方向けに基礎の部分を紹介していこうと思います。まぁ自分のことなんですけどね。

本記事のお品書き

  • エンジン側で用意されている親クラスの種類
  • フォルダ構造の確認
  • 基本のコード確認
    • インクルードしているもの
    • マクロ装飾の見方
    • エンジン側のメソッドをオーバーライド
  • 最後に
  • 参考資料

エンジン側で用意されている親クラスの種類

C++クラスはUE4のエディタ上にある「新規追加」>「新規C++クラス」で作ることが可能です。

image.png

たくさんの種類が存在しています。どれをどう使えばいいのか、簡単に紹介していきます。間違ってたらコメント下さい。

Character

Playerや、EnemyやNpcの本体(身体)を作成する際に多く使用します。

歩行や走行、ジャンプ、落下のスピード等を調節できるコンポーネントが付属しています。それらに合わせたアニメーションを実装するためのコンポーネントも含まれています。

Characterクラスはワールドに配置することが可能です。

参考:https://docs.unrealengine.com/latest/JPN/Gameplay/Framework/Pawn/Character/index.html

Pawn

制御可能な全てのアクターの基本クラスです。

先ほど紹介したCharacterもPawnを継承しています。なのでPawnの基本機能+人間のようなキャラクターを作成するのに向いている機能を持ったクラスとなっています。

比べて、Pawn単体は最もシンプルにPlayerやAIが操作して動きを制御できるアクターとなっています。

こちらもワールドに配置することが可能です。

参考:https://docs.unrealengine.com/latest/JPN/Gameplay/Framework/Pawn/index.html

Actor

UE4上に存在するオブジェクトの基本クラスです。

なので、壁や床、置物などなどが、このクラスを継承した上でメッシュやコリジョンを変更してワールドに配置することとなります。

もちろん、ゲーム中で生成したり破棄したりもできます。

参考:https://docs.unrealengine.com/latest/JPN/Programming/UnrealArchitecture/Actors/index.html

Actor Component

アクターに対して特殊機能(例えば武器実装など)を付与したい場合に作成するコンポーネントの基本クラスです。

このコンポーネントは再利用可能であるという前提を持っているので、できるだけ特定のアクターに依存(例えばカスタムクラスへのキャスト処理を入れたり)がないように作成しましょう。

ワールドに配置はできません。

参考:https://docs.unrealengine.com/latest/JPN/Programming/UnrealArchitecture/Actors/Components/index.html

Scene Component

基本的にはアクターコンポーネントと同じで、アクターに対して機能追加したい場合に使用します。

ただし、こちらはトランスフォームに対する操作の部分が拡張されているため、ワールド上での配置情報を使用することができます。描画やコリジョン機能はありません。

参考:https://docs.unrealengine.com/latest/JPN/Programming/UnrealArchitecture/Actors/Components/index.html#scene%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88

Player Camera Manager

Playerの視点の挙動を管理するクラスです。

カメラアニメーションやシェイクなどの動きや、ポストプロセスエフェクトを適用することができます。

参考:
https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Camera/APlayerCameraManager/

プレイヤーコントローラー

Pawnを継承するオブジェクトをPlayerが制御するために使用するクラスです。

ユーザーがパッドやキーボードなどを使用して外部から入力した際の、操作制御を行います。

Player Controllerはゲーム中必ず一つ、ずっと持ち続けることとなります。身体であるポーンを作りなおしたとしても、Player controllerが作り直されることはありません。

参考:https://docs.unrealengine.com/latest/JPN/Gameplay/Framework/Controller/PlayerController/index.html

Game Mode Base

全てのGame Modeの親クラス。Game Modeと比べると機能はシンプルですが、オーバーライド可能な関数が多く含まれています。

このクラスの子として、現在Game Modeが存在しており、そちらはマルチプレイでの対戦ゲーム作成に適した機能が実装されています。

参考:https://docs.unrealengine.com/latest/JPN/Gameplay/Framework/GameMode/index.html

World Settings

WorldSettingsに存在するプロパティにアクセス可能な実装を持たせることができるアクター…だと思います。

参考:https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/GameFramework/AWorldSettings/

HUD

画面上に2DのUI(HPバーなど)を表示するために使用します。

このクラスのインスタンスは、ゲーム内に存在する全てのプレイヤー各々が持つ視界(ビューポート)に描画されます。

参考:https://docs.unrealengine.com/latest/JPN/Gameplay/Framework/UIAndHUD/index.html

Player State

MOのゲームを作成する際に、使用されるクラスです。

サーバーに接続されている全てのプレイヤー用に作成されます。
なのでスコアや名前などの、プレイヤーに関する情報をここに含ませることとなります。

参考:https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/GameFramework/APlayerState/

Game State Base

PlayerStateと同じように、MOのゲーム作成時によく使用されるクラスです。

ただし、Player固有の情報を持つのではなく、全クライアントに知らせる必要がある情報を管理します。
(例えば、制限時間や画面上に表示するプレイヤーのスコアランキングの情報など)

参考:https://docs.unrealengine.com/latest/JPN/Gameplay/Framework/GameMode/index.html#gamestate

Blueprint Function Library

全ブループリントから使用可能な関数を作成し、まとめることができるクラスです。

ただし普通のブループリントと比べて、使用可能な機能が制限されています。

参考:https://docs.unrealengine.com/latest/JPN/Programming/BlueprintFunctionLibraries/index.html

スレートウィジェットとスレートウィジェットスタイル

これらはUE4エディタ自体の拡張を行うのに適したクラスです。

例えばプロジェクトで使用したい便利なカスタム機能などを追加する際に使用するのかなぁと思います。

参考:https://docs.unrealengine.com/latest/JPN/Programming/Slate/Overview/index.html

アンリアルインターフェース

言わずと知れたインターフェースをcpp側で作成できます。

依存性や多態性を意識してクラスやブループリントを構築する際には重要な機能となります。

参考:https://docs.unrealengine.com/latest/JPN/Engine/Blueprints/UserGuide/Types/Interface/index.html

フォルダ構造の確認

エディタ上で作成したcppファイル及びhファイルは、プロジェクトフォルダの下にあるSourceの下に存在しています。フォルダを作成してその下に置くことも可能です。

image.png

基本コード確認

早速エディタ上で適当に作成したクラスを確認してみましょう。

今回はCharacterクラスから継承して、クラス作成を行ってみました。

まずはヘッダーファイルから。

image.png

「何をインクルードしているんだろう?」「UCLASS()ってなんだろう?」「GENERATED_BODY()??」という風になりませんか?私はなりました…。

インクルードしているもの

CoreMinimal.h

Unreal C++を使用していくにあたって必要な機能クラスのヘッダーを集めたファイルです。

例えば、後述する変数の型(Float32、Vector等)が当てはまります。

GameFramework/Character.h

ベースとしているCharacterクラスが存在しているヘッダーファイルです。

CharacterBase.generated.h

ファイル内で検出されたマクロに基づいて、Unrealヘッダーツール(UHT)が自動的に作成する結果を格納しているのが、このファイルです。この.generated.hファイルは全てのアクタークラスでインクルードする必要があります。インクルードするに当たって、必ず…必ず最後にインクルードするように記述してください!

マクロ装飾の見方

さて、次にクラス宣言ですが、C++では見かけない、UCLASS()とかGENERATED_BODY()とかがデフォルトでついていますね。これらはUnreal C++でのマクロの一種となります。これらのマクロには、

Unreal C++で使用する主要のマクロを一つずつ見ていきましょう。

UCLASS()

Unreal C++のマクロの一つです。

このマクロには指定子を設定することができます。例えばBlueprintTypeを設定している場合、このクラスをブループリント上で変数として使用することができます。つまり、普通のUE4クラスのように動作する、カスタムC++クラスとして宣言することができるのです。

例:UCALSS ( Blueprintable )

逆に指定子としてNotBlueprintTypeが指定されている場合は、変数として使わないよう制限をかけることができます。

指定子の一覧は以下のURLから確認することができます。

指定子一覧参考:https://docs.unrealengine.com/latest/JPN/Programming/UnrealArchitecture/Reference/Classes/index.html#%E3%83%A1%E3%82%BF%E3%83%87%E3%83%BC%E3%82%BF%E6%8C%87%E5%AE%9A%E5%AD%90

また、UCLASSとして宣言されたクラスのオブジェクトを、「ConstructObject」という機能を使用して作成することで、オブジェクトの破棄管理などをUE4側で管理してもらえるようになります。

(ただし自身でスマートポインタを使用した、より安全なコードを作成することも可能です)

GENERATED_BODY()

コンパイルの前にUnrealビルドツール(UBT)によって、オブジェクトの本体内にコードが挿入されるようにするマクロです。

UFUNCTION

このマクロは、どんな関数にも付与することができるマクロです。

付与することによって、C++コード側とBP側の両方から呼び出すことが可能となります。UFUNCTION()は実際はC++関数ではありますが、UCLASSと同様に指定子を追加することができます。

(例えばブループリントで使用可能とするかどうかなど)

指定子一覧参考:https://docs.unrealengine.com/latest/JPN/Programming/UnrealArchitecture/Reference/Functions/index.html#%E9%96%A2%E6%95%B0%E6%8C%87%E5%AE%9A%E5%AD%90

UPROPERTY

UCLASSで宣言したクラス内では、UPROPERTYというマクロを持つことができるフィールドをいくつも持つことができます。

このマクロもまた、指定子を設定することができ、ブループリントからアクセスを可能にするかどうか設定することができます。

intやfloatなどのお馴染みな型もUE4用に用意されたものがあり、以下のURLでも表となって紹介されているので、一度確認して頂くと良いかもしれません。

指定子一覧参考:https://docs.unrealengine.com/latest/JPN/Programming/UnrealArchitecture/Reference/Properties/index.html

エンジン側のメソッドをオーバーライド

最後にcppファイルを開いてみましょう。これまでに、ブループリントで使っていたBeginPlay()やTick()も既に定義の記述が行われています。

コンストラクタに見知らぬ「PrimaryActorTick.bCanEverTick」という変数が勝手にtrueとして設定されていませんか?

これは、毎フレームTickイベントを呼び出すか否かを設定するフラグです。

ゲーム自体のパフォーマンスを気にする場合には、できるだけ切っておいた方がいいでしょう。

また、知らないメソッド「SetupPlayerInputComponent」がありますね。

これは、PlayerControllerがこのPawnを所有するときに呼び出されます。

参考:https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/GameFramework/ADefaultPawn/SetupPlayerInputComponent/

最後に

とりあえず、基礎知識の紹介としては以上となります。

明日、ブループリントを用いたUE4でのNpc作成手法に関する記事を公開する予定です。そちらの記事の内容をC++で実装してみた、なんていうこともそのうちやってみたいなぁ、と思いつつ、とりあえずUnreal C++を入門するところから始めてみました。

この記事が誰かの助けになれば幸いです。

以上です。

参考資料

  • Unreal Engine 4 Scripting with C++ Cookbook
  • Unreal Engine 4.X By Example
  • Unreal Engine リファレンス群