SerializeFieldで定義したprivateフィールドはIL2CPPでコンパイル後はpublicに変換される

## 前提
Unityで外部からオブジェクトの参照を入れる場合、`public`フィールド or `[SeiralizeField]private` で
Inspectorから設定することが多いかと思います。
果たして、これらで定義したものは一体どこからどうやってインスタンスを注入されるのか？
というのを気になって検証してたところ、掲題の件を見つけたのでメモ

## その前に
`public`フィールド or `[SeiralizeField]private` でインスタンス化のコストは変わるんだろうか？と
少しだけ検証コードを書いて試してみました。
結果は、**変わりません**
検証用コード載せようと思いましたが、大したことないコードなので省略。
単純に、Inspectorからオブジェクトを設定するフィールドを5個ぐらい用意して多数のオブジェクトを生成して、
生成時間を比較してみただけです。10000個ぐらい生成してみて多少の違いはありましたが、誤差の範囲程度でした。

## IL2CPPで生成されたコード
```c
// SerializeFieldTest
struct  SerializeFieldTest_t3057108995  : public MonoBehaviour_t3962482529
{
public:
	// UnityEngine.GameObject SerializeFieldTest::obj1
	GameObject_t1113636619 * ___obj1_4;
	// UnityEngine.GameObject SerializeFieldTest::obj2
	GameObject_t1113636619 * ___obj2_5;
	// UnityEngine.GameObject SerializeFieldTest::obj3
	GameObject_t1113636619 * ___obj3_6;
	// UnityEngine.GameObject SerializeFieldTest::obj4
	GameObject_t1113636619 * ___obj4_7;
	// UnityEngine.GameObject SerializeFieldTest::obj5
	GameObject_t1113636619 * ___obj5_8;

public:
	inline static int32_t get_offset_of_obj1_4() { return static_cast<int32_t>(offsetof(SerializeFieldTest_t3057108995, ___obj1_4)); }
	inline GameObject_t1113636619 * get_obj1_4() const { return ___obj1_4; }
	inline GameObject_t1113636619 ** get_address_of_obj1_4() { return &___obj1_4; }
	inline void set_obj1_4(GameObject_t1113636619 * value)
	{
		___obj1_4 = value;
		Il2CppCodeGenWriteBarrier((&___obj1_4), value);
	}
```

こんな感じになります。ちなみに、publicで宣言した場合も同じコードとなります。

## これらにどこでインスタンスを注入しているのか
更にコードを追っていくと、StartをC++のコードに変換したコードを見つけました。

```cpp
extern "C" IL2CPP_METHOD_ATTR void SerializeFieldTest_Start_m226281896 (SerializeFieldTest_t3057108995 * __this, const RuntimeMethod* method)
{
	static bool s_Il2CppMethodInitialized;
	if (!s_Il2CppMethodInitialized)
	{
		il2cpp_codegen_initialize_method (SerializeFieldTest_Start_m226281896_MetadataUsageId);
		s_Il2CppMethodInitialized = true;
	}
	{
		ObjectU5BU5D_t2843939325* L_0 = (ObjectU5BU5D_t2843939325*)SZArrayNew(ObjectU5BU5D_t2843939325_il2cpp_TypeInfo_var, (uint32_t)5);
		ObjectU5BU5D_t2843939325* L_1 = L_0;
		GameObject_t1113636619 * L_2 = __this->get_obj1_4();
		NullCheck(L_2);
		String_t* L_3 = VirtFuncInvoker0< String_t* >::Invoke(3 /* System.String System.Object::ToString() */, L_2);
		NullCheck(L_1);
```
`il2cpp_codegen_initialize_method ` 内でmetaデータをもとにインスタンスを設定しているっぽい？
`SerializeFieldTest_Start_m226281896_MetadataUsageId` はただのint型のIDです。

```
ObjectU5BU5D_t2843939325* L_0 = (ObjectU5BU5D_t2843939325*)SZArrayNew(ObjectU5BU5D_t2843939325_il2cpp_TypeInfo_var, (uint32_t)5);
```
これは、フィールド分確保されたメモリの先頭を渡しているようにも思えます。
`(uint32_t)5` も今回実装したクラスのフィールド数に一致します。



## さらに追う
```
inline void il2cpp_codegen_initialize_method(uint32_t index)
{
    il2cpp::vm::MetadataCache::InitializeMethodMetadata(index);
}
```
こうなっています。どうやら、Unityの `meta` データをキャッシュしているクラスがあるようで、
そこでインスタンスを設定しているようです。
ただ、iOS用のIL2CPPのコードで追えるのはここまででした。
MetaDataChacheのソースコード自体は含まれていないので、外部ライブラリとして隠蔽されているようです。

## 今回はここまで
今回はいろいろあり力尽きたのでここまで。これらを一通り調査したあと、以下の資料を見つけました。
[スマホゲームセキュリティ IL2CPPは本当に安全なの？](https://www.nevermoe.com/wp-content/uploads/2016/11/avtokyo_jp_re.pdf)

どうやら、Unityが生成するmetaデータをまとめてそこから、必要なインスタンスを設定しているようです。
時間が出来たらもうちょい深掘りしてみます。