Unity歴10年のエンジニアがUnreal Engineを学ぶときに戸惑ったこと

先日、友人の [SensitiveCubeさん](https://x.com/onCube_jp) にお誘いいただき、Unreal Engineで初めてゲームを作ってみました！
完成したゲームはこちらです。「UE5ぷちコン」に応募しました。

https://x.com/segur_vita/status/1909564629698691502

私はUnityをかれこれ10年近く業務で使っています。
そんな私がUnreal Engineを触ってみて感じた「戸惑い」を紹介していこうと思います。


## デフォルトでモーションブラーやレイトレーシングがONになっている

一番衝撃を受けたのは、デフォルトのFirstPersonサンプルを開いたとき、**初期状態でレイトレーシングがON**になっていたことでした！

たとえば、CubeにEmissiveColorを設定しただけで、床や壁にも反射した色が乗る状態になります。

| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/33767aab-304b-41e1-9aab-688f3b736957.png) |
|---|
| CubeのMaterialにEmissiveColorを設定しただけのシーン<br>床や壁に反射した色が自動で乗る |

これを見たとき、カルチャーショックを受けました。

初学者がライティングを学ぶ動機を失ってしまうのではないか、とも感じました。


## 「Level」という用語に戸惑った

日本で「レベル」というと、キャラクターの成長度を表す数値を連想する人が多いと思います（例：経験値を積んでレベルアップ）。

しかし、Unreal Engine（UE）における「Level」は、**UnityでいうScene**に相当する概念です。

もちろん、Unity界隈でも「Level」という言葉を地形やマップの意味で使うことはあります。
実際、過去に書いた私の記事の中でもそのことに触れています。

https://qiita.com/segur/items/db3fecf170e67d7c739c#ゲーム業界の英語が少し難しかった

それでも、**正式な用語として明確に「Level」と提示されると**、戸惑いました。


## BlueprintはJSON、GameObjectはXMLに似ている？

UEのBlueprintは、UnityでいうPrefabに近い存在です。

Blueprintは、複数のコンポーネント（Static Mesh、Collision など）を内包できますが、このコンポーネントの役割はUnityのコンポーネントとは少し異なります。  
Blueprintはコンポーネントとして、**別のBlueprintを置くことができる**からです。
ここに最初は戸惑いました。

この構成の違いは、XMLとJSONの違いにも似ていると感じました。

### UnityのGameObjectはXMLに似ている

以下はXMLのサンプルです。

```xml
<Event name="〇〇勉強会" date="2025-XX-XX" place="〇〇会議室">
  <Session time="10:00" title="オープニングセッション" />
  <Session time="11:00" title="最新技術紹介" />
  <Session time="13:00" title="ハンズオン" />
</Event>
```

XMLは「要素（Element）」の配下に別の「要素（Element）」を持てます。
これは、GameObjectが配下に別のGameObjectを持てる構造に似ています。

それとは別に、XMLの「要素（Element）」は「属性（Attribute）」を持てます。
上記のサンプルの `name` や `time` が属性です。
これは、GameObjectがComponentを持つ構造に似ています。

### UEのBlueprintはJSONに似ている
一方、JSONはすべての情報を要素としてネスト構造で表現します。

以下はJSONのサンプルです。

```json
{
  "event": {
    "name": "〇〇勉強会",
    "date": "2025-XX-XX",
    "place": "〇〇会議室",
    "schedule": [
      {
        "time": "10:00",
        "title": "オープニングセッション"
      },
      {
        "time": "11:00",
        "title": "最新技術紹介"
      },
      {
        "time": "13:00",
        "title": "開発ハンズオン"
      }
    ]
  }
}
```

XMLにおける属性のような概念はなく、すべて並列に並びます。
UEのBlueprintはこの構成に近いと感じました。


## BlueprintのFunctionはカプセル化できる

BlueprintのFunctionは、Unity Visual Scripting（旧Bolt）のSubgraphよりも、**より正統派な関数**として扱えます。

具体的には、public、privateなどアクセス管理ができます。

| ![アクセス管理](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/4feda22d-2547-4582-a09d-6b9fed7af399.png) |
|---|
| アクセス管理の図 |

つまり、Blueprintは**C#のclassに近い感覚で設計できる**のです。

これは嬉しい戸惑いでした！


## Blueprintでポリモーフィズム！

まだまだ驚くことがあります。
Blueprintでは、なんと**Interfaceが使えます！**

UnityのVisual Scripting（旧Bolt）には、Interfaceに相当する機能がありません。
そのため、テスト用スタブを作ったり、依存性を分離した設計をするのが難しいです。

しかし、Unreal EngineのBlueprintでは、Interfaceを使ったポリモーフィズムが実現できます！

具体例として、私は「マウスクリック」や「マウスホバー」に対応したInterfaceを作成してみました。
Interfaceは**Functionの宣言だけ**を行います。

| ![Interface](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/c40c8ab2-e5f2-4186-b3e1-788a667e88e2.png)|
|---|
| マウス操作に対応したInterfaceの例 |

このInterfaceを継承するBlueprintを作って、Functionの具体的な処理はそちらに記述します。

| ![Interfaceを実装したBlueprint](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/630f20b3-a43f-4816-a371-72009cfd3147.png) |
|---|
| Interfaceを実装したBlueprintの例 |

Functionを呼び出す側では、以下のように記述します。
**個別のBlueprintを意識せず、Interface越しにFunctionを実行**しているだけです。

| ![Interfaceを呼ぶ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/6347b4aa-cd86-42e7-a758-59beac7fc883.png) |
|---|
| Interface経由でFunctionを呼び出している例 |

Visual ScriptingやPlayMakerに慣れていた身としては、感動しました！


## Blueprintは依存性の逆転ができる！

Unreal EngineのBlueprintには、UnityのC#におけるAction Delegateに相当する機能があります。
それが**Event Dispatcher**です！

残念ながら、UnityのVisual Scriptingにはこの仕組みはありません…

| ![Event Dipatcher](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/d5d666e6-5559-4e7d-9c06-1f1f7d7912a4.png) |
|---|
| Event Dispatcherの図 |

Event Dispatcherを使うと、**依存性の逆転（Dependency Inversion）**が実現できます！
これによって**疎結合なBlueprint**が作りやすくなっています。


# さいごに

Unreal Engineを触り始めたときは、正直ネガティブな戸惑いもありました。
ですが、触っていくうちにポジティブな意味での驚きや感動を覚えるようになりました。

この感覚は、かつて新しいプログラミング言語を学んだときに感じたワクワクにとてもよく似ています。
そんな気持ちを久しぶりに味わうことができました。

挑戦してみて本当に良かったです！

本記事作成にあたり、以下のページを参考にさせていただきました。ありがとうございました！

- [UnityからUnreal Engineへの移行ガイド](https://dev.epicgames.com/documentation/ja-jp/unreal-engine/unity-to-unreal-engine-overview)
- [Unreal Engine 5.2 チュートリアル](https://dev.epicgames.com/community/learning/courses/qlm/unreal-engine-5-2/oEoB/unreal-engine-5d4937)

---

ここからは補足です

# 追記
Unityをあまり知らない方が本記事を読んで、「UEの方がUnityより優れている」という誤解が生まれそうなので、補足しておきます。

Unityにも、BlueprintのEventGraphに相当する機能として、 **Visual Scripting（旧Bolt）** があります。
ただ、Visual ScriptingにはInterfaceやEvent Dispatcherといった機能がないため、大規模なプログラミングにはあまり向いていません。

とはいえ、これをもってUnityがUEより劣っている、という話ではありません。

Unityには、標準で**C#という非常に強力なオブジェクト指向言語**が搭載されています。
Unityエンジニアは基本的にC#を使い、InterfaceやDelegate（Event Dispatcherに相当する仕組み）を活用できますし、C#にはより高度な機能も豊富に備わっています。

Visual Scriptingを使うケースは、

- C#が使えない特殊な実行環境
- プログラミングを本業としないクリエイター

など、限られた状況での利用が中心です。
通常の開発ではC#が使用されます。

そのため、本記事はUEとUnityの優劣を比較するものではありません。
あくまで、Visual ScriptingとBlueprintを比較したときに感じた違いについて述べたものです。