Godotがコンポーネントシステム(ECS)を採用しない理由

Godotがコンポーネントシステムを採用しない理由

ECS(Entity-Component-System)とは

エンティティ コンポーネント システム( ECS )は、主にビデオ ゲーム開発でゲーム ワールド オブジェクトの表現に使用されるソフトウェア アーキテクチャパターンです。ECS は、データのコンポーネントから構成されるエンティティと、エンティティのコンポーネントで動作する システムで構成されます。

ECS は、継承よりも構成の原則に従います。つまり、すべてのエンティティは型階層ではなく、それに関連付けられたコンポーネントによって定義されます。システムは、必要なコンポーネントを持つすべてのエンティティに対してグローバルに機能します。

この概念の理論的な有用性が何であれ、Entity Component System フレームワークが特にゲーム プログラミングで広く使用されていることから、その実用的な有用性は議論の余地のないものになっています。

Entity component system – Wikipedia

ECS(Entity-Component-System)は、ゲームエンジンのアーキテクチャの一つで、ゲームオブジェクトを実装する方法の一つです。以下にECSのメリットとデメリットを示します。

メリット:

1. スケーラビリティ:ECSは非常にスケーラブルで、大規模で複雑なシステムでも高速に動作します。ゲームエンジンの処理がパフォーマンスボトルネックになることが少ないため、大規模なゲームを開発する場合には有利です。

2. コードの再利用:ECSは、コンポーネントを再利用しやすいため、開発時間を短縮できます。同じコンポーネントを異なるエンティティに適用することができ、コードの共有が可能です。

3. メモリ効率:ECSは、コンポーネントが独立しているため、メモリ使用量を最適化できます。同じコンポーネントを持つエンティティをグループ化することで、キャッシュの効率も高くなります。

4. シンプルなデバッグ:ECSは、デバッグが比較的容易であるため、開発者が問題を見つけて修正するのが簡単です。各コンポーネントが個別に存在するため、問題がある場合には、特定のコンポーネントに焦点を当ててデバッグできます。

デメリット:

1. 学習コスト:ECSは、従来のオブジェクト指向プログラミングとは異なる考え方を必要とするため、学習コストが高いと感じる開発者もいます。

2. 一貫性の欠如:ECSは、慣れていない開発者が実装すると、コンポーネントとエンティティの関係性が曖昧になり、一貫性が欠如する場合があります。

3. 複雑性の増大:ECSは、一部の場合では、コンポーネントの状態やエンティティ間の相互作用など、プログラマが管理する必要がある複雑な問題があるため、実装が複雑になる場合があります。

4. 設計の制限:ECSは、従来のオブジェクト指向プログラミングに比べて柔軟性が低いため、一部の場合では、特定のシナリオに合わないことがあります。例えば、ECSは、UIやGUIなどの特定のシナリオには適していない場合があります。

5. コンポーネントの依存関係の問題:ECSは、コンポーネントが独立しているため、コンポーネント間の依存関係が重要な場合に問題が発生する可能性があります。特定のコンポーネントが他のコンポーネントを必要とする場合、そのコンポーネントをインスタンス化する順序が重要になります。

6. エンティティの管理の問題:ECSは、オブジェクト指向プログラミングのような継承ベースのアーキテクチャとは異なり、エンティティに属するコンポーネントを直接管理する必要があります。これにより、エンティティの管理が複雑になる可能性があります。

ECSは、一般的に大規模なゲームエンジンで使用されます。ただし、ECSの設計と実装は、開発者が特定のシナリオに適合するように選択する必要があります。

Godot が ECS ベースのゲーム エンジンではないのはなぜですか?

なぜ Godot がECSを利用しないのかという話題が頻繁に出てくるので、この記事では、その背後にある設計上の決定を説明し、Godot がどのように機能するかを明らかにします。

注: 誤解を避けるために、この記事は、継承対合成や炎上戦争を引き起こすための反 ECS 記事ではないことを強調するために、記事を変更しました。ゴドーが現在のアーキテクチャを採用した理由を説明しているだけです。

(※以前は反ECS的な書き方だったが後日修正された)

物事を行うための普遍的に優れた方法があるとは思わないので、より適切に機能する他のアプローチまたはアーキテクチャを使用することを好む場合は、それは素晴らしいことです。あるアプローチが他のアプローチよりも優れているかどうかを理解するのではなく、ゴドーのアーキテクチャの背後にある理由を理解することに興味がある場合は、これを読んでください。

ECSとは?

ECSは、ビデオ ゲームで一般的に使用されるデザイン パターンです (ただし、他のソフトウェア業界ではあまり使用されません)。これは、ベース エンティティ(コンテナー オブジェクト) とそれに追加できるコンポーネントで構成されます。コンポーネントは、データと、全世界と対話する手段を提供します。最後に、システムは独立して動作し、すべての同様のコンポーネントに対してアクションを実行します。

この設計は、2010 年代初頭にゲーム エンジンとライブラリで一般的になりました。(アーキテクチャ以外の) 主な魅力は、コンポーネント データを連続したメモリに配置できるため、キャッシュ アクセスが向上することです。これは、データ指向の最適化の一般的な形式です

アーキテクチャ的には、ECS は、 OOPインターフェイスまたは多重継承が機能するのと同様に、構成を優先することにより、継承を置き換えることを目指していますECS の主な利点は、コンポーネントが動的であることです(実行時に追加または削除できます)。

Godot が ECS を使用しないのはなぜですか?

Godot は、データロジックの両方を含むノードを提供することで、より伝統的な OOP を使用しますまた、継承を多用します構成は引き続き行いますが、より高いレベルで行われます (構成するノードは通常、従来の ECS のコンポーネントよりも高いレベルです)。

違いの例として、典型的な ECS では、Button エンティティは次のようなコンポーネントを持つことができます。

  • 変身

  • レンダラー

  • EventHandler

  • ボタン

  • 行動

より簡単にして問題を回避するために、一部の実装では、他のコンポーネントが追加されたときに一部のコンポーネントが存在するように強制します。

Godot では、Button は完全な継承チェーンを暗黙的に持っています。

Node -> CanvasItem -> Control -> Button -> Behavior Script

より複雑な例として、スプライトがアタッチされた剛体が挙げられます。典型的な ECS では、これは以下を含むエンティティとして検出されます。

  • 変身

  • リジッドボディ

  • コライダー

  • スプライト

ただし、ゴドーでは、これはより複雑です。3 つのノードと階層が必要です。

  • RigidBody (Node -> Node2D -> PhysicsBody2D -> RigidBody2D)

    • Sprite (Node -> Node2D -> Sprite)

    • CollisionShape (Node -> Node2D -> CollisionShape)

では、最初はゴドーのアプローチの方が無駄が多いように見えますが、そうでしょうか。

  • ノードは軽量で、コンポーネントに似ています。

  • Node2D には、ECS の Transform コンポーネントに似た 2D 変換が含まれています。3 つのノードが必要ですが、ECS では 1 つのコンポーネントで十分です。これは無駄に思えますが、本当ですか?エンティティでは、コライダーとスプライトは中心に配置されずに使用される可能性が高く、オフセットと回転のプロパティが必要になるため、最終的にはあまり変更されません。

  • Godot では、これら (複数のスプライトとコライダー) をさらに追加することは一種の自由であり、変換オフセットは自動的に行われます。ECS では、これを処理するために特別なロジックが存在する必要があります。

ご覧のとおり、継承と構成は共存でき、ゴドーの文脈では意味があります。

主な違いは次のように要約できます。

ゴドーは、従来の ECS よりも高いレベルで作曲を行います。

これには、アーキテクチャとパフォーマンスの両方で 2 つの基本的な違いがあります。

建築

アーキテクチャに関しては、これにより ECS の動作が大幅に変更されます。

継承はより明示的です

継承が優先されるため (ECS のコンポーネント間の暗黙的な関係のために)、これらの関係は継承チェーンで明示的になりました。

これにより、(Godot ユーザーにとって) シーン ノードがどのように構成され、何ができるかを、継承ツリーを見るだけで非常に簡単に理解できるようになります。

シーンはより露骨です

構成はより高いレベル (ノード) で行われるため、Godot ユーザーはシーン ツリーを見るだけでシーンが実際に何をするかを簡単に理解できます。

再利用性が向上

すべてがノードである (コンポーネントを持つエンティティではない) おかげで、再利用が容易になり、可能な限りすべてを組み合わせることができます。これが、Godot がプレハブとシーンの概念や区別を持たない理由です。

さらに、より高いレベルのノードを持つことで、Godot には「シーン設定」の概念がありません。これらもノードで行われるからです。

その結果、従来の ECS アプローチよりもはるかに優れた構成能力が得られます。通常は次のとおりです。

Components -> Entity -> Prefab -> Scene -> World

ゴドーにはノードがあり、シーンは単にツリーを形成するノードの集まりであり、ファイルに保存されます。シーンは、他のほとんどのツールよりも高い柔軟性でインスタンス化および継承できます。

最適化

コンポーネントは別として、Godot はデータとシステムを区別せず、より伝統的な OOP の方法ですべてをバンドルすることを選択しました。ノードには独自のロジックが含まれています。

アーキテクチャの好みは別として、これは最適化側の問題のように思えるかもしれません。ECS の最大の利点の 1 つは、システム (データ指向) 部分です。これにより、線形メモリに編成された多くの同様のコンポーネントのデータを実行できます。これにより、Godot がノードを操作する方法に比べてパフォーマンスが大幅に向上します。

ここでも重要な点は、Godot のシーンとノードが従来の ECS 実装よりも高いレベルで動作することを理解することです。

これは、エンジンとゲーム ロジックの部分を別々に調べることで理解できます。

エンジン

Godot は、物理、レンダリング、オーディオなどにデータ指向の最適化を多数使用しています。ただし、それらは別個のシステムであり、完全に分離されています。

ECS を利用するほとんどの (すべてではないにしても) テクノロジーは、基本アーキテクチャとして機能し、その上に他のすべて (物理、レンダリング、オーディオなど) を構築することによって、コア エンジン レベルでそれを行います。

代わりに、これらのサブシステムはすべて分離され、分離されています (そしてServersの内部に収まります)。これにより、コードがよりシンプルになり、保守と最適化が容易になることがわかりました (これは、Godot のコードベースが他のゲーム エンジンと比較して非常に小さいことを示していますが、同様のレベルの機能を提供しています)。

Godot (ノード) のシーン システムは、従来の ECS システムと比較すると、一般的に非常に高レベルです。発生することのほとんどは、シグナル コールバックを介して発生します(オブジェクトが衝突した、何かを再描画する必要がある、ボタンが押されたなど)。ユーザー側から Godot のフレームごとに何かを処理する必要がある状況は非常にまれです。これは、エンジンがこれを内部で管理し、複雑さをユーザーから取り除くためです。

簡単に言うと、ノードはサーバー内で処理される実際のデータへのインターフェイスにすぎませんが、ECS では実際のエンティティはシステムによって処理されるものです。

つまり、エンジンとしての Godot は、ユーザーから処理の負担を取り除こうとし、代わりに、イベントが発生した場合に何をすべきかを決定することに重点を置いています。これにより、多くのゲーム コードを記述するためにユーザーが最適化する必要が少なくなり、Godot が伝えようとしている使いやすいゲーム エンジンを構成するビジョンの一部となっています。

ゲームロジック

それでも (圧倒的多数ではありませんが)、一部の種類のゲームでは、ゲーム ロジック側で ECS を使用するとパフォーマンスが向上します

これらは一般に、数十万のオブジェクトでゲーム ロジックを処理する必要があるゲームであり、CPU キャッシュに移動するページの量が数桁増加し、パフォーマンス (およびバッテリーの使用量) に深刻な影響を与えるため、データ指向の最適化が必須になります。モバイルデバイス)。

繰り返しになりますが、このユースケースはまれですが (対照的に、ほとんどのゲームは通常、せいぜい数百のオブジェクトであり、キャッシュの最適化を行わなくてもメモリ アクセス頻度は十分に高いものです)。キャッシュの最適化を必要とするものは実際にあり、存在します。

これらのタイプのゲームの例は次のとおりです。

  • 都市建設業者 (多くのことが進行中)。

  • サンドボックス (フレームごとに処理が必要な小さなものがたくさんあります)。

  • 一部のストラテジー ゲーム (大部分ではありませんが、同時に数千または数十万のゲーム ユニットを使用できるゲームもあります)。

  • 他にもAAAのゲームが盛りだくさん。

では、これらのタイプのゲームは Godot では作成できないということですか?

答えは、やりたいことは何でもできますが、別の方法で行う必要があるということです。

巧妙な最適化を行う

ブルート パフォーマンスに正面から取り組む前に、多くの場合、巧妙な最適化に頼ることができます。SimCity が Commodore 64 でどのように動作するのか疑問に思ったことはありませんか? フレームごとにどのタイルを処理するかを交互に変更することでこれを行ったため、同時に何千ものタイルを処理する必要はありませんでした (6502 CPU では不可能です)。

最適化は、すべてのフレームのすべてを処理しないものから、目に見えるもの (またはカメラの近く) を処理することを優先するものまでさまざまです。多くの場合、これらの最適化により、処理が必要なオブジェクトの量が桁違いに削減されますが、完全なデータ指向に移行するよりも優れたパフォーマンスが得られます。

Godot はこれを支援するようなノードを提供しておりVisibilityEnabler、今後の Godot 4.0 では、シーン ツリーのセクションを無効にすることをより細かく制御できます。

それでも、これはゲームにとって十分ではないか、面倒すぎるかもしれません. この場合、単にシーンをスキップする必要があるかもしれません:

サーバーを直接使用する

前述のように、Godot はエンジンの高性能/低レベル部分のほとんどをServersに配置します。サーバーへの API は で完全に公開されており、エンジン全体を非常に低いレベルで制御できます。

ほとんどの場合、GDNative (またはモジュール) を介して GDScript、C#、または C++ のサーバーを使用しても、上記のタイプのゲームには十分です。コア ゲーム ループには高パフォーマンスのコードが必要になる場合がありますが、ロジックが複雑すぎて本格的なフレームワークが必要になることはめったにありません。

これは、SDL/OpenGL で自分でゲームを作成するのと似ていますが、エンジンの残りの部分は、特殊なゲーム コードではない他のすべて (UI、IO、保存、ネットワークなど) に引き続き使用できます。つまり、残りのゲームの 90%)。

コンピューティングの使用

コンピューティング (GPGPU) は現在、ほぼ普遍的 (デスクトップとモバイルでサポート) であり、非常に高い柔軟性とパフォーマンスの最適化を可能にします。Godot 4.0 には、高度な並列タスクに対する使いやすい Compute サポートが含まれます。

ECS の使用

Godot で ECS ソリューションを使用することを妨げるものは何もありません。実際、Godexに関する Andrea Catania の素晴らしい作品を確認することを強くお勧めします。Godex は、高性能 ECS プラガブル実装を実現することを目的としています。

未来

Godot の将来のバージョンでは、ECS がシステムと同様の方法でデータとロジックを分離しながら、Godot の動作方法に適応させて、同様のノードを処理するためのキャッシュ フレンドリーな方法を (オプションで実際に必要な場合に備えて) 評価しています。結局のところ、これらのタイプの最適化は ECS だけのものではありません。

まとめ

一度に複数の問題を解決することを目的とするアーキテクチャと設計パターンはプログラマーにとって非常に魅力的ですが、Godot は非常に実用的なアプローチで開発されています。

ECS が利点をもたらすことは事実ですが、Godot の目標に対する利点を客観的に証明できるケースは非常に限られているため、(少なくとも私たちにとって) アーキテクチャの変更を正当化することは非常に困難です。例外であり、一般的なルールではありません (また、多くの場合、最適化は他のより単純な手段で達成できます)。

Godot は何よりもユーザー フレンドリーでスケーラブルであることの道を選びました。ほとんどの場合、エンジンの設計方法により、極端なゲーム ロジックのパフォーマンスが必要になるケースははるかに少ないことを理解しています (エンジンが処理するため)。力仕事のほとんど)。それでも、この必要が生じた場合、Godot はその面で答えを提供するように設計されており、時間の経過とともにより多くのオプションが提供され続けます.

Next Post

エンバークスタジオと開発中のRust製ゲームエンジン

日 3月 5 , 2023
エンバークスタジオとRustとプロシージャル