アルゴンUE4/UE5&アプリ開発日記

UE4/UE5の機能やプラグインを紹介します。初心者や中級者向けになってます!!

【UE4/UE5】C++初心者向け学習メモ

C++で作ってみましょう(*'ω'*)

今回はついにC++の説明をしていこうと思います。

一部UE関係ないC++特融のことなども少し紹介します。

今回は作る上で必ず使うであろう関数などを重点的に説明します。

C++のすごく細かい知識などは少し省くかもしれません。

※GASなどの難しいお話は説明しません!

C++とはそもそも何?

C++とはC言語オブジェクト指向を加えて、

より効率よく行えるプログラミング言語になります。

ヘッダーファイルとCPPファイルに分かれており、

ヘッダーファイルにはクラス定義や関数や定数などを宣言しておき、

CPPファイルの方に各種関数の処理を記載する形になります。

それからUE用処理のクラスや関数などが用意されているので、

それをBPと同様に呼び出して処理が作成できます。

公式ドキュメントにより細かい説明があるのでこちらもどうぞ。

UE4 の C++ プログラミング入門 | Unreal Engine ドキュメント

※補助されているとはいえ少しは知識が無いと厳しいので、

 C++以外のプログラミング言語に触れておくのも効果的です。

・目次に戻る

回転する床のActorを作ってみよう

まず作らないと話が始まらないので作っていきましょう!

とその前に環境構築からの説明になりますが、

私は今回VisualStudioCodeを使用しています。

VScodeの環境構築はこちらをご参照ください。

【UE5】VSCodeでプロジェクトのビルドを行う。 - アルゴンUE4/UE5&アプリ開発日記

VisualStudioを使用する場合は少し古いですが記載しています。

【UE4】VisualStudio2017でUE4を動かす(Windows) - アルゴンUE4/UE5&アプリ開発日記

実際にプロジェクトを作成していきます。

今回はC++プロジェクトを作成していきます。

サードパーソンテンプレートをC++プロジェクトで作成します。

C++のプロジェクトの作成

プロジェクトを追加したらメニューのToolsから、

「NewC++Class…」を選択してC++用の処理ファイルを作成します。

C++クラス作成のあれ

選択したらアクターとファイルを選択できるダイアログが出ます。

元となるクラスが今回はActorになってほしいのでActorを選択して作成します。

元となるクラスの指定

ファイルの場所を指定

作成するとTestActorのヘッダーファイルとCPPファイルが作成されます。

ヘッダーファイルとCPPファイルの生成

余談ですがVSCodeの場合は「Commands_Default.json」に、

追加したC++関連のファイルを追加します。

VSCodeのファイルの連携

それでは実際に.h(ヘッダーファイル)の説明をしていきます。

まずは#pragma onceから説明します。

こちらは呼び出しているヘッダーファイルを、

何度も呼ばれないようにするための宣言になります。

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

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "GameFramework/RotatingMovementComponent.h"
#include "TestActor.generated.h"

その下は「#include "ヘッダーファイル名"」を記述しています。

今回はCoreMinimal.hGameFramework/Actor.hや、

GameFramework/RotatingMovementComponent.hなどになります。

各種ヘッダーについての説明は下記になります。

・CoreMinimal.h

→  Vector2DやColorなどの値関連の変数を使用するための宣言

・GameFramework/Actor.h

→ Actor用の関数や変数を使用するための宣言

・GameFrameWork/RotatingMovementComponent.h

→ 各種回転動作を制御するコンポーネントを使用するための宣言

・TestActor.generated.h

→ UPROPERTYなどを生成する際に使用する宣言

※これ以降にヘッダーファイルを宣言するとエラーになるので注意!

続いて実際の処理について説明していきます。

    GENERATED_BODY()
    public:
        // Sets default values for this actor's properties
        ATestActor();
    protected:
        // Called when the game starts or when spawned
        virtual void BeginPlay() override;
    public:
        // Called every frame
        virtual void Tick(float DeltaTime) override;
        // スタティックメッシュ用の変数
        UPROPERTY(EditAnywhere,Category="Mesh",BlueprintReadWrite)
        UStaticMeshComponent* Mesh;
        // RotatingMovementComponent用の変数
        UPROPERTY(EditAnywhere,Category="RotationMovement",BlueprintReadWrite)
        URotatingMovementComponent* Rotating;
        // 回転する角度量の変数
        UPROPERTY(EditAnyWhere,Category="RotationValue",BlueprintReadWrite)
        FRotator MeshRotationValue;

まず一番上のGENERATED_BODY()からですね。

これはUEのC++の特徴でUCLASSを使用したUE4用のクラスとして、

使用する場合は必ず呼び出す必要のあるマクロになります。

続いてPublic:やProtected:などのアクセス修飾子になります。

Public →変数宣言後などほかのクラスでも呼び出せる。

Protected → サブクラスからなら呼び出せる。

private → 同一クラス内のみで呼び出せる。

続いて一番上のATestActor();についてですが、

こちらはコンストラクタ用の宣言になりBPで表すと下記のノードになります。

コンストラクタ用ノード

続いてvirtual void Tick(float DeltaTime) overrideになります。

C++のvirtual ? override? となる方が多いと思うので、

こちらも少し説明します。

まずVirtualについてですがこれは継承したクラスの関数を、

カスタムして使用したい時に使用します。

overrideを書く理由はオーバーライドした関数ということを表します。

ヘッダーファイル内の変数や関数について

UPROPERTYですがUE4上での変数の扱い方などを設定することが可能です。

細かい部分はこの後説明しますが書いてある部分は説明します。

EditAnywhere → どこでも編集が可能

Category ="" → カテゴリの設定

BlueprintReadWrite → BP上で呼び出せて編集等行えること

今回追加した変数で追加したものは、

回転板用のStaticMeshComponentと、

回転動作を司るRotatingMovementComponentと、

回転量の変数でFRotatorこの3つを作成しています。

ヘッダーファイルは宣言のみなので以上になります。

CPPファイル内の処理

今度はCPPファイルの方の紹介になります。

#include "TestActor.h"

まず元のヘッダーファイルのみ宣言してます。

これによりヘッダーファイルの関数・変数を使用できます。

// Sets default values
ATestActor::ATestActor()
{

こちらはコンストラクタの処理になります。

ATestActor::ATestActor()がコンストラクタ用の宣言になります。

    // 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;

bCanEventTickでTickを使用するかどうかのフラグをfalseにしています。

※今回は使用していないのでfalseにしていますが
 もし必要があればそのままにしてください。

    // StaticMeshComponentの作成
    Mesh = CreateDefaultSubobject<UStaticMeshComponent>("StaticMesh");

StaticMeshComponentとしてSubobjectのStaticMeshを作成します。

    // コンポーネントのアタッチ
    Mesh->SetupAttachment(RootComponent);

必要はないですが一応ルートコンポーネントにアタッチしてます。

    // ObjectとしてStaticMeshオブジェクトをロード
    static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeVisualAsset(TEXT("/Game/LevelPrototyping/Meshes/SM_Cube.SM_Cube"));

スタティックメッシュ用のモデルデータ情報をロードします。

    // キューブアセットのロードに成功した場合
    if(CubeVisualAsset.Succeeded())
    {
        // モデルのセットと位置のセット
        Mesh->SetStaticMesh(CubeVisualAsset.Object);
        // Mesh->SetRelativeLocation(FVector(0.0f,0.0f,0.0f));
    }

モデルをロードできたらロードしたメッシュを適応します。

    // メッシュの大きさを指定
    Mesh->SetRelativeScale3D(FVector(5,5,0.5f));

回転板にするために縦横の倍率を5にして縦幅を0.5fにする。

    // RotatingMovementComponentのコンポーネント設定
    Rotating = CreateDefaultSubobject<URotatingMovementComponent>(TEXT("Rotation"));

RotatingMovementComponentとしてSubobjectのRotationを作成します。

    // 回転する軸の位置を指定
    Rotating->PivotTranslation = FVector(250,250,250);

回転する軸の位置と回転量をそれぞれ設定します。

※ポインタ(*)の付いた変数は「->」アロー演算子で呼び出します。

    // 回転量を設定
    MeshRotationValue = FRotator(0,180,0);
}

 

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

BeginPlayの関数内になります。

※Super:BeginPlay();ではC++にはなくUE特融のものになります。

    // 回転する軸に回転量を設定
    Rotating->RotationRate = MeshRotationValue;

最後に回転量をRotationRate(RotationMovementの回転量)に渡します。

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

最後にTickになりますが今回は使用していないので何も処理はしません。

}

以上が今回作成した回転処理になります。

後はこれをマップ上でドラッグアンドドロップして配置したり、

回転速度が速い場合は数値を変更してみてください。

C++のアクターの配置と回転量設定

実際に動かしたものは下記ツイートになります。

・目次に戻る

UPROPERTYの説明

ここではもう少しUPROPERTUYについて、

少し触れていきたいと思います。

まずUPROPERTYとは何ぞや?というお話になるかと思います。

UPROPERTYとはUE特有のメタデータや指定子を設定するための、

マクロ宣言になります。

この中では主にどのようにUE上でアクセスできるか?

その他別の方法でのアクセスを有効にするかなど設定できます。

※余談ですがこういったマクロ関連の部分は、

 Engine/Source/Runtime/CoreUObject/ObjectMacros.hに、

 すべての設定方法が記されているのでこちらを見るのも便利です。

アクセス関係については私が説明するまでもなく、

下記のQiitaに分かりやすく説明されているので私の方では省きます。

それ以外で私が使いそうなものをいくつか紹介させていただきます。

〇Config・GlobalConfigについて

値や数値の変数の中でUPROPERTY(VisibleAnywhere,Config)と設定します。

次にUClass()の中に「Config=Game」を記載します。

実際にプログラムで書くと下記のような形になります。

UCLASS(Config=Game)
class CCODEEXAMPLE_API ATestCubeActor : public AActor
{
    GENERATED_BODY()
    // Configテスト用変数
    UPROPERTY(VisibleAnyWhere, GlobalConfig, Category="CustomValiable")
    float FloatTest;
};
後はどこでこのパラメータをConfigとして設定するのか?
という話になるかと思いますがそれはConfigフォルダ内の、
DefaultGame.iniに記載します。
/Script/CCodeExample←ここまでがフォルダ階層
.TestCubeActor←これがファイル名
後は「指定した変数名=それに入れたい値」を入れればOKです。
[/Script/CCodeExample.TestCubeActor]
FloatTest=1.3423f
これで実際に動かしてみるとFloatTest内の値がConfigに設定した値になります。

DefaultGame.iniで設定した値の確認

こちらは各種ゲームの設定値を入れたりコンフィグの値を設定するのに、

便利だったりするので覚えておいて損はないかなと思い紹介しました。

ドキュメントにも紹介されてるのでもう少し細かい説明はこちらで。

コンフィギュレーション ファイル | Unreal Engine ドキュメント

それからGUI関係で行いたい場合は下記を参照

[UE4] 「エディタの環境設定」や「プロジェクト設定」に項目を追加する|株式会社ヒストリア

すいませんUPROPERTYまわりやUCLASS周りは色々あるんですが、

もっと細かく書くために別記事に分けようと思います。

C++専用で何か作りたいなと思います。

・目次に戻る

Q&A

ここからはこの記事を書きながら疑問に思うかなと思ったことなどを、

Q&A方式で残していこうと思います。

※今後色々分かったことがあったら増やしていきます。

Q:プログラム言語に振れたことがないのでC++自体が良くわかりません。

A:まずはC++の元となっているC言語の扱いから学びましょう。

 いくつか本もありますが動画で教えているサイトもあります。

 まずはこちらをやってみるのが良いでしょう

C言語入門 (全22回) - プログラミングならドットインストール

 本で個人的におすすめしている本をいくつか書いておきますね。

独習C++ 新版(高橋 航平 επιστημη(エピステーメー))|翔泳社の本

ゲームプログラミングC++(Sanjay Madhav 吉川 邦夫 今給黎 隆)|翔泳社の本

Q:UE関連のC++の書籍などを購入したいのですが、

 どこかにまとまってないでしょうか?

A:C++onlyでリンクまとめてみました。

C++でつくるUnreal Engineアプリ開発for Windows & m / 鈴木 晃【著】 - 紀伊國屋書店ウェブストア|オンライン書店|本、雑誌の通販、電子書籍ストア

アンリアる! C++入門編 ~対話形式で学ぶUnreal Engine~ - Colory Games - BOOTH

Q:GetPlayerPawnなどの呼び出し方が分かりません・・・

A:Kismet/GameplayStatics.hから呼び出すことができます。

 GameplayStatics内にGetPlayerCharacterやGetPlayerPawnなどがあります。

 ヘッダーファイルの方に「#include kismet/GameplayStatics.hを宣言して」、

 CPPファイルの方に下記のような形で呼び出すことで取得できます。

 ※GetWorldはどこからPlayerCharacterのデータを引っ張ってくるかを表します。

  AActor::GetWorld()などクラスに合う形で取得してください。

ACharacter *TestCharacter = UGameplayStatics::GetPlayerCharacter(GetWorld(),0);

・目次に戻る

最後に

ここまで見ていただきありがとうございました!

今回はだいぶ文章が多めのものになりますが、

これだけの知識だとまだまだC++で全部作れる。

というわけにはいかないので今後もいろいろ記事を作っていこうと思います。

一旦はここまでで見ていただきありがとうございました。