1

サンプルのゲーム エンジン サーバーでは、ゲームの世界を World オブジェクトで表すことができます。ゲームには複数のゲーム ワールドがある場合があり、ワールドにいるプレーヤーは、そのワールド内のユニットの位置データのみを受け取る必要があります。

class World
{
    public List<Unit> Units { get; set; }
}

ただし、コードの一部は、ユニットがどのワールドにいるかを簡単に調べることができる必要もあります。そのため、ユニット オブジェクト自体がワールド参照を追跡します。

class Unit
{
    public World World { get; set; }
}

これはルックアップには機能しますが、プログラマーがオブジェクト間の関係を認識していないときにデータを変更するとすぐに問題が発生するため、 を読み取り専用に変更UnitsWorld、 に次のコードを追加しましたUnit

public virtual World World
{
    get { return _world; }
    set
    {
        // Unit must always be in a world
        Contract.Requires<ArgumentNullException>(value != null);

        // If already this, don't do anything
        if (value == _world) return;

        var oldWorld = _world;
        _world = value;

        if(oldWorld != null) oldWorld.UpdateUnitEntry(this);
        _world.UpdateUnitEntry(this);
    }
}

これは機能しますが、これを行うためのより良い方法があるように感じます。特に、同じ方法でリンクする必要があるものを追加すると (a にWorldStructures とPlayers があります)、多くの繰り返し機能が入ります。両側を手動で更新せずに、この 1 対多の関係を実現するより良い方法はありますか? ?

4

1 に答える 1

0

このような洗練された参照管理と GC を持たない C++ のような言語では、とにかくこのような循環参照が問題になります (例: SharedPtr)。これは、ゲーム状態のシリアル化などの問題でもあります。

これは、その問題に一般的にアプローチするためのより良い方法があるかもしれないと私に信じさせます. 例: ユニットは本当に自分の世界を知る必要がありますか? たぶん、それが必要になると思わせたそのコードを見て、これがもう必要なくなるように変更できるかもしれません。

そのため、エンティティ管理システムを実装し、抽象 ID またはハンドルによってのみゲーム エンティティを参照するようにします。背後のオブジェクトを操作する前に ID/ハンドルを解決しますが、エンティティに別のエンティティへの参照を保存させないでください。ゲームの状態をシリアライズしたい場合は、これも非常に役立ちます。

さもないと:

あなたがしていることは厳密に間違っているわけでも何でもありません。それが機能していて、あまり痛みがない場合は、そのままにしてください。

于 2014-09-08T14:19:45.490 に答える