配列のオブジェクトまたはオブジェクトの配列?


13

Roller Coaster Tycoonのラインに沿った、管理シムゲームを作成しています。パフォーマンスを最大化するために、ワールドオブジェクトを構造化する最善の方法を知りたいです。

私のゲームには5,000人の人がいるとしましょう:

オブジェクトを作成し、そのような配列に保存します。

class person() {
    this.x = 0;
    this.y = 0;
    this.thirst = 15;
    this.hunger = 15;
    // etc.. add methods:
    public findPath(int destX, int destY) {
    // and so on
    }

    people = new person[5000];

for (int = 0; i < 5000; i++) {
    people[i] = new person;
    }

または、次のような人々の属性を表す多くのバイト配列を含む人々のオブジェクトを作成する必要があります。

class people() {
    this.hunger = new byte[5000]
    this.thirst = new byte[5000]

    getThirst(int i) {
        return this.thirst[i]
        }

 // and so on....

それとも、私は完全に外れていますか?


かなり興味深い質問です。特に2013年、RCTが発表されてから12年以上たってから、世界で5000の独立したNPCを目にするという考えは完全に不可能に見えます(技術の進歩にもかかわらず)
-Katana314

回答:


15

一般的な用語は「配列の構造」(SOA)と「構造の配列」(AOS)であり、Cに由来し、SIMD作業の観点から最もよく見られます。

通常、AOSアプローチは適切に使用すればより高速ですが、SOAはより簡単に作業できる傾向があります(したがって、より重要な品質である開発時間に最適化されます)。

SOA、特にJavaでは、データをメモリに密に詰めたままにすることができます。プロパティを反復処理し、CPUキャッシュなどが満足な状態を維持することを期待できます。AOSでは、特にJavaでは、すべてのオブジェクトがメモリの「どこか」に割り当てられます。オブジェクトを反復処理すると、CPUキャッシュが大幅に低下する可能性があります。

最後に、あなたが最も使いやすいと思うアプローチを採用します。ゲームが10年前のPCをサポートするか、9年前のPCのみをサポートするかよりも、開発時間のほうがはるかに価値があります(htatが最新のハードウェアを必要とすることはほとんどありません)。


1
3番目の段落では、AOSを2回参照するつもりですか?コメントは矛盾しているようです
...-ali_goes_oosh

申し訳ありませんが、修正しました。
ショーンミドルディッチ

4

Facadeパターンを使用して1つのインターフェイスから他の基になる表現に変換するので、両方を持つことはできない理由はありません。たとえば、SeanのSOA / AOS用語を使用すると:

SOAファサード

class PeopleFacade {
    Person persons[5000];
    getThirst(int i) { return persons[i].thirst; }
}

AOSファサード

class People { int thirsts[5000]; } people;
class PersonFacade {
    int i;
    getThirst() { return people.thirsts[i]; }
}

このようにして、使いやすいフォームから自由に選択できますにして、開発者インターフェイスとして、効率/キャッシュの理由など、何らかの理由で実装として最適なもの。

ファサードのもう1つの利点は、実際にメモリにあるよりもはるかに多くの人を表すためにインターフェイスを使用するフライウェイトパターンに非常に自然につながることです。たとえば、おそらく喉が渇いていないロボットのパトロンがいます。その特別なケースをに入れることができPersonFacade、そのインターフェースのユーザーはロボットについて知る必要はありません。

class People { int nonRobotThirsts[1000]; } people;
class PersonFacade {
    int i;
    bool isRobot;
    getThirst() {
        if (isRobot)
            return 0;
        else
            return people.nonRobotThirsts[i];
    }
}

...またはよりオブジェクト指向のアプローチを使用するとRobotPersonを除いてまったく同じように動作する別個のクラスができますgetThirst()


-1

オブジェクトを作成し、配列に保存します!空腹渇きの ために配列を作成すると、スペースを少し節約でき、いくつかの単純な状況でより速く実行できますが、OOPではありません。JavaとOOPは、機会があればあなたに大いに役立ちます。本当にシンプルなゲームの場合、2番目の例はうまくいくかもしれませんが、それでもあなたはオブジェクト指向のスキルを練習する必要があります。プログラムがどんなに大きく、複雑で、毛むくじゃらであっても、最初のアプローチはうまくいきます。

常に取得するのが便利だと思う Personクエリからオブジェクト。 このメッセージ送信したのはですか?例えば。あなたが書く多くのメソッドは、彼らが誰扱っているか知りがるでしょう。そして、適切なPersonクラスにうまく適合する多くのメソッドがあります。Person静的またはシングルトンの場合、個々の人々に作用するメソッドをどこに配置しますか?

マルチスレッドを実行する場合(そして5000人のユーザーがいる場合)、各ユーザーの親インスタンスはるかに実用的であることがわかります。

(そして、その人々の配列:今のところそれを固執しますが、ある時点で他のストレージデバイスが必要になります。名前で人々を見つけることができる何らかのマップ。そしておそらく異なるキーを持つ複数のリスト、配列またはリンクリストになるのに十分な短いリストを作成します。)

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