14 ポイント 投稿者 GN⁺ 2025-12-30 | 13件のコメント | WhatsAppで共有
  • Unityが使用するMonoランタイムは、最新の.NETと比べて実行速度が著しく遅く、同じC#コードでも最大15倍まで差が出る事例がある
  • 実際のゲームコードで、MonoベースのUnity実行は100秒、同一コードの.NET実行は38秒と計測されており、デバッグやテストの効率にも大きく影響する
  • ReleaseモードでもMonoは30秒、.NETは12秒で、最適化された環境でも2.5倍以上の性能差が維持される
  • 原因はMonoの非効率なJITコンパイルとインライン化の失敗、過剰なメモリコピーなどで、.NETの最新CoreCLR JIT最適化と対照的である
  • UnityがCoreCLRベースの.NETモダナイゼーションを完了すれば、ゲームとエディタの両方で大きな性能向上が可能となり、これはすべてのUnityプロジェクトにおける隠れた性能税の解消につながる見込み

UnityがMonoを使う背景

  • Unityは2006年からMonoフレームワークを使ってC#コードを実行している
    • 当時のMonoは唯一のマルチプラットフォーム.NET実装であり、オープンソースだったためUnityが改変可能だった
  • 2014年以降、Microsoftは**.NET Coreをオープンソース化し、2016年に.NET Core 1.0**をリリース
    • 以後、Roslynコンパイラ新しいJIT性能改善など、.NETエコシステムは急速に発展した
  • 2018年、UnityのエンジニアはCoreCLR移植作業を進めていると明かし、Mono比で2〜10倍の性能向上を期待していた
  • しかし2025年末の時点でも、CoreCLRベースのゲーム実行は不可能な状態にある

Monoと.NETの性能格差

  • UnityプロジェクトのシミュレーションコードをUnity外部で.NETとして実行し、直接比較
    • Unity/Mono環境: 100秒、.NET環境: 38秒(Debugモード基準)
  • ReleaseモードではMono 30秒、.NET 12秒で差が維持される
    • .NETは4K×4Kマップを3秒以内に生成するなど、マルチスレッド最適化に優れる
  • Monoの非効率なコード生成が主因で、単純なループでも15倍の速度差が発生する

アセンブリ比較: Mono vs .NET

  • 同じテストコードから生成されたx64アセンブリを比較した結果
    • .NET JITはループ不変式をループ外へ移動(hoisting)し、最小限のレジスタ演算だけを実行
    • Monoは数十個のmov命令でメモリコピーを繰り返し、非効率なインライン化によって性能が低下する
  • int.MaxValue反復ループの実行時間
    • .NET: 750ms、Mono: 11,500ms、Unity Editor(Debug): 67,000ms
  • Monoはループ内で不要なメモリ移動と比較演算を繰り返し実行する

CoreCLR導入の意味

  • CoreCLRは最新JITSpan<T> APISIMD最適化ハードウェア命令サポートなどの現代的な機能を提供
    • これらの機能により、さらに2倍以上の性能向上の可能性がある
  • UnityのBurstコンパイラはLLVMベースでネイティブコードを生成するが、C#機能の制限が存在する
    • CoreCLRの現代的なJITはBurstに近い性能を提供しつつ、言語上の制約が少ない
  • CoreCLRは**AOT(事前コンパイル)をサポートし、起動速度の改善JITが制限されるプラットフォーム(iOSなど)**への対応も可能
    • ただしUnityは依然としてIL2CPPを維持する方針を示している

結論: Unityに必要な.NETモダナイゼーション

  • Monoは最新.NETと比べて1.5〜3倍以上遅い実行性能を示し、これはすべてのUnityプロジェクトにおける隠れたコストとして作用する
  • CoreCLR導入時に期待される効果
    • ランタイム性能向上高速な反復ビルドGC改善ドメインリロードの削減マネージドコード比率の拡大
  • Unity 6.xのロードマップには**.NET Modernizationが含まれているが、予定は2026年以降**となっている
  • CoreCLRサポートが完成すれば、Unity開発者とプレイヤーの双方に実質的な性能革新をもたらす可能性がある
  • 現時点では、Monoの限界がUnityエコシステム全体の性能ボトルネックとして残っている

13件のコメント

 
quack337 2025-12-31

ああ……Mono はまだ legacy な .NET Framework ベースなんですね……
ゲームではなく、10万行くらいの .NET 4.8 + LINQ to SQL + WinForms の金融アプリを .NET 10 + Entity Framework に移行している途中ですが、かなり速くなったのを実感しています。10秒かかっていた計算処理が3秒に縮むことも!

 
intajon 2025-12-30

NuGet互換も追加してくれるとうれしいです(私がUnityにあまり詳しくないからでしょうか?)

 
sonohoshi 2025-12-31

公式サポートではありませんが…… NuGetForUnity というオープンソースはあります。

 
rkttu 2025-12-30

理論上は、.NET Standard 2.0 をターゲットにして作られた NuGet パッケージは Unity 環境でも読み込んで使えることにはなっている……のですが、やはり不便な点は多いように思います。

https://learn.microsoft.com/ko-kr/dotnet/…

 
sonohoshi 2025-12-30

もっともな話ではあるけれど、あえてエディタのパフォーマンスを比較する理由はいまいちよく分かりませんね……。せめてデバッグビルドでも持ってきて比較していたらどうだっただろう? いや、そうするとかえって説得力が落ちたのかな? 一方で、IL2CPP も Mono もどちらも時代遅れの技術であることには変わりない気もするけれど

 
foriequal0 2025-12-30

大規模なプロジェクトでは、エディタのパフォーマンスが開発体験を大きく損なっているため、エディタ性能にも意味があります。エディタの起動が遅く、アセットのインポートも遅く、デバッグ/テストのループも遅く…。

 
sonohoshi 2025-12-30

ああ……もちろんこれも重要ではあります。私が最初に読んだとき、記事の筆者はもう少し根本的なコード実行速度について論じたかったようにも見えました。Unity はおっしゃるとおり、エディタも遅く、インポートも遅く、全体的なテストループが遅いというのも事実ですね……

 
dunward 2026-01-05

Unityに関する記事を見ると、とてもうれしいですね。
興味深く拝読しました。

 
mhcoma 2025-12-30

うまく導入されれば、ありふれたインディーゲームの最適化はおそらく良くなるだろうと予想…

 
rkttu 2025-12-30

Mono が必ず CoreCLR によってモダン化されるべきもう一つの理由として、Unity には Mono の性能改善に投資する余力も意思もあまりないだろう、という点があると思います。.NET Framework 時代の遺産は、一日でも早く整理されるのが正しいと思います。 :-D

 
rkttu 2025-12-30

そして、.NET 10を節目として、かつてIL2CPPで解決しようとしていた問題が、別の展開方向ではあるものの、的確に扱われつつある点(Native AOT)も考慮されるとよいのではないかと思います。

もちろん、これは途中で編集可能なC++コードが生成されないという限界はありますが、結果としてJust-In-Timeが発生しないネイティブバイナリの生成は、.NET 8を皮切りに、10に至ってさらに成熟してきました。

そうした理由から、CoreCLRへのモダナイズをこれ以上先延ばしにするのは、Unityにとって良い選択にはならないだろうと思います。あるいは、まったく別の言語や基盤へ切り替えるほうが、より有効かもしれません。

 
sonohoshi 2025-12-30

> UnityはMonoのパフォーマンス改善に投資する余地も意欲もあまり高くないでしょう

これにも強く同意します...

 
GN⁺ 2025-12-30
Hacker News のコメント
  • プロのゲーム開発者として、普段は Unity 関連の議論にはあまり参加しないが、今回は自分の専門分野に直接関わる話なのでコメントする。
    記事には、Unity 開発経験があまりない人が書いたように見える部分がいくつかあった。
    1. シミュレーション層と表現層の分離は、昔からよく使われてきた性能最適化手法だった(昔は主に C++ で実装されていたが)。
    2. ほとんどのゲームは Mono バックエンドではなく IL2CPP でリリースされている。
    3. 最新の Unity では、性能のために Burst Compiler と HPC# を活用するのが一般的だ。Job System も大きく役立つ。
    4. エディタ上でのプロファイリングはほとんど意味がない。デバッグビルドよりはるかに遅いからだ。
      要するに、Unity 開発者が今回のアップデートに期待しているのは性能向上よりも 最新の言語機能へのアクセス のためだ。そして実行中の GC を最小化したり、非管理メモリ や DOTS で回避したりするのが一般的だ。
    • Unity のマーケティングに引っ張られすぎているように見える。Unity はいつも 問題の多いシステムを少しずつ改善 するやり方を取る。
      IL2CPP は .NET IL を C++ に変換する 品質の低いコードジェネレータ にすぎず、最適化コンパイラ頼みだ。
      Unity ブログの IL2CPP 内部構造を見ればわかる。
      Burst/HPC# も ECS や SoA のようなトレンドには従っているが、性能はよく書かれた C++ や CoreCLR の C# に及ばない。
      しかもこれらの技術は クローズドで Unity 専用 なので外部では使えない。Unity はいつも遅い Mono との比較ベンチマークでマーケティングしている。
      結局 Unity も CoreCLR を受け入れざるを得なくなり、そのとき既存の複雑なコードよりも 普通の C# コードの方が速いという現実 に気づくことになるだろう。
    • 筆者として意見に感謝する。私たちのゲームは Unity の型や DLL に まったく依存しない構造 なので、一般的な Unity ゲームとは異なる。
      IL2CPP を使わないのは、ランタイム DLL ロード、リフレクション、FieldOffset 構造体パッキング などと互換性がないためだ。
      モッダーが IL インジェクションで機能を拡張できるので、結果として開発速度が上がる。
      Burst と HPC# は複雑さと制約が多く、好まない。Mono と .NET の性能差のせいでなおさらもどかしい。
      エディタでのプロファイリングも、実際のビルドと似た比率で性能向上を示してくれるので有用だった。ただし Unity 標準のプロファイラは不正確なので、自作のトレースシステム を使っている。
      GC は依然として問題だ。文字列処理や UI が毎フレーム ガベージ を生成する。CoreCLR になれば、より良い API と移動型 GC によってメモリ断片化の問題を減らせるはずだ。
  • Unity は入りやすいが、モノリシックな構造 のせいで技術的負債が重い。
    Asset Store は素晴らしいが、エンジン自体は洗練されていない印象だ。
    Mono ベースのスクリプティングは CoreCLR へ移行するには構造的に複雑すぎる。
    Unity が本当に Core を改善したいなら、Blender 3.x のようにエディタ全体を再設計 しなければならない。
    今のままでは 1999 年製の UI のように感じる。
    • Unity の最大の問題は、新機能を完成させずに捨てること だ。
      数多くのプラグインやツールが「0.x-preview」の段階で止まり、5~10 年後には動かなくなるか、新しいアセットに埋もれてしまう。
      だから私は今では 1.0 以上のバージョンしか使わない。そうしないと放棄されたプラグインに依存することになり、結局また移植し直す羽目になる。
      Unity にとっても、開発者にとっても、ユーザーにとっても損だ。
    • Unity は方向性を失った会社のように見える。
      内部的に 自社ゲーム開発の失敗 があり、実際のゲーム制作感覚が不足している。
      ただ要望された機能を追加しているだけで、一貫したビジョン がない。
    • WebGPU は Vulkan のような 抽象化レイヤ だ。
      性能が重要なら Vulkan を直接呼ぶべきで、移植性 が重要なら WebGPU を使うべきだ。
      ブラウザごとに実装が違うためオーバーヘッドが生じるが、OS ドライバレベルで WebGPU が提供されれば解決できる。
    • Unity は何かをしようとすると、常に 回避策 を探さなければならない感じがある。
      一方で Godot は シンプルで意味のあるビルディングブロック を提供してくれるので、欲しいものを自由に作れる。
    • Unity は自社機能の API を頻繁に壊すので、チュートリアルさえ動かなくなる
      Asset Store も同様にバージョン互換性の問題で保守が難しく、ほとんどが 放置されたアセット になってしまう。
      Unity が有用なアセットを買収しても、統合はまともに行われず、競合アセットは消えてしまう。
      一方 Unreal Engine はこうした機能を エンジン内蔵レベル で提供している。
  • Unity の GC は Boehm GC を使っているため、.NET や Mono よりずっと遅い。
    Unity は IL2CPP により良い GC を導入する予定もない。
    CoreCLR ベースのエディタが出れば、むしろ エディタの方がビルドより速い可能性すらある
    関連する議論: Unity CoreCLR と .NET モダナイゼーション
    • GC が良くなるのは良いことだが、ゲームでは フレームごとの割り当てを 0 に保つ ことの方が重要だ。
      インクリメンタル GC がうまく動けば、スタッターの問題もそれほど大きくない。
    • CoreCLR への移行で ドメインリロードの除去 により、エディタ速度は大きく向上するはずだ。
    • Mono にはすでに 正確な GC があるのに、なぜ Boehm を使っているのか疑問だ。
  • Unity が 2018 年に CoreCLR の移植を議論していた頃から、長い道のり だった。
    C# 自体が非常に高速になっているのだから、Unity はこの移行に 全力を注ぐべき だ。
    私たちのチームは .NET Framework 4.7.2 から .NET 6 への移行に数か月かかったが、その後の LTS バージョンアップグレードは 数時間程度 で済んだ。
  • Unity にはもう CoreCLR へのマイグレーションを実行する 技術力 が不足しているように見える。
    遅延は続き、リーダーたちは去っている。
    代案として .NET 10 ベースの Stride エンジン を勧めたい。Unity のような 境界オーバーヘッド がない。
    • 進みは遅いが、Unity は実際に CoreCLR 移行を進めている
    • Stride は Unity の機能の 一部しか提供していない
      Godot はオープンソースだが C# サポートが不安定で、Web ビルドができないなら ゲームジャム向きではない
      GPU サポートのある 本物のサンドボックスソリューション が必要だ。
    • 技術力不足ではなく、リソースとリーダーシップの問題 だ。
      優先順位が変わり続け、要件も修正されるため、作業が繰り返し発生する。
      開発者たちは今でも優秀だが、一貫した推進力 が足りない。
    • Unity が買収した数多くの技術やアドオンを 廃止するか統合しなければならない負担 が大きい。
      こうした大規模なリライトは、CEO にとっても リスクの高い決断 だ。
  • Rec Room の Circuits システム を開発したが、Unity 依存を取り除いて CoreCLR でテスト可能にした経験がある。
    その結果、性能が大きく向上し、エンジン依存性の低下 によってコード保守も楽になった。
    Unity の概念を必要な箇所にだけ露出させ、テストで境界を強制することで、論理的分離の価値 を実感した。
  • なぜ筆者が IL2CPP ではなく Mono を使っているのか気になる。IL2CPP の方がはるかに速いので、Mono ビルドは時代遅れ だ。性能を重視するなら IL2CPP が最初の一歩であるべきだ。
  • 私の夢は .NET SDK を Android スマホに直接インストール してネイティブ実行することだ。
    ルート権限があり、WireGuard や Tailscale のようなネットワークツールと組み合わせれば、携帯型サーバー としても完璧だ。
    .NET 10 の新しい GC でゲームのスタッターもほとんど消えるはずだ。
    今はメイン PC から Sunlight + Moonlight でゲームをストリーミングして、スマホで遊んでいる。
    高リフレッシュレートの OLED 画面のおかげで、バッテリー消費も少ない。
    • ルート制限は セキュリティ上の理由 だ。公共の場の USB ポート経由の感染を防ぐため、ルート化を難しくしている。
    • MAUI(Xamarin) でも似たことはできる。
      .NET SDK そのものではないが、Mono ランタイムがアプリに同梱 されているので、体感としては近い。
  • Unity がなぜいまだに .NET へ完全移行しないのか不思議だ。
    Mono の クロスプラットフォーム上の利点はすでに失われている のに、なぜ IL2CPP のような複雑なハックを維持しているのか理解できない。
    • 埋没コストの罠 が大きい。すでに Mono、IL2CPP、Burst などに莫大な投資をしてきたため、方向転換が難しい。
    • Unity は Mono を 大幅にカスタマイズ しているので、単純に置き換えることはできない。
      長年にわたる 非標準の修正 が積み重なっていて、大企業でなければ新たに最適化するのも難しい。
  • Unity が 2018 年から CoreCLR への移行を始めたのに、いまだに完了していないのは驚きだ。
    この規模のプロジェクトなら 1~2 年で十分だったはず だと思う。