回答:
ゲームの範囲に依存します。アセットマネージャーは、タイトルが大きい場合には不可欠ですが、ゲームが小さい場合にはそれほど重要ではありません。
大きなタイトルの場合、次のような問題を管理する必要があります。
小さいタイトルの場合、これらの問題はそれほど問題ではありません。XNAのようなフレームワークにはアセットマネージャーがあります-再発明する意味はほとんどありません。
アセットマネージャーが必要な場合は、万能のソリューションはありませんが、ファイル名のハッシュ*としてキーを使用したハッシュマップ(小文字で区切り、すべて「固定」)が見つかりました私が取り組んできたプロジェクトに適しています。
通常、アプリでファイル名をハードコードすることはお勧めできません。通常、別のデータ形式(xmlなど)でファイル名を「ID」に表現することをお勧めします。
(ここでは「アセットマネージャーを使用しないでください」という議論を避けようとしています。これはトピック外だと考えているためです。)
キー/値マップは非常に便利なアプローチです。
さまざまなリソースタイプのファクトリを登録できるResourceManager実装が1つあります。
「getResource」メソッドは、テンプレートを使用して必要なリソースタイプの正しいファクトリを見つけ、特定のResourceHandleを返します(再びテンプレートを使用してSpecificResourceHandleを返します)。
リソースは(ResourceHandle内の)ResourceManagerによって再カウントされ、不要になったときに解放されます。
最初に作成したアドオンは「reload(XYZ)」メソッドで、コードを変更したりゲームをリロードしたりすることなく、実行中のエンジンの外部からリソースを変更できます。(これは、アーティストがコンソールで作業する場合に不可欠です;))
ほとんどの場合、ResourceManagerのインスタンスのみがありますが、レベルまたはマップのためだけに新しいインスタンスを作成することもあります。このように、levelResourceManagerで「シャットダウン」を呼び出すだけで、リークがないことを確認できます。
// very abbreviated!
// this code would never survive our coding guidelines ;)
ResourceManager* pRm = new ResourceManager;
pRm->initialize( );
pRm->registerFactory( new TextureFactory );
// [...]
TextureHandle tex = pRm->getResource<Texture>( "test.otx" ); // in real code we use some macro magic here to use CRCs for filenames
tex->storeToHardware( 0 ); // channel 0
pRm->releaseResource( pRm );
// [...]
pRm->shutdown(); // will log any leaked resource
専任のマネージャークラスが適切なエンジニアリングツールになることはほとんどありません。アセットが一度だけ必要な場合(背景やマップなど)、一度だけリクエストする必要があり、処理が完了したら通常どおりに終了させます。特定の種類のオブジェクトをキャッシュする必要がある場合は、最初にキャッシュをチェックしてから何かをロードし、キャッシュに入れてから返すファクトリを使用する必要があります。そのファクトリは、静的変数にアクセスする静的関数にすぎません。 、それ自体の型ではありません。
スティーブイェッジ(他の多くの多くの人も)は、シングルトンパターンを介して、役に立たないマネージャークラスが最終的に存在することについての良い物語を書きました。http://sites.google.com/site/steveyegge2/singleton-considered-stupid
私は常に、優れた資産管理者にはいくつかの操作モードが必要だと考えてきました。これらのモードは、多くの場合、共通のインターフェースに準拠した別個のソースモジュールです。操作の2つの基本モードは次のとおりです。
共有データベースからすべてのassestを取得し、運用データセットを作成できるツールが必要です。
開発者としての数年間、このようなことは一度もありませんでしたが、私はほんの一握りの会社でしか働いていなかったので、私の見解は実際に代表的なものではありません。
更新
OK、いくつかの否定的な投票。この設計を拡張します。
第一に、あなたが持っているのであれば、あなたは本当にファクトリークラスを必要としません:
TextureHandle tex = pRm->getResource<Texture>( "test.otx" );
あなたはタイプを知っているので、そうしてください:
TextureHandle tex = new TextureHandle ("test.otx");
しかし、その後、私が言いたかったのは、とにかく明示的なファイル名を使用しないことです。ロードするテクスチャは、テクスチャが使用されるモデルによって指定されるため、実際に人間が読める名前は必要ありません。 32ビットの整数値にすることもできますが、これはCPUでの処理がはるかに簡単です。そのため、TextureHandleのコンストラクターには次のものがあります。
if (texture already loaded)
update texture reference count
else
asset_stream = new AssetStream (resource_id)
asset_stream->ReadBytes
create texture
set texture ref count to 1
AssetStreamは、resource_idパラメーターを使用してデータの場所を見つけます。これを行う方法は、実行している環境によって異なります。
開発中:ストリームは(たとえばSQLを使用して)データベース内のIDを検索してファイル名を取得し、ファイルを開きます。ファイルはローカルにキャッシュするか、ローカルファイルが存在しないか、時代遅れ。
リリース:ストリームはキー/値テーブルでIDを検索し、オフセット/サイズを大きなパックファイル(DoomのWADファイルなど)に取得します。
私が資産のためにしたいことは、一括マネージャーを設定することです。ドゥームエンジンに触発、塊はに格納された資産を含むデータの部分である一括ファイル塊の名前、長さ、タイプ(ビットマップ、サウンド、シェーダなど)を宣言し、コンテンツタイプ(ファイル、別の塊、内部が一括ファイル自体)。起動時に、これらのランプはバイナリツリーに入力されますが、まだロードされていません。各マップ(これも塊である)には依存関係のリストがあります。これは、マップが機能するために必要な塊の名前です。これらの塊は、既にロードされていない限り、マップのロード時にロードされます。さらに、マップの隣接するマップの塊がロードされるのは、同時にではなく、何らかの理由でエンジンがアイドリングしているときです。これにより、マップがシームレスになり、ロード画面がなくなります。
私の方法はオープンワールドマップに最適ですが、レベルベースのゲームはこの方法で得られるシームレスさの恩恵を受けません。お役に立てれば!