C++ ときどき ごはん、わりとてぃーぶれいく☆

Wonder Rabbit Projectのなかのひとのブログ。主にC++。

UE4: 4.16 から 4.17 へアップグレードした際に遭遇した諸問題と解決について

4.16で開発していたプロジェクトを4.17へアップグレードした際に遭遇した問題と解決方法を整理します。

問題と解決方法

1. 4.15 向けのプラグインがビルド不能に陥った

レベル内の重力を器用に扱いたい場合に便利なプラグインとして CustomGravityPlugin (参考1)があります↓。更新が4ヶ月以上停止していて、4.15以降ではwarningが生じる状態(但しビルドはできた)でした。4.17ではビルドできなくなりました。

このプラグインを4.17で使う際の問題は、4.15で導入された ReadOnlyTargetRules に対応したコンストラクターを定義した <plugin>.Build.cs が定義されていない事でした。修正せずにビルドを試みると以下のような警告が表示されます。

C:\Users\usagi\tmp\\Plugins\CustomGravityPlugin\Source\CustomGravityPlugin\CustomGravityPlugin.Build.cs: warning: Module constructors should take a ReadOnlyTargetRules argument (rather than a TargetInfo argument) and pass it to the base class c onstructor from 4.15 onwards. Please update the method signature.

また、このプラグインはIWYU(参考2、参考3、参考4)に対応したコードになっていないため、ついでにIWYUにも対応しました。

<plugin>.Build.cs の ctor を ReadOnlyTargetRules をサポートするよう書き換え、IWYUの運用を設定します。

// original
public CustomGravityPlugin(TargetInfo Target)
{
// changed
public CustomGravityPlugin(ReadOnlyTargetRules Target) : base(Target)
{
  // IWYU 対応
  PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
  // memo: CustomGravityPlugin の場合は 4.16 時点でもこれがないとビルドできません。
  // 4.17でも同様なので、他の PublicIncludePaths.AddRange などと同様に ctor 内に書き加えます。
  PublicDependencyModuleNames.AddRange
  ( new string[]
    { "Core", "CoreUObject", "Engine", "InputCore"
    }
  );

その後、プラグインの全ての .h ファイルの冒頭へ #include "CoreMinimal.h" と必要に応じた UE4 のヘッダーファイルの #includeAPI リファレンスなど参考に書き加え、全ての .cpp ファイルの冒頭へ #include "<source>.h" を書き加えます。

2. ヘッドマウントディスプレイ関連のコードがリンクエラーやwarningを出すようになった

4.17からヘッドマウントディスプレイ関連のコードがモジュール化されました(参考5)。これに伴い、ヘッドマウントディスプレイを扱うUE4のプロジェクトを4.16から4.17へアップグレードする際には主に2つの修正作業が必要です。

  1. ヘッドマウントディスプレイ関連の #include "Kismet/<file>.h"#include "<file>.h" へ変更します。(Kismet/が付かなくなります。)
  2. <project>.Build.csPublicDependencyModuleNames.AddRangeHeadMountedDisply を追加しモジュールに必要なライブラリーのリンクを定義します。
// 4.16 以前
#include "Kismet/HeadMountedDisplayFunctionLibrary.h"
// 4.17 以降
#include "HeadMountedDisplayFunctionLibrary.h"
PublicDependencyModuleNames.AddRange
  ( new string[]
    { "Core", "CoreUObject", "Engine", "InputCore"
    // ↓ヘッドマウントディスプレイのモジュール
    , "HeadMountedDisplay"
    }
  );

3. operator[] の呼び出しコードを文法エラー扱いされるようになった

int operator[]( int ) が定義されたクラスの内部でこれを使いたい場合、auto result = operator[]( parameter ); のように記述できるが(参考6)、そのようなコードについて、

error C3861: ‘[]’: identifier not found

のようにエラーを出力されコンパイル不能扱いされてしまいました。

これは正確にはUE4、4.16から4.17へアップグレードとは直接の関係は無く、Windows 環境向けに Microsoft Visual Studio という(残念ながら)昔から間抜けな実装やバグでも有名な開発環境を使用している場合に起こる問題でした。

4.16のプロジェクトを4.17のエンジンでアップグレードして読み込もうとした際に作られるプロジェクトのコピーのプロジェクト設定のPlatform、Windows、Toolchain の設定が default にセットされた状態となり、 4.16 のプロジェクトの際には Visual Studio 2017 を指定していたプロジェクトのソースの一部がアップグレード直後に default ( = Visual Studio 2015 ) でのビルドとなりコンパイル不能となっていました。

少し困った事に、 Unreal Editor の GUI が起動しない事にはどこかにある設定ファイルの該当項目を探し出してテキストエディターで書き換える手間が必要です。あるいは、一時的に operator[]( parameter ) のようなコードを (*this)[ parameter ] のようにバギーな旧式の Visual Studio でも問題の無いコードに書き換えてあげて一端ビルドが通る状態で Unreal Editor を起動させ、プロジェクト設定を GUI から変更する必要があります。

所感

4.16 プロジェクトを 4.17 へアップグレードする手間はゼロではありませんでしたが、それほど大変な事はありませんでした😃

参考

  1. GitHub - mhousse1247/UE4-CustomGravityPlugin: Unreal Engine 4 : Custom Gravity Plugin
  2. IWYUでコーディングしよう - #memo
  3. Game Engine Technology by Unreal
  4. Unreal Engine | IWYU リファレンス ガイド
  5. Game Engine Technology by Unreal
  6. [Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ