エンティティコンポーネントシステムアーキテクチャは、定義上オブジェクト指向ですか?


20

エンティティコンポーネントシステムアーキテクチャは、定義上、オブジェクト指向ですか?それは私にとってより手続き的または機能的だと思われます。私の意見では、オブジェクト指向言語で実装することを妨げるものではありませんが、堅実なオブジェクト指向の方法で実装することは慣用的ではありません。

ECSはデータ(E&C)を動作(S)から分離しているようです。証拠として

アイデアは、エンティティにゲームメソッドを埋め込まないことです。

そして

コンポーネントは、特定の目的に必要な最小限のデータセットで構成されます。

システムは、特定のコンポーネントを持つエンティティのセットを使用する単一目的の機能です


これはオブジェクト指向ではないと思います。オブジェクト指向になることの大部分は、データと振る舞いを組み合わせることだからです。 証拠として

対照的に、オブジェクト指向のアプローチは、プログラムの残りの部分から直接アクセスできない場所にデータを配置することをプログラマに促します。代わりに、データにバンドルされている一般にメソッドと呼ばれる特別に記述された関数を呼び出すことにより、データにアクセスします。

一方、ECSは、行動からデータを分離することのすべてのようです。

回答:


21

前書き


エンティティコンポーネントシステムは、オブジェクト指向のアーキテクチャ手法です。

オブジェクト指向プログラミングと同じように、この用語の意味についての普遍的な合意はありません。ただし、エンティティコンポーネントシステムは、継承のアーキテクチャ上の代替として特に意図されていることは明らかです。継承階層はオブジェクト何であるかを表現するのに自然ですが、特定の種類のソフトウェア(ゲームなど)では、オブジェクト何をするかをむしろ表現ます。

これは、C ++またはJavaでの作業に慣れている可能性が高い「クラスと継承」とは異なるオブジェクトモデルです。エンティティは、JavaScriptやSelfのプロトタイプのように、クラスと同じくらい表現力があります。これらのシステムはすべて相互に実装できます。

 


言おうPlayerとするエンティティであるPositionVelocityKeyboardControlled明らかに物事を行うコンポーネントを、。

entity Player:
  Position
  Velocity
  KeyboardControlled

私たちは知っているPositionの影響を受けなければなりませんVelocity、とVelocityによりますKeyboardControlled。問題は、これらの効果をどのようにモデル化するかです。

 

エンティティ、コンポーネント、およびシステム


コンポーネントが相互に参照していないと仮定します。外部PhysicsシステムはすべてのVelocityコンポーネントを走査しPosition、対応するエンティティのを更新します。Inputこのシステムは、すべての横断KeyboardControlledコンポーネントとアップデートVelocity

          Player
         +--------------------+
         | Position           | \
         |                    |  Physics
       / | Velocity           | /
  Input  |                    |
       \ | KeyboardControlled |
         +--------------------+

これは基準を満たします:

  • エンティティはゲーム/ビジネスロジックを表現しません。

  • コンポーネントには、動作を説明するデータが格納されます。

システムは現在のイベントを処理し、責任ある制定コンポーネントによって記述行動を。また、衝突などのエンティティ間の相互作用の処理も担当します。

 

エンティティとコンポーネント


しかし、コンポーネントがあるとしませんお互いへの参照を持っています。エンティティは、いくつかのコンポーネントを作成し、それらを一緒にバインドし、それらのライフタイムを管理する単なるコンストラクタです。

class Player:
  construct():
    this.p = Position()
    this.v = Velocity(this.p)
    this.c = KeyboardControlled(this.v)

エンティティは、入力および更新イベントをそのコンポーネントに直接ディスパッチする可能性があります。Velocity更新にKeyboardControlled応答し、入力に応答します。これはまだ基準を満たしています:

  • エンティティは、イベントのみをコンポーネントに転送する「ダム」コンテナです。

  • 各コンポーネントは、独自の動作を実行します。

ここで、コンポーネントの相互作用は明示的であり、システムによって外部から課されるものではありません。動作を説明するデータ(速度の量は?)と、それを実行するコード(速度は?)は結合されていますが、自然な形です。データは、動作に対するパラメータとして表示できます。また、一部のコンポーネントはまったく動作しません。a は場所Positionいるという動作です。

相互作用は、エンティティのレベル(「… Playerと衝突する場合Enemy」)または個々のコンポーネントのレベル(「… Lifeとエンティティが衝突する場合Strength」)で処理できます。

 

構成部品


エンティティが存在する理由は何ですか?単なるコンストラクターである場合は、コンポーネントのセットを返す関数に置き換えることができます。後でタイプでエンティティをクエリしたい場合は、それを可能にするTagコンポーネントを用意することもできます。

function Player():
  t = Tag("Player")
  p = Position()
  v = Velocity(p)
  c = KeyboardControlled(v)
  return {t, p, v, c}
  • エンティティはできる限り愚かです。コンポーネントは単なるセットです。

  • コンポーネントは、以前と同様にイベントに直接応答します。

エンティティタイプからイベントを完全に分離し、抽象クエリによって相互作用を処理する必要があります。クエリするエンティティタイプはこれ以上ありませんTag。デバッグには、ゲームロジックよりも任意のデータを使用する方がおそらく良いでしょう。

 

結論


エンティティは、関数、ルール、アクター、またはデータフローコンビネーターではありません。それらは、具体的な現象をモデル化する名詞です。つまり、オブジェクトです。Wikipediaが言うように、エンティティーコンポーネントシステムは、一般的なオブジェクトをモデリングするためのソフトウェアアーキテクチャパターンです。


2
クラスベースのオブジェクト指向、プロトタイプベースのオブジェクト指向に代わる主な代替手段も、データと動作を結び付けているようです。実際、クラスベースのオブジェクト指向と同様に、ECSとは異なるようです。では、OOの意味を詳しく説明していただけますか?

@delnanの質問に追加するために、私が引用したOOウィキペディアの記事の抜粋に同意しませんか?
ダニエルカプラン

@tieTYT:ウィキペディアの引用はカプセル化と情報隠蔽について話している。データと動作の結合が必要であることの証拠ではないと思いますが、それが一般的であるということだけです。
ジョンパーディ

@delnan:オブジェクト指向では何の意味もありません。私にとってオブジェクト指向プログラミングとは、まさに、オブジェクトの特定の定義が実装定義である「オブジェクト」(関数、ルール、アクター、データフローコンビネーターなどとは対照的な)を使ったプログラミングです。
ジョンパーディ

1
@tieTYT:Wikipediaの記述と矛盾することはなく、確かに広い用語であることを伝えるために、野生で見た実装を説明していました。
ジョンパーディ

20

いや そして、そうでなければ投票した人の数に驚いた!

パラダイム

それはだデータ指向別名データドリブン私たちが話しているので、アーキテクチャはなく、言語それがで書かれています。アーキテクチャは、プログラミングスタイルやの実現ですパラダイム通常unadvisably与えられた言語で回避することができ、。


機能的?

あなたの比較機能 / 手続きプログラミングは適切かつ有意義な比較です。ただし、「関数型」言語は「手続き型」パラダイムとは異なることに注意してください。そして、Haskellのような関数型言語でECSを実装できます。


凝集が起こる場所

あなたの観察は関連性があり、スポットオンです:

「... [ECS]はオブジェクト指向言語での実装を妨げるものではありませんが、堅実なオブジェクト指向の方法で実装することは慣用的ではありません」


ECS / ESはEC / CEではありません

コンポーネントベースのアーキテクチャ「Entity-Component」と「Entity-Component-System」には違いがあります。これは進化するデザインパターンであるため、これらの定義は同じ意味で使用されています。「EC」または「CE」または「Entity-Component」アーキテクチャコンポーネントに動作を設定しますが、「ES」または「ECS」アーキテクチャはシステムに動作を設定します。以下にECSの記事をいくつか紹介します。どちらも誤解を招く命名法を使用していますが、一般的な考え方を理解してください。

2015年にこれらの用語を理解しようとしている場合、「エンティティコンポーネントシステム」への参照が「エンティティコンポーネントアーキテクチャ」を意味していないことを確認してください。


1
これは正解です。ECSはOOPパラダイムにはあまり適していません。ECSはデータと動作を分離することに関するものであり、OOPはその逆です。
ナックス 'vi-vim-nvim'

「OOPは反対です」OOPが何であるかについての定義は、SmallTalkのように実際に使用されることのない役に立たないアカデミックな定義がない限り受け入れられません。
ジャンマイケルセレリア

10

エンティティコンポーネントシステム(ECS)は、システムの定義方法に応じて、OOPまたは機能的な方法でプログラムできます。

OOPの方法:

エンティティがさまざまなコンポーネントで構成されるオブジェクトであるゲームに取り組んできました。エンティティには、すべてのコンポーネントでupdateを順番に呼び出すことにより、オブジェクトを適切に変更する更新関数があります。これは明らかにスタイルのOOPです-動作はデータにリンクされており、データは変更可能です。エンティティは、コンストラクタ/デストラクタ/更新を持つオブジェクトです。

より機能的な方法:

別の方法は、エンティティをメソッドなしのデータにすることです。このエンティティは、それ自体で存在する場合と、さまざまなコンポーネントにリンクされているIDである場合があります。このようにして、完全に機能し、不変のエンティティと、新しいコンポーネント状態を生成する純粋なシステムを持つことができます(ただし、一般的には行われません)。

(個人的な経験から)後者の方法はより多くの牽引力を得ており、正当な理由があるようです。エンティティデータを動作から分離すると、より柔軟で再利用可能なコード(imo)が得られます。特に、システムを使用してコンポーネント/エンティティをバッチで更新すると、パフォーマンスが向上し、多くのOOP ECSを悩ますエンティティ間のメッセージングの複雑さを完全に回避できます。

TLDR:どちらの方法でもできますが、優れたエンティティコンポーネントシステムの利点は、より機能的な性質から得られると主張します。


特に、コンポーネントの要点は、扱いにくいOOP階層から逃げることでしたので、より多くの牽引力が得られました。これは、メリットの説明です。
パトリックヒューズ14年

2

データ指向エンティティコンポーネントシステムは、オブジェクト指向パラダイムと共存できます。-コンポーネントシステムは、ポリモーフィズムに適しています。-コンポーネントは、POD(プレーンな古いデータ)とALSOオブジェクト(クラスとメソッドを含む)の両方である場合があり、コンポーネントクラスメソッドがローカルオブジェクトが所有するデータのみを操作する場合、全体は依然として「データ指向」です。

このパスを選択する場合、仮想メソッドを使用することを避けることをお勧めします。仮想メソッドがある場合、コンポーネントは純粋にコンポーネントデータではなく、それらのメソッドは呼び出すのにより多くのコストがかかるためです-これはCOMではありません。原則として、外部のあらゆるものへの参照がないようにコンポーネントクラスを保持します。

例としては、vec2またはvec3があります。これは、そのデータに触れるためのいくつかのメソッドを備えたデータコンテナーであり、それ以上のものはありません。


2
この投稿は読みにくい(テキストの壁)。それをより良い形に編集してもいいですか?また、リンクされたブログ記事が質問に役立つと思われる理由を読者に説明すると役立ちます
...-gnat

...あなたが何らかの形でそのブログに関係している場合(あなたですか?)、所属
-gnat

はい、それは私のブログです。私は公開ブログと密接に提携しています。データ指向設計の原則に基づいたオブジェクト指向エンティティコンポーネントシステムの詳細を公開しています。バイアスを削除します。
ホーマー

2

ECSは基本的にOOPとは異なるものと考えており、データと機能が非常に明確に分離されているため、本質的に機能的または特に手続き型に近いものと同じように見える傾向があります。また、中央データベースを扱う種類のプログラミングに似ています。もちろん、正式な定義に関しては私は最悪の人です。概念的に定義されているものではなく、物事の傾向にのみ関心があります。

コンポーネントがデータフィールドを集約し、それらをパブリック/グローバルにアクセス可能にし、エンティティがコンポーネントを集約し、システムがそのデータの機能/動作を提供する一種のECSを想定しています。これは、通常オブジェクト指向コードベースと呼ばれるものから、根本的に困難なアーキテクチャ特性につながります。

そしてもちろん、人々がECSを設計/実装する方法の境界がいくらかぼやけており、そもそもECSを正確に構成するものについては議論があります。しかし、こうした境界は、関数型言語または手続き型言語と呼ばれるもので記述されたコードでもぼやけています。このすべてのあいまいさの中で、機能からデータを分離したECSの基本定数は、OOPよりも機能的または手続き型プログラミングにはるかに近いように思えます。

ECSをOOPのクラスに属すると考えるのが役に立たないと思う主な理由の1つは、OOPに関連付けられているSEプラクティスのほとんどが、データではなくパブリックインターフェイスモデリング関数を使用して、パブリックインターフェイスの安定性を中心に展開していることです。基本的な考え方は、パブリックな依存関係の大部分は、具体的なデータではなく抽象関数に向かって流れるということです。そのため、OOPは基本的な設計動作を変更するのに非常にコストがかかる傾向があり、具体的な詳細(機能を実装するために必要なデータやコードなど)を非常に安価に変更します。

ECSはこの点で根本的に異なります。公共の依存関係の大部分が具体的なデータ(システムからコンポーネントまで)に向かって流れるにつれて、物事がどのように結合されるかを考慮しています。その結果、ECSに関連するSEプラクティスは、データの安定性を中心に展開されます。これは、最も一般的で広く使用されているインターフェイス(コンポーネント)が実際には単なるデータであるためです。

その結果、DXとGLの両方のエンジンが提供されていれば、ECSを使用して、DirectXの代わりにOpenGLレンダリングエンジンを使用することができます。同じ安定したデータにアクセスできます。一方、それは非常に高価であり、たとえばaのデータ表現を変更するために多数のシステムを書き直す必要がありMotionComponentます。

これは、少なくとも結合特性と「パブリックインターフェース」対「プライベート実装の詳細」を構成する点で、OOPに従来から関連付けられているものとは正反対です。もちろん、どちらの場合でも「実装の詳細」は簡単に変更できますが、ECSでは変更にコストのかかるデータの設計(データはECSの実装の詳細ではありません)、OOPでは変更にコストのかかる機能の設計です(関数の設計は、OOPの実装の詳細ではありません)。それは「実装の詳細」という非常に異なる考え方であり、メンテナンスの観点からECSの主な魅力の1つは、私のドメインで、物事を行うために必要なデータは、そのデータを使用して行うことができるさまざまなこと(クライアントが考えを変え、新しいユーザーの提案が殺到するたびに変化する)よりも、一度にすべてを前もって安定させて正しく設計するのが簡単でした。結果として、抽象関数から生の中央データに依存関係を向け始めると、メンテナンスコストが急落することがわかりました(ただし、どのシステムがどのコンポーネントにアクセスして、概念的にすべてのデータにもかかわらず不変条件を正常に維持できるように注意します)グローバルにアクセス可能)。

そして、少なくとも私の場合、APIとすべてのコンポーネントを備えたECS SDKは、実際にはCで実装されており、OOPの類似点はありません。ECSアーキテクチャにオブジェクト指向が本来備わっていないことと、最も幅広い言語とコンパイラで使用できるプラグインアーキテクチャが必要であることを考えると、このような目的にはCが十分すぎることがわかりました。C ++は物事を非常に便利にし、システムは複雑さの大部分をモデル化するため、システムはまだC ++で実装されており、OOPに近いと考えられる多くの事柄で使用されていますが、それは実装の詳細のためです。建築設計自体は、依然として非常に手続き的なCに似ています。

ですから、少なくとも、ECSが定義上オブジェクト指向であると言うのはやや混乱していると思います。少なくとも基本は、一般にOOPに関連する多くの基本原則から完全に180度回転することを行います。カプセル化から始まり、望ましい結合特性と考えられるもので終わる可能性があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.