ゲーム制作におけるファイルの運用
Posted: 2017年4月04日(火) 19:05
こんにちは。DXライブラリでシューティングゲーム制作をしている中でファイル(ファイルロード)関連で悩む事があり、投稿させていただきました。
現在、各クラスオブジェクトがファイルを使用する(所有する)場合、そのクラス自身に初期化関数内でロードさせて運用しています。
また、初期化関数内でそのロードしたファイルを使用したその他の初期化処理(画像サイズの取得など)を行っています。
しかし、シーン変更時のローディング画面を行うためにDXライブラリ用の非同期読み込みを行おうと思った場合、上記の手法ではロードが完了していないままファイルを使用した初期化を行おうとしてしまうため、当然、初期化が失敗していまいます。
方法として、
①使用するファイルを一括で管理するクラスを別で作り、ローディング時はそのクラスに非同期読み込みを行わせてから、各クラスオブジェクトに一括クラスへのインターフェースまたはファイルを 初期化関数の引数で与えていき、初期化を行う。
②初期化関数の他に、ロード関数を全てのクラスに実装し、その中でファイルをロードさせてから、あらためて初期化を行う
③現在の運用方法のまま、シーンの初期化自体をthreadクラスなどでマルチスレッドにして走らせる
④シングルトンなどでグローバルなファイル保管部分を作り、非同期で読み込んだファイルをそこに保管(あるいはweak_ptrなどで監視登録)したあと初期化関数でアクセスしファイルを取り出す
を考えてみましたがそれぞれの方法で疑問があります。
①の場合、派生クラス型のオブジェクトなどは引数で受け取るため引数付きの初期化関数を用意することになりますが、基底クラスの初期化関数(仮想関数)と別のものを定義する必要があるため、誤って基底クラスの初期化関数を呼び出し、初期化忘れが発生しやすくなるのではないかという懸念があります。
②は現在の運用方法のままいけそうですが、初期化関数以外にそういう関数を用意するのはどうなんだろう・・・と考えています。初期化関数を呼べばエラーが起きない限り運用できるようになっているべきと思っているのですが、ロード関数を用意すると初期化関数以外に初期化で行うべき関数ができてしまうのでよくないのでは?と考えています。
③の方法はDXライブラリの関数自体がスレッドセーフでないため、初期化をマルチスレッドで行うのは何も考えずにすると画像が途中で切れていたりノイズが入ったりするなど安定しません。そうでなかったとしても初期化関数内では色々な処理をすると思うので、マルチスレッドで走らせるのは管理しきれないと思っています。あるいは私の知識が乏しいだけで、DXライブラリであってもマルチスレッドでできるし、管理もしっかりやればできるのでしょうか。
④はオブジェクト指向で考えればこの方法はよくないと思いますが、実際どうなんでしょう。実際はこの方法のほうが運用しやすいということはあるんでしょうか
長くなりましたが質問をまとめますと、
1)①~④のどの方法を取るべきか。あるいはこれら以外にもっと取るべき方法があるか
2)①~④のどれかをとる場合、懸念点については問題ないのか
とこちらは少し内容からそれるかもしれませんが、
3)コンストラクタ内でファイルロードはするか(コンストラクタと初期化関数はどういう風に使い分けているか)
もよければ教えて頂けると幸いです。
意見、おかしな点の指摘などあればよろしくお願いします。
現在、各クラスオブジェクトがファイルを使用する(所有する)場合、そのクラス自身に初期化関数内でロードさせて運用しています。
また、初期化関数内でそのロードしたファイルを使用したその他の初期化処理(画像サイズの取得など)を行っています。
しかし、シーン変更時のローディング画面を行うためにDXライブラリ用の非同期読み込みを行おうと思った場合、上記の手法ではロードが完了していないままファイルを使用した初期化を行おうとしてしまうため、当然、初期化が失敗していまいます。
方法として、
①使用するファイルを一括で管理するクラスを別で作り、ローディング時はそのクラスに非同期読み込みを行わせてから、各クラスオブジェクトに一括クラスへのインターフェースまたはファイルを 初期化関数の引数で与えていき、初期化を行う。
②初期化関数の他に、ロード関数を全てのクラスに実装し、その中でファイルをロードさせてから、あらためて初期化を行う
③現在の運用方法のまま、シーンの初期化自体をthreadクラスなどでマルチスレッドにして走らせる
④シングルトンなどでグローバルなファイル保管部分を作り、非同期で読み込んだファイルをそこに保管(あるいはweak_ptrなどで監視登録)したあと初期化関数でアクセスしファイルを取り出す
を考えてみましたがそれぞれの方法で疑問があります。
①の場合、派生クラス型のオブジェクトなどは引数で受け取るため引数付きの初期化関数を用意することになりますが、基底クラスの初期化関数(仮想関数)と別のものを定義する必要があるため、誤って基底クラスの初期化関数を呼び出し、初期化忘れが発生しやすくなるのではないかという懸念があります。
②は現在の運用方法のままいけそうですが、初期化関数以外にそういう関数を用意するのはどうなんだろう・・・と考えています。初期化関数を呼べばエラーが起きない限り運用できるようになっているべきと思っているのですが、ロード関数を用意すると初期化関数以外に初期化で行うべき関数ができてしまうのでよくないのでは?と考えています。
③の方法はDXライブラリの関数自体がスレッドセーフでないため、初期化をマルチスレッドで行うのは何も考えずにすると画像が途中で切れていたりノイズが入ったりするなど安定しません。そうでなかったとしても初期化関数内では色々な処理をすると思うので、マルチスレッドで走らせるのは管理しきれないと思っています。あるいは私の知識が乏しいだけで、DXライブラリであってもマルチスレッドでできるし、管理もしっかりやればできるのでしょうか。
④はオブジェクト指向で考えればこの方法はよくないと思いますが、実際どうなんでしょう。実際はこの方法のほうが運用しやすいということはあるんでしょうか
長くなりましたが質問をまとめますと、
1)①~④のどの方法を取るべきか。あるいはこれら以外にもっと取るべき方法があるか
2)①~④のどれかをとる場合、懸念点については問題ないのか
とこちらは少し内容からそれるかもしれませんが、
3)コンストラクタ内でファイルロードはするか(コンストラクタと初期化関数はどういう風に使い分けているか)
もよければ教えて頂けると幸いです。
意見、おかしな点の指摘などあればよろしくお願いします。