UE4のVRアプリをUE5にバージョンアップした話

この記事はUnreal Engine (UE) Advent Calendar 2023(シリーズ 1)の8日目の記事です。

https://qiita.com/advent-calendar/2023/ue


# はじめに
UE4.27で作成していたマルチプレイVRアプリをUE5に対応させました。
UE4の頃は、エンジンのマイナーバージョンアップに合わせて常に最新バージョンを使うようにアプデしてきたのですが、UE4→UE5のアプデは数々の困難が立ちはだかり、非常に苦労しました。

UE5.1.0の時点でバージョンアップ作業を始めたものの、アプリ側での修正点や無視できないエンジンバグが多く、最終的にリリース可能なレベルと判断できたのがUE5.2.1で、期間にして10ヶ月ほどかかりました。
（途中別の作業に手を取られていた時期もありましたが）

本当に大変だったので同じ苦労をする人が1人でも減るように、（今更ですが）対応の記録を記事にまとめます。

:::note warn
バグ対応の話なので、基本的に内容がネガティブ寄りです。
開発作業中のネガティブ要素を抽出したような記事になっています。

……ですが、実際のVR開発はとても楽しいです！
皆やろうよVR開発！！！
:::



# アップデート対応作業の概要

:::note alert
バージョン管理をせずにアップデート作業を行うと確実にﾀﾋにます。
必ずバージョン管理をして元の状態に戻せるようにしてください。

バージョン管理について書いた[こちらの記事](https://www.docswell.com/s/abricheese/5R4VE5-2022-08-13-181950)もよろしければご覧ください。（ダイマ）
:::

### ざっくりアプデの手順
詳しい手順は次の章に書きます。

1. プロジェクトのバージョンをUE5.1に変更

1. 使用しているプラグインをUE5.1のものに変更していく

1. slnファイルの作成

1. Visual Studioでビルド

1. UEエディタ起動時にクラッシュしたのでその対応

1. BPのコンパイルエラーを解消して、PIE/VRプレビューを実行できるようにする

1. PIE/VRプレビューを実行して、実行中に発生したエラーに対応する

1. エラーは出ないが正しく機能しなくなったものに対応する

1. パッケージングしたアプリで正しく機能しなくなったものに対応する

1. 上記を対応している間にUE5.2がリリースされたのでもう一度同じ対応をしていく
（以降ループ……）


# 各作業で発生した問題や詳しい手順など
同じ問題に遭遇した人の参考になるように、遭遇した問題などについて記載していきます。

エラーメッセージで検索したときに使える情報にするために、細かな問題も挙げていて長いです。
全て読む必要はありません。

解決したものもあれば、解決できずに妥協したものもあり、解決策がよくわからないけどいつの間にかよくなったものもあります。
（マイナーバージョンアップ（UE5.1.0→UE5.1.1など）で解消したものに関しては、同じバグに遭遇することは少なそうなので割愛します。）

## プロジェクトのバージョンをUE5.1に変更
 [Unreal Engine 5 への移行ガイド](https://docs.unrealengine.com/5.1/ja/unreal-engine-5-migration-guide/)を参考に、プロジェクトのバージョンをUE4.27→UE5.1に変更しました。

何か壮大な処理が行われるのかと思いましたがあっという間に終わり、ソース管理対象ファイルの変更点は.uprojectに記載のエンジンバージョンがUE5.1に変更されただけでした。


## 使用しているプラグインをUE5.1のものに変更していく
マケプレで最新版が公開されているものは最新版に置き換えました。

プロジェクト独自で改修を加えていれば置き換えたうえで以前と同様に改修し、マケプレで最新版がまだ出てないものやオワコンになっているものはエンジンバージョン表記のみ書き換えて（.upluginのEngineVersionを5.1.0に書き換えました）、この先の手順でビルドしてエラーが出たら対応しました。


## slnファイルの作成
slnファイル作成のため、.uprojectファイルを右クリック＞Generate Visutal Studio project fileを実行して、出てきた下記エラーを対応しました。

### error CS0117: 'UnrealTargetPlatform' does not contain a definition for 'Win32'
原因：
UE5でWin32のパッケージングが出来なくなったため

対応：
`UnrealTargetPlatform.Win32`の記述を削除


### error CS1503: Argument 1: cannot convert from 'UnrealBuildTool.ModuleRules.RuntimeDependency' to 'string'
対応前：
`RuntimeDependencies.Add(new RuntimeDependency(Path.Combine(dllPath, dll)));`

対応後：
`RuntimeDependencies.Add(Path.Combine(dllPath, dll));`

参考：
[サードパーティ ライブラリ](https://docs.unrealengine.com/5.1/ja/integrating-third-party-libraries-into-unreal-engine/)


## Visual Studioでビルド
Visual Studioでプロジェクトのビルドを行い、エラーが出たものを対応しました。

UE5.1に対応していないプラグインや独自のプラグインでエラーが出たものもここで対応しました。
エラーが解消できないものでそれほど重要な機能ではないものは、一旦プラグインごと削除してアプデを待ちつつ他の作業を先に進めていきました。


:::note warn
[公式ドキュメント](https://docs.unrealengine.com/5.3/ja/setting-up-visual-studio-development-environment-for-cplusplus-projects-in-unreal-engine/)に記載の通り、UEの作業ではVisual Studioのエラーリストウィンドウを使用することは推奨されていません。
~~読みづらいですが、~~ ビルドログを追ってエラー内容を確認することをお勧めします。
:::

### Unable to find plugin '[プラグイン名]' (referenced via [プロジェクト名].uproject). Install it and try again, or remove it from the required plugin list.
原因：
UE5で廃止になったエンジンプラグインを使用していたため

対応：
.uprojectから該当プラグインの記載を削除
（プラグインを参照している部分も修正する）

### 現在の.NET SDKは、ターゲットとする.NET 6.0をサポートしていません。.NET 5.0以下をターゲットとするか、.NET 6.0をサポートする.NET SDKのバージョンを使用してください。
原因：
使用していたVisual Studio2019が.NET6.0に対応していなかったため

対応：
Visual Studio2022に変更

備考：
.NET 6.0 SDK (v6.0.404)をインストールしてVisual Studio2019で使おうとしましたが、エラーが解消できませんでした。


## UEエディタ起動時にクラッシュしたのでその対応
Visual Studioでビルドが通ってほっとしたものの、.uprojectをダブルクリックしてUEエディタを開こうとするとクラッシュしました。

エラーメッセージ：
`Fatal error: [File:D:\build\++UE5\Sync\Engine\Source\Runtime\Engine\Private\ShaderCompiler\ShaderCompiler.cpp] [Line: 4668] /Engine/Private/DepthOnlyVertexShader.usf(44,45-60): error X3018: invalid subscript 'InstanceId' /Engine/Private/BasePassVertexShader.usf(40,51-66): error X3018: invalid subscript 'InstanceId' /Engine/Private/PositionOnlyDepthVertexShader.usf(23,51-66): error X3018: invalid subscript 'InstanceId' /Engine/Private/DebugViewModeVertexShader.usf(56,51-66): error X3018: invalid subscript 'InstanceId' /Engine/Private/VelocityShader.usf(53,51-66): error X3018: invalid subscript 'InstanceId' Failed to compile default material /Engine/EngineMaterials/WorldGridMaterial.WorldGridMaterial!`

原因：
エンジンバグ（Instanced Stereoが有効になっているときにLiDAR Point Cloud Supportプラグインを有効化するとクラッシュする）
→UE5.2で解消

対応：
DefaultEngine.iniでInstanced StereoをFalseに変更

参考：
[フォーラム](https://forums.unrealengine.com/t/lidar-plugin-for-ue-5-1-crashes-editor-on-install/731790/5)
[バグレポート](https://issues.unrealengine.com/issue/UE-175226)



## BPのコンパイルエラーを解消して、PIE/VRプレビューを実行できるようにする
無事エディタを起動できたところで、早速実行ボタンを押すとコンパイルエラーになっている箇所が一覧で表示されるので、出てきたコンパイルエラーを解消していきました。
（プロジェクト独自の実装によるエラーなので詳細は割愛）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/d4a2b9f6-a791-19bd-1ceb-addab257f192.png)

プラグインのアプデ待ちで一旦プラグイン自体を削除しておいたところでもエラーが出るので、そこは暫定的にエラーが出ないような対応をしました。

マケプレのプラグインでUE4の頃と同じ関数名なのに引数が全く異なっていたものもあったので対応しました。~~互換性を持たせてくれぇ……~~



## PIE/VRプレビューを実行して、実行中に発生したエラーに対応する
コンパイルエラーを解消でき、晴れてアプリを実行できるようになったので、実際に動かしてみて発生したエラーを修正しました。
（プロジェクト独自の実装によるエラーなので詳細は割愛）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/2c849024-bf51-c53b-f1fa-6951322cd590.png)




## エラーは出ないが正しく機能しなくなったものに対応する
エラーではないものの挙動や見た目に問題のあるものがないかを、アプリを動かしてみて確認していきました。

### Questのコントローラーでスティック操作が効かない
原因：
下記赤枠で囲んだ、スティックを倒したかどうかのInput値がUE5で使えなくなっていた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/cedf41c0-8310-97f5-5324-f932d5787486.png)

対応：
X-Axis/Y-Axisでスティック操作を取得するように変更

備考：
下記のタッチ判定も取れなくなってました。。
![FmwfXnPaUAAWSGN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/874429e1-2c90-60c7-ebcf-4b5c1d8b958d.png)


### GPUがクラッシュしているか、D3Dデバイスが削除されています。
~~UE5でよく見るやつ~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/ffe945fc-4e8a-49aa-1c2e-4300256f5f8c.png)

原因：
GPUのスペック不足など

対応：
エディタのメインウィンドウから設定＞エンジンの拡張機能設定＞スケーラビリティの品質を下げた
（変更内容はPCスペックや確認したい内容に合わせて変更してください。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/072ade1c-b40e-ec4e-f862-51fa2af10f93.png)

参考：
[GPU ドライバーのクラッシュを解決する方法](https://docs.unrealengine.com/5.3/ja/how-to-fix-a-gpu-driver-crash-when-using-unreal-engine/)

### UEエディタの起動が途中で止まる
様々なプロジェクトで時々発生してます……

https://twitter.com/abricheese/status/1661340776637530112

原因：
不明
（UE5.2では頻度減ったかも？）

対応：
タスクマネージャーから終了してUEエディタを再起動もしくはPC再起動で直った


### SceneCaptureで撮影したRenderTargetをMaskedのマテリアルで使用すると、ALPHA値が反転して不透明な部分が透明になる
原因：
エンジンバグと思われる

対応：
マテリアルのALPHA値を1-xで反転させてもよかったのですが、そのほかの処理で不整合が発生しました。
今回はWidgetをテクスチャ化するために使用していたため、おかずさんの作成された下記プラグインを使用する処理に変更しました。
[UMG(Widget)をテクスチャ(RenderTarget)に描画する方法について (サンプル配布) (UE4.21に対応)](https://pafuhana1213.hatenablog.com/entry/2017/05/21/171809)



### Developmentビルドできなくなった
原因：
DefaultGame.iniで`ForDistribution=True`だったため

対応：
`ForDistribution=False`に変更

参考：
[UE5.1/5.2でForDistribution=TrueだとDevelopmentを指定してもShippingでパッケージされる](https://qiita.com/abricheese/items/86789747e1a593bd840b)


### エンジン内の音声ファイルが1個だけ鳴らなくなった
原因：
不明

対応：
UE4.27から移行してみても音が鳴らず、4.27でWAV形式でエクスポートして、5.1に取り込んだら鳴りました。


### DownloadImageでファイルパスに日本語が含まれていると画像の読み込みに失敗する
原因：
DownloadImageの内部で用いているFCurlHttpRequest・libcurlの仕様で日本語URLが扱えない

対応：
ImportFileAsTexture2Dを代わりに使用（ローカルファイルのみに有効）




## パッケージングしたアプリで正しく機能しなくなったものに対応する
エディタ実行では発生しなかったがパッケージングしたアプリで発生した不具合に対応しました。
（発見時のフェーズに合わせて分類して記載しているため、一部エディタ実行でも発生する不具合もあります。悪しからず。）


### VRの手が動かなくなることがある
VRでしばらくプレイしていると、突然手がトラッキングされなくなることがありました。
MotionControllerのTransformが更新されなくなる状態で、動かない状態でもコントローラーの各種ボタン操作はできました。
また、現象発生時にOculusボタンを押してVR内のOculusメニューを表示すると手は問題なくトラッキングされていたため、HMD側の問題ではなくUE側で何らかの問題が生じ、MotionControllerのTransformが更新されなくなったものと推測されます。

原因：
不明
VRテンプレートなどでは再現できず

対応：
不明
UE5.2.0にアップデートしたら発生しなくなったため、OpenXRプラグインの何らかの対応で改善されたものと思われます。

備考：
今回のUE5対応で困ったバグ第1位でした。。
左手が動かなくなることもあれば右手のこともあり、発生しないこともあれば両手共に動かなくなることもあって、原因や発生条件が最後まで分かりませんでした。
VRで手が動かせないというのは致命的なため、UE5.1でのリリースは断念しました。


### アプリ起動中にQuest Linkをし直すとクラッシュする
エラーメッセージ：
`Assertion failed: (Index >= 0) & (Index < ArrayNum) [File:D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Public\Containers\Array.h] [Line: 752] Array index out of bounds: 0 from an array of size 0`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/d213b3db-eff4-be7e-6c36-8fb8bca7d30c.png)

原因：
エンジンの仕様 ~~（アプリ実行中のリンクし直しがそもそも想定されていないらしい）~~

対応：
~~不能~~

[2024.03.15 追記]
下記の手順にて復帰できるようになりました！

https://qiita.com/mechamogera/items/f3a7d989606e49faf766

備考：
今回のUE5対応で困ったバグ第2位でした。。
そもそもの設計として、VRアプリはアプリ起動時からずっとHMDを接続したままで使用することを想定していたみたいですが、現状のHMDは未だ接続が不安定なものも多く、（特にケーブルが劣化してくると）途中でリンクが切断されてしまうこともあるのでそのたびにアプリ再起動が必要だとつらいです……
展示会などに参加して他の方がUE5で作られたVRアプリを体験してみても、このバグに遭遇することがちょくちょくあります。
UE4ではできていたことなので、今後UE5でも対応されていくといいのですが……



### HMDを装着したタイミング（アプリ起動後初回にスリープ解除されたとき？）にHMD内に砂時計アイコンが表示されて固まり、しばらく後にアプリがクラッシュする
エラーメッセージ①（パッケージングしたときはこれが出る、上記Quest Linkし直しで発生するものと同じ）：
`Assertion failed: (Index >= 0) & (Index < ArrayNum) [File:D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Public\Containers\Array.h] [Line: 752] Array index out of bounds: 0 from an array of size 0`

エラーメッセージ②（エディタ実行で発生するとこっちが出る）：
`Fatal error: [File:D:\build\++UE5\Sync\Engine\Plugins\Runtime\OpenXR\Source\OpenXRHMD\Private\OpenXRHMD_Swapchain.cpp] [Line: 93] Failed to wait on acquired swapchain image. This usually indicates a problem with the OpenXR runtime.`

原因：
エンジンバグ？（VRテンプレでも発生）

対応：
不明
UE5.1では割と高頻度（体感10回に1回くらい）で発生していましたが、UE5.2では頻度がかなり下がりました。（50回に1回くらい？）頻度は不明ですがUE5.3.0でも発生を確認しました。

VR関連のバグなので、HMDを使わなければ発生しません。
そのため、下記のような方法を使ってVRプレビュー以外の方法で動作確認をすると（開発中は）回避できます。
[[UE5]HMDを使わずにVRの動作確認をして開発速度を上げる](https://qiita.com/abricheese/items/9ec6a51433eaee7f1bf9)

備考：
今回のUE5対応で困ったバグ第3位でした。。
VR開発は（他のデバイスも同じかもですが）関係機関が多いので、UEのバグなのかHMDのバグなのか自プロジェクトのバグなのかの切り分けが難しいですね。



### テクスチャの見た目がサイバーパンク？になる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/138f2aa4-759a-5371-1e00-d24b23c3aae0.png)

原因：
VRAMの不足？

対応：
頻度がかなり低いので今のところ対応せず
（UE5.2で発生しなくなったかも？）

参考：
[フォーラム：I have this strange new texture glitch occuring](https://forums.unrealengine.com/t/i-have-this-strange-new-texture-glitch-occuring/629547)


### HMDのデバイス名を取得できない
「VRで開始」をFalseにしてパッケージングしてGetHMDDeviceNameを呼び出すと文字化けしました。

取得される文字列：
```
ￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍￍ,
```

原因：
エンジンの仕様（GetHMDDeviceNameはステレオレンダリングが有効化された時に初期化されるため）

対応：
`IHeadMountedDisplayModule::Get().GetDeviceSystemName();`を代わりに使用



# おわりに
UE5対応はいろいろと本当に大変で、大好きなものづくり作業もできずにバグ解析の日々が続き苦しかったですが、何とか切り抜けることができました。
バグ解析にご協力いただきましたEpic Gamesの皆様に感謝申し上げます。

苦労した分、バグ対応の実力もかなり上がったのではないかと思います。
これで次Unreal Engine6へのアップデート対応をするときも怖くありませんね！