UnityC#からUE4C++への移行、知っておくべき6つのこと

# はじめに
この記事は、Unityを使用していた筆者が、UE4を使い始めるにあたり、
UnityC#からUE4C++に乗り移るにあたって知っておくとスムーズだなと感じた点について6点、記載していきます。

:::note
想定している読者層
Unity/C#での開発経験がある程度あること。
C++の基礎的な文法知識があること。
:::

基本的には文法そのものの解説はせず、C#の考えそのままでは少々通用しづらい面や、生のC++と違うUE4に特有な面についてピックアップしていきます。
普段Unityを使用している方で、UE4を触ってみたいと考えている方や、UE4を触り始めた方に、何か参考になれば幸いです。

それでは早速本題にいきましょう。

# 1. 型推論
C#ではvar
C++ではauto
を使用します。

**落とし穴：**
C#では型推論を使えるところでは積極的に使っていくことを推奨する文化([C# のコーディング規則 (C# プログラミング ガイド) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/csharp/fundamentals/coding-style/coding-conventions#implicitly-typed-local-variables))([[雑記] 型推論の是非](https://ufcpp.net/study/csharp/sp3_var.html))([C#でもvarを使うべき3つの理由](https://www.k-karakuri.com/entry/2018/04/13/C%23%E3%81%A7%E3%82%82var%E3%82%92%E4%BD%BF%E3%81%86%E3%81%B9%E3%81%8D3%E3%81%A4%E3%81%AE%E7%90%86%E7%94%B1%EF%BD%9CMicrosoft%E3%82%82%E4%BD%BF%E7%94%A8%E3%82%92%E6%8E%A8%E5%A5%A8))がありますが、
C++ではautoは基本的に推奨されないケース([コーディング規約 - Unreal Engine 4 Documentation](https://docs.unrealengine.com/4.27/ja/ProductionPipelines/DevelopmentSetup/CodingStandard/#:~:text=%E3%81%B9%E3%81%8D%E3%81%A7%E3%81%99%E3%80%82-,%27auto%27%20%E3%82%AD%E3%83%BC%E3%83%AF%E3%83%BC%E3%83%89,-%E4%BB%A5%E4%B8%8B%E3%81%AE%E4%BE%8B%E5%A4%96))を多く見かけます。

これには様々な背景が考えられますが、一つの大きな理由は
・autoでは単純な型なのか、参照なのかを右辺だけで決めることができない
というのがありそうです。

C#では変数宣言時、右辺を見て型が分からないことはあまりないですが、
C++ではよくあります。
~~~csharp:C#
int num = 10;
var num2 = num;//この時、num2は必ずint
~~~
~~~cpp:C++
int num = 10;
auto num2 = num;//この時、num2は[int]?それとも[int&]?
~~~
言われてみれば当たり前ですが、当時はしばらく悩んでいた記憶があります。

# 2.「宣言」と「定義」
プログラミングでは「変数を宣言」したり「変数を定義」したり等、「宣言」と「定義」という言葉が出てきます。

**落とし穴：**
C#では宣言と定義はほとんど同時になされるので、あまり区別して考える必要がありませんが、
C++では宣言と定義は明確に別のものです。
~~~cpp
//関数宣言(通常、.hに記述される。)
void Func();
 
//関数定義(通常、.cppに記述される。)
void Func() {}
 
//C++では関数宣言は何度行ってもOK
void Func();
 
//2回以上の関数定義はコンパイルエラー(単一定義原則)
void Func() {}
~~~
宣言を何度も行っていいことが、
ヘッダファイルをインクルードして、各所に宣言が記述されている状態になっても問題が起こらないことと関係しています。

# 3. usingとinclude
C#では異なる名前空間のクラスを利用する時にはusingというキーワードで名前空間を指定します。
C++ではそれに代わり、includeというキーワードを使用して他のクラスの機能を利用可能にします。

**落とし穴：**
includeは他のクラスを利用するためだけに存在するキーワードではありません。
指定したファイルの内容をその場に展開するものです。これを理解していないと、クラス間の相互参照時に単純にヘッダファイルをインクルードした場合に起こる問題が理解できません。


# 4. C#のstructとC++のstructは全くの別物
C#ではclassとstructは明確に区別され、代入演算子など各所で挙動が異なりますが、
C++ではclassとstructはデフォルトのアクセス指定子(public/private)が異なること以外、区別はありません。

これはどちらかというと、C++からC#に乗り移るときに特に引っかかる落とし穴かもしれませんね。
# 5. ガベージコレクションの挙動
C#では言語の機能としてガベージコレクションが搭載されています。

C++には言語の機能としてのガベージコレクションはありませんが、
UE4の機能でC++を使用していてもガベージコレクションを使うことができます。

但し、その記述方法はC#とも、通常のC++とも異なりますので、注意して実装する必要があります。
具体的には以下の記事が詳しく解説しています。

[[UE4] GC(ガベージコレクション)の基本](https://qiita.com/madcanyon1219/items/aa3781898440e097e773)

# 6. イベント駆動開発の手法
C#では、eventを使用して非同期処理を実装していきます。

C++にもstc::functionをはじめとした関数オブジェクトを取り扱う方法が用意されていますが、
UE4では、デリゲートを作成できるマクロが実装されています。

UE4で開発するのであれば、こちらを使ったほうが便利です。

[デリゲート | Unreal Engine ドキュメント](https://docs.unrealengine.com/4.27/ja/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/Delegates/)

# 番外編：static変数
UnityC#とは関係ありませんが、個人的にハマった落とし穴に、UE4C++のstatic変数の挙動があります。

UE4C++では、static変数はPIE(Play in Editor)するたびに初期化されるものではなく、前回の状態を引き継ぎます。
ですので、PIE時には初期化されないという前提でstatic変数を取り扱うようにしましょう。

# おわりに
UE4のC++は、生のC++といろいろな点で異なり、使いやすくなっている反面、使いこなすためには様々な知識を得ておく必要があります。
ドキュメントやエンジンのソースなどを見つつ、慣れ親しんでいきましょう！