自己流SceneManager
Sceneに渡す引数をキャストしたくない
今回は自己流のSceneManagerを作りました。今回一番重視した点は「Sceneに渡す引数をキャストしない」ことです。
例えば、キャラクター詳細シーンがあった場合、どのキャラクターについて表示するかはキャラクター詳細シーンの呼び出し側からキャラクターのIDを渡すと思います。これをint型で渡すの難しく、大抵はobject型にキャストして渡すことになると思います。難しい理由は次の2点です。
- シーンの読み込みは非同期なので呼び出し時点では呼び出されるシーンは存在しない
- 他のシーンの引数がint型とは限らない
呼び出し時点でシーンが存在しないので、シーン引数は一時的に保存しておく必要があります。また、シーン引数はシーンによって変わるため、どんな型が来ても大丈夫なようにobject型で保存することになります。
ただ自分はどうしてもobject型へのキャストを避けたいと思っていました。その理由は2つです。
- ダウンキャストは危険なので行いたくない
- 引数のヒントが無くなる
渡される引数がobject型なのでどんな型でも来る可能性があるということです。 int型を要求するシーンでも絶対にint型をもらえるとは限りません。
また、どのような引数を渡せばよいか、object型ではひと目ではわかりません。引数の型については受け取るシーンのソースコードを読む必要があります。シーンを作成した直後は覚えているでしょうが、1ヶ月後にもなればシーンを作った本人も忘れています。ドキュメントにして残しても、変更があった場合にドキュメントが変更される保証はありません。
Sceneに渡す引数をActionで保存する
この問題の解決策としてAction<T>として保存することにしました。Tはシーンが読み込まれたときにSceneDirecotr(自己流SceneManagerの名前)にアクセスするクラスです。このクラスにはわかりやすいように○○SceneStarterという名前を付けるようにしました。
例えばTitleシーンの読み込みには
sceneDirector.LoadFromBuiltinAsset<TitleSceneStarter>("Title", (TitleSceneStarter ss) => ss.SetArgument("User1"));
という形で呼び出し、(TitleSceneStarter ss) => ss.SetArgument("User1")の部分をAction
class LoadedActionCache<T> { public static Queue<Action<T>> Queue { get; } = new Queue<Action<T>>(); }
というCacheクラスを作って保存します。Queueなのは複数回同時にScene読み込みが行われた場合を想定しています。
参考:http://engineering.grani.jp/entry/2017/07/28/145035
Titleシーンが読み込まれたらTitleSceneStarter.Start()がSceneDirectorにアクセスして保存してあったAction
懸念点
Actionをstaticな領域に保存していますが、これを初期化する方法を考える必要があります。エラーで「タイトルに戻る」という処理を実装する場合、このstaticな領域にActionが残ったまま再開されてしまう可能性があります。