UE4のC++プログラミング入門1(パラメータの説明)


はじめに

  • Unreal Engine4のC++を勉強していると,UE C++という表現を目にする.これは的を得ており,普通のC++とは全然違い,熟練のC++プログラマーでも戸惑うと思う.
  • そのUE C++での独特な特徴を簡単に紹介し,自分にとっての備忘録を残したいと思う.
  • これはUE4でBlueprintを触り,プログラマがC++でゲームを作りたいと思った人向けである.UE4にまったく触っていない人を対象として書いていないので注意してほしい.
  • 間違っているところがあれば教えてくれると,うれしい.
  • C++プログラミングを行う前にVisual Stdioの設定をしなければならない.あまり難しくはないため説明は公式に丸投げする.

目次

  • プロジェクトの作成とC++コードの作成,ビルド
  • UCLASS()とGENERATED_BODY()
  • UPROPERTY()とUFUNCTION(),及び関数の呼び出し
  • まとめと実行環境

プロジェクトの作成とC++コードの作成,ビルド

まずプロジェクトを作成する.テンプレートは何でもよいが今回はBlankを選択した.
プロジェクト設定にてC++を選択する.プロジェクト名は何でもよい.今回はC_Testにした.

その後,新規追加にて新規C++クラスを選択する.そして全てのクラスを表示して一番上のObjectを選択する.

次へ進み,名前を付ける.名前は何でもよいが今回はSampleとした.
またパブリックとプライベートではパブリックを選択する.

このパブリック,プライベートはプラグインに関係しているらしい.画像ではパブリックだが,本来はプライベートのほうがよいと思う.これからはプライベートにする.
クラスを作成すると自動でVisual Stdioが開いたと思う.
また一度,プロジェクト設定をブループリントにしたからといって,C++でプログラミングできないわけではない.新規C++クラスを作り,その後UE4を再起動したらよい.
最後にビルド方法を説明する.ビルドのやり方は簡単で2つがある.
エディタからコンパイルというボタンを押す方法.

VSからプロジェクト名を右クリックを押して,一番上のビルド選択する方法.

次からプログラムの中身に入りたいと思う.

UCLASS()とGENERATED_BODY()

Sample.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "Sample.generated.h"/*ここはファイル名.generated.hとなっている*/

UCLASS()
class C_TEST_API/*プロジェクト名*/ USample : public UObject
{
    GENERATED_BODY()
};

さて自動生成されたプログラムは上記にようになっていると思う.UObjectはUE4の一番上にいる親クラスである.UE4の全てのオブジェクトがこれを継承している.

UCLASS()GENERATED_BODY()とは?

C++の経験者であればまずこのコードに戸惑う.
UCLASS()GENERATED_BODY()これなに?ってなる.なんでこんなところにいるの?コンパイルエラーになるんじゃないの?と思う.
UCLASS()は簡単に言うとUE4でclassを作成する際に必要なコードである.
GENERATED_BODY()もUE4が勝手に管理してくれるために必要なコードである.ガーベージコレクション(後述予定)などのために必要だ.
要するにUCLASS()やGENERATED_BODY()は「考えるな感じろ」ということだ.何も考えずに必要なものとして,おまじないだと思おう.
またUCLASS()のほかにUSTRUCT()やUENUM()などある.

UCLASS()の()の中身について

ここからが大事である.()の中にクラス指定子を書きます.これを書くことによりエディタやBlueprintからアクセスすることができます.
クラス指定子はたくさんあります.全部紹介するのは無理だし,必要ない.詳しくは公式を見た方がよい.
よく使うのはBlueprintTypeやBlueprintableなどだ.それぞれ説明していく.

BlueprintType

ここから実際に書いてみてほしい.まず一か所だけ変える.

Sample.h
/*includeを省略*/

UCLASS(BlueprintType)
class C_TEST_API USample : public UObject
{
    GENERATED_BODY()
};

上記のように変えた後にビルドを行う.ビルド方法は既に書いてある.参考にしてほしい.
BlueprintTypeにするとUE4から変数の型を宣言したクラス名にすることができる.よってここでは変数の型が"Sample"となっている.ソースファイルではクラス名が"USample"となっているが"U"はとれ,Sampleとなる.

Blueprintable

Sample.h
/*includeを省略*/

UCLASS(Blueprintable)
class C_TEST_API USample : public UObject
{
    GENERATED_BODY()
};

上記のようにBlueprintableにして,ビルドを行う.これをつけるとBlueprintを作成するときそのクラスを継承することができます.
その後,エディタで新規のブループリントクラスを作成しようとしてみる,そして下記のようにSampleがあることを確認する.これを選択するとSampleクラスが継承される.

BlueprintableとBlueprintTypeなどはUCLASS()以外にもUSTRUCT()やUENUM()にも使用できる.この2つは後述する予定である.

UPROPERTY()とUFUNCTION(),及び関数の呼び出し

Sample.h
/*inculdeを省略*/
UCLASS()
class C_TEST_API USample : public UObject
{
    GENERATED_BODY()
public:
    UPROPERTY()
        int32 Integer;
    UFUNCTION()
        static FString Hello();
};

さてクラスを作るということはもちろんメソッドやメンバ変数を定義する.メソッドを定義するときはUFUNCTION()をつけ,メンバ変数にはUPROPERTY()をつける.これらをつけるとエディタから操作できたり,Blueprintからアクセスすることができる.
またUPRORERTY()をつけるとガーベージコレクションの対象となる.
間違っていた、UPROPERTY()をつけるとガーベージコレクションの対象外となる。ご指摘ありがとうございます

UPROPERTY()の()の中身について

こちらも詳しくは公式を確認する.
よく使う,プロパティ指定子を紹介する.また先ほどのクラス指定子では省略したメタデータ指定子についても説明する.
プロパティ指定子はBlueprintReadWriteとCategoryを説明する.
メタデータ指定子はDisplayNameについて説明する.

Sample.h
/*inculdeを省略*/
UCLASS(BlueprintType)
class C_TEST_API USample : public UObject
{
    GENERATED_BODY()
public:
    UPROPERTY(BlueprintReadWrite, Category = "UE C++ Test", 
        Meta = (DisplayName = "int"))
        int32 Integer;
    UFUNCTION()
        static FString Hello();
};

上記のようにしてビルドを行う.その後,エディタに戻りレベルブループリントを開く.
その後,変数を作成して型をSampleにする.その変数をイベントグラフにドラッグ&ドロップを行う.
そこからワイヤーを出して,UE C++ Testと入力する.

上記のように出てくる.BlueprintReadWriteにすると,値をgetとsetのどちらも行うことができる.またCategoryを設定してやると検索するときに便利である.
DisplayNameを設定するとそう表示されるようになる.変数名で検索しても出てこない.DisplayNameを設定しないと変数名がそのまま表示されます.

BlueprintReadWriteをBlueprintReadOnlyにするとgetsetがなくなる.そのままの意味である.
訂正しました。ご指摘ありがとうございました。

UFUNCTION()の()の中身について

さて初めは恒例の公式の紹介である.ここに関数指定子が詳しく書いてある.
ここではBlueprintCallableとBlueprintPureを説明する.
メタデータ指定子はここでは説明しない.Actorを実装する際に詳しく紹介する.

Sample.h
/*inculdeを省略*/
UCLASS()
class C_TEST_API USample : public UObject
{
    GENERATED_BODY()
public:
    UPROPERTY()
        int32 Integer;
    UFUNCTION(BlueprintCallable, BlueprintPure, Category = "UE C++ Function")
        static FString Hello();
};

上記のようにしてビルドを行う.
その後,レベルブループリントを開き,イベントグラフで右クリックを押す.その後,検索でUE C++ Functionと入力する.Helloと出るはずだ,それをクリックしてだしてみる.

BlueprintCallableのCallbleは呼び出し可能という意味だ.よってBlueprintCallbleがないとブループリントから呼び出すことができない.
BuleprintPureだとワイヤー接続ができないノードが出るはずだ.BuleprintPureのpureは純粋という意味だ.
BlueprintPureがないと下記のようなノードになる.

Hello関数の実装

C++クラスを作った時点でSample.cppは存在していると思う.しかしinculdeしが書かれていない.ここに関数の実装を記述する.書き方はC++と同じだ.

Sample.cpp
#include "Sample.h"

FString USample::Hello()
{
    return FString("Hello");
}

上記のようにしてビルドする.これは戻り値としてFString型でHelloを返す.
先ほどからFStringと書いてあるがこれはいわゆるString型である.StringをUE C++として定義されているのが,FStringである.FStringはUE4のために最適化されている.
通常のString型を使うことは不可能ではないがメリットが少ないと思う.
FString以外にもFVectorなどがある.これらはUnrealString.h,Vector.hで定義されている.この2つのヘッダーファイルはCoreMinimal.hでincludeされている.

さて,この関数を呼び出してみよう.レベルブループリントを開いて,イベント BeginPlayからHelloノードをつなげる.その後,Print Stringノードにつなぐ.

こうなっているはずだ.ではレベルブループリントをコンパイルしてプレイを押してみよう.
下記のようになるはずだ.

まとめと実行環境

今回はここまでとする.ここでは初めに戸惑う,UCLASS()やUFUNCTION()などの説明を中心に紹介した.これだけでも,複雑なプログラムをC++で記述し,ブループリントで呼び出すことができる.
次回はActorを作ってみる.

実行環境

Visual Stdio 2017
Unreal Engine 4.24.3