4

ゲームエンジンにオブジェクトのクローンを実装するための探求で、少しつまずきました。私の目標は、クラスが特別な扱いを必要としない限り、クラスごとに維持する必要のないクローンシステムを作成することです。

私のゲームエンジンのセットアップは、Texture2Dの形式でいくつかの画像データを含む基本クラスObject2Dを中心に展開しています。長い話は、Texture2Dを含むSpriteを含むDisplayObjectが含まれているということです。当然、「Player」、「Enemy」、「Projectile」などの他のクラスはすべて、基本的なObject2Dクラスから派生します。

残念ながら、XNAのTexture2Dクラスはシリアル化できないことがわかりました。これは理にかなっています。メモリ内のテクスチャデータを意地悪に複製したくないからです。

これは私にとってジレンマを生み出します。オブジェクトのクローンを作成するためにディープクローンメソッドを使用していましたが、シリアル化できないため、それを行うことができなくなりました。Texture2D [NonSerializable]をマークしようとしましたが、クローンのテクスチャがnullであるため、描画しようとすると問題が発生します。クローン作成後に割り当てることができる隠されたトリックを見つけることができませんでした(ある種の「onClone()」メソッドのように)。

だから私はこれをやろうと思った。一般的にディープクローンを作成できないオブジェクトの場合、clone()メソッドを指定できる「SpecialClone」インターフェイスを実装します。

ただし、一般的にディープクローンを作成できないクラスは基本クラスであるため、クラスごとにクローンメソッドを作成するという最初の段階に戻ります。

    public static T clone<T>(T obj) {
        if (obj == null) return default(T);

        if (!typeof(T).IsSerializable) {
            if (obj is SpecialClone) {
                object obj2 = ((SpecialClone)obj).clone();
                return (T)obj2;
            } else {
                throw new ArgumentException("Object type is not serializable.", "obj type: " + Type.GetTypeHandle(obj));
            }
        } else {
            return deepClone(obj);
        }
    }

    public static T deepClone<T>(T obj) {
        if (obj == null) return default(T);
        if (typeof(T).IsSerializable) {
            try {
                BinaryFormatter bf = new BinaryFormatter();
                MemoryStream ms = new MemoryStream();
                bf.Serialize(ms, obj);
                ms.Seek(0, SeekOrigin.Begin);
                T obj2 = (T)bf.Deserialize(ms);
                ms.Dispose();
                return obj2;
            }
            catch (Exception e) {
                Console.WriteLine(e);
                return default(T);
            }
        } else {
            Console.WriteLine(typeof(T) + " is not marked as serializable!");
            return default(T);
        }
    }

私はまだC#が得意ではないので、使用できるトリックが不足しているかどうか、またはこれが本当にこの問題に対処する方法であるかどうかはわかりません。このクローン作成の主な目的はObject2Dタイプを対象としているため、作成する新しいサブクラスごとにクローンメソッドを作成する必要があるのは非常に困難です。

これを回避する方法はありますか?

4

2 に答える 2

1

Texture2dのクローンを作成する必要はありません。

テクスチャ(およびモデル、ウェーブファイルなど)を「共有アセット」と見なす必要があります。サイズは数メガバイトになる可能性があります。メモリ不足の世界にあなたを残すクローン作成は、(クローン作成にかかる時間に加えて)非常に迅速に傷つきます

理想的な解決策: 代わりに、参照のクローンを作成します。

各Object2Dインスタンスがシリアル化されることを意図していない場合は、同じTexture2DをさまざまなObject2Dに参照割り当てできます。シリアル化する場合は、前述のように、Texture2D参照を渡し、さらに、シリアル化される文字列textureFilePathをコピーします。

また、これはXNAのContentManagerが自動的に行うことであることに注意してください。「myPic.xnb」を10回要求すると、自動的に1回読み込まれ、その参照が10回返されます。

于 2011-12-26T08:10:57.417 に答える
0

ICloneable(.Netコアインターフェイス)は、SpecialCloneよりも優れています。保護されたコンストラクターctor(SerializationInfo info、StreamingContext context)とともにISerializableインターフェイスを実装することもできます。

これにより、カスタムシリアル化が可能になります(SerializationInfoは、後でオブジェクトを逆シリアル化するために必要なものをすべて保持できるバッグであり、保護されたコンストラクターで渡されます)。

シリアル化について知っておくべきことはこれだけです。それができるかどうかは、そのオブジェクトを再作成するために逆シリアル化で使用できる、シリアル化できないクラス(つまり、キー、ファイル名、バッファー)に何かがあるかどうかによって異なります。

于 2011-11-12T17:19:48.763 に答える