Featured image of post [UE5] 『Add C++ Class』ウィザードが自動生成するコードの内容をカスタマイズする (新規項目追加編)

[UE5] 『Add C++ Class』ウィザードが自動生成するコードの内容をカスタマイズする (新規項目追加編)

UE 5.1.1

はじめに

前回の記事では、『Add C++ Class』ウィザードが自動生成するコードをカスタマイズしたい場合、

  • ① 対応する Template ファイルが存在するクラスであれば、エンジンビルドなしでカスタマイズできる (Launcher 版でも OK)
  • ② 対応する Template ファイルが存在しないクラスの場合、エンジンコードの修正とビルドが必要になる

ということを述べ、① の場合の手順について解説しました。

今回は、② の場合の手順について解説します。

エンジンコードの修正が必要となるので、カスタムエンジンを使用してください (Launcher 版は ❌)。

前回の内容を理解しているという前提での解説となります。わからないことが出てきた場合は、前回の記事で解説されていないか見直してみてください。

手順の概要

  • Template ファイルを作成し、Templates ディレクトリに追加する
  • エンジンコード内の以下の関数を編集して、特定のクラス選択時に追加した Template が使われるようにする
    • FNewClassInfo::GetHeaderTemplateFilename() (/Engine/Source/Editor/GameProjectGeneration/Private/GameProjectUtils.cpp)
    • FNewClassInfo::GetSourceTemplateFilename() (/Engine/Source/Editor/GameProjectGeneration/Private/GameProjectUtils.cpp)
  • エンジンをビルドする

実例

UCheatManager の自動生成コードをカスタマイズして、Console Command のサンプルコードを含むようにしてみます。

Template ファイルを新規追加する

Templates ディレクトリに、UCheatManager 用のテンプレートを追加します。

Template ファイルを一から記述するのは面倒なので、UObject 用の template ファイルを複製し、これらを改変する形で作ります。

  • UObjectClass.h.template
  • UObjectClass.cpp.template

を複製し、ファイル名を

  • CheatManagerClass.h.template
  • CheatManagerClass.cpp.template

に変更します。

内容を以下のように変更します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
%COPYRIGHT_LINE%

#pragma once

#include "CoreMinimal.h"
%BASE_CLASS_INCLUDE_DIRECTIVE%
#include "%UNPREFIXED_CLASS_NAME%.generated.h"

/**
 * %CURSORFOCUSLOCATION%
 */
UCLASS(%UCLASS_SPECIFIER_LIST%)
class %CLASS_MODULE_API_MACRO%%PREFIXED_CLASS_NAME% : public %PREFIXED_BASE_CLASS_NAME%
{
    GENERATED_BODY()

    %EVENTUAL_CONSTRUCTOR_DECLARATION%
    %CLASS_PROPERTIES%
    %CLASS_FUNCTION_DECLARATIONS%
    
    // Console Command Sample
    UFUNCTION(exec)
    void Echo(const FString& String) const;
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
%COPYRIGHT_LINE%

%PCH_INCLUDE_DIRECTIVE%
%MY_HEADER_INCLUDE_DIRECTIVE%
%ADDITIONAL_INCLUDE_DIRECTIVES%

%EVENTUAL_CONSTRUCTOR_DEFINITION%
%ADDITIONAL_MEMBER_DEFINITIONS%

// Console Command Sample
void %PREFIXED_CLASS_NAME%::Echo(const FString& String) const
{
    UE_LOG(LogTemp, Log, TEXT("%s"), *String);
}

Console Command のサンプルとして、Echo というメンバ関数の宣言・定義を追加しています。定義の部分には %PREFIXED_CLASS_NAME% マクロを使用しています。

追加した Template が使用されるようにする

/Engine/Source/Editor/GameProjectGeneration/Private/GameProjectUtils.cpp を開き、FNewClassInfo::GetHeaderTemplateFilename()FNewClassInfo::GetSourceTemplateFilename() に以下のような記述を追加します。

490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
FString FNewClassInfo::GetHeaderTemplateFilename() const
{
    switch(ClassType)
    {
        case EClassType::UObject:

            (省略)

                if ((BaseClass == UActorComponent::StaticClass()) || (BaseClass == USceneComponent::StaticClass()))
                {
                    return TEXT("ActorComponentClass.h.template");
                }
                else if (BaseClass == AActor::StaticClass())

                (省略)

                // ↓ ここから追加
                else if (BaseClass == UCheatManager::StaticClass())
                {
                    return TEXT("CheatManagerClass.h.template");
                }
                // ↑ ここまで追加
            }
            // Some other non-actor, non-component UObject class
            return TEXT( "UObjectClass.h.template" );

            (省略)

}
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
FString FNewClassInfo::GetSourceTemplateFilename() const
{
    switch(ClassType)
    {
        case EClassType::UObject:

            (省略)

                if ((BaseClass == UActorComponent::StaticClass()) || (BaseClass == USceneComponent::StaticClass()))
                {
                    return TEXT("ActorComponentClass.cpp.template");
                }
                else if (BaseClass == AActor::StaticClass())

                (省略)

                // ↓ ここから追加
                else if (BaseClass == UCheatManager::StaticClass())
                {
                    return TEXT("CheatManagerClass.cpp.template");
                }
                // ↑ ここまで追加
            }
            // Some other non-actor, non-component UObject class
            return TEXT( "UObjectClass.cpp.template" );

            (省略)

}

前回解説したとおり、これらの関数は、『Add C++ Class』ウィザードで使用される Template ファイルを決定するために使われるものです。

両方の関数に『UCheatManager クラスが選択された場合、“CheatManagerClass.*.template” を返す』という条件分岐ブロックを書き足すことで、追加した Template ファイルが使用されるようになります。

エンジンビルドをして動作確認する

エンジンビルド後に『Add C++ Class』ウィザードを開き、UCheatManager の派生クラスである UMyCheatManager を作成してみます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// Copyright HogeFuga, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/CheatManager.h"
#include "MyCheatManager.generated.h"

/**
 * 
 */
UCLASS()
class MODULENAME_API UMyCheatManager : public UCheatManager
{
    GENERATED_BODY()
	

    // Console Command Sample
    UFUNCTION(exec)
    void Echo(const FString& String) const;
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Copyright HogeFuga, Inc. All Rights Reserved.


#include "MyCheatManager.h"


// Console Command Sample
void UMyCheatManager::Echo(const FString& String) const
{
    UE_LOG(LogTemp, Log, TEXT("%s"), *String);
}

追加した Template ファイルをベースに、ファイルが生成されていることが確認できました!

(* ´∀`)<おわり