質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.78%

Unity2Dでシームレスマップを実装する方法について

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 539

score 75

前提・実現したいこと

Unity2Dでダークソウルのようなファストトラベル付きのシームレスマップを実装したい。
現在予定している仕様については以下で詳細を述べます。
しかしこの仕様に添って提案・アドバイスを行う必要は全くなく、他によい実装があればどうかご教授くださいませ。
よろしくお願いいたします。

現在考えている仕様

・まずゲーム全体を一つの大きなシーンにする。

・ステージが5つとするなら5つはそれぞれマップにつき一つのTileMapオブジェクトと環境物、敵、ギミックなどで占められていると仮定する。
・それに加えてそれぞれのマップをつなぐ通路的な小さな空間を用意する。
・普段は現在いる一つのマップ以外の4つのオブジェクトは非アクティブにしておく。
・マップの切れ目近くで次のマップのテクスチャなどのデータを非同期でロードし、マップに侵入する通路で次のマップのオブジェクトを全て一斉に(一部ずつにしたほうがいいでしょうか?)アクティブにする。
・次のマップに入れば通路を除く前のマップは非アクティブにしてデータもアンロードする。
・敵のステータスに所属マップを加えて休憩ポイントで休憩した際とファストトラベルした際に蘇る敵を管理する。
・ギミックと敵はプレイヤーの近くに来るまで機能を停止していて、ある程度離れるとまた機能停止する。しかし初期位置?元の持ち場?というか縄張りを離れていた場合戻るまでは敵キャラは動く。(startメソッドで初期位置を記録する)

というようなやり方でシームレスマップと敵キャラを管理したいと思うのですがいかがでしょうか?
メモリ管理に自分なりに気を遣った結果ですが、至らぬ点、あるいは根本の方向性からして間違っているということがあればご指摘いただければ幸いです。
また足りない情報などあればお手数ですがご指摘くださいませ。

どうぞよろしくお願いいたします。

 追記

手前で色々と調べた結果、上の仕様に加えて

・マップをアクティブにした際環境物やエネミーなどのオブジェクトはコンポーネントのenableを切った状態にして呼び出す。
そして近くに入ったらenableをtrueにする。(この際スプライトレンダラーの方はそもそもカメラに入っていない場合は切らなくていいですか?)

というのを加えてみることにしました。
色々と調べましたが正直あまり定まらず、僕が好きな2Dゲームでは(シームレスです)シーン移動のようなものはなく、あるマップのはしから落ちると別のマップの地面に叩きつけられるようなこともあったので一つのシーンにマップを集めていいのではないかと思い至った次第です。
それからUse By Compositeを使うかどうか悩んでいます。
デフォルトのタイルマップコライダーを無効化してコンポジットコライダーを利用するプロパティのようですが、
2D タイルマップアセットワークフロー
上記記事の記述によると最適化されるようなので今のところ使うつもりです。

そして上の仕様でプロファイラーを注視しつつ作っていきますがアドバイスがあればぜひとも教えて下さい。
よろしくお願いします。

 さらに追記

マップそのものをプレハブ化して呼び出すアプローチを試してみる。
呼び出す際もインスタント化とオブジェクトプールの2つを試してみる。

インスタンス化ではフレームレートが低下し入力が遅延するなどゲームプレイを阻害し、メモリ使用量もかなり増えていた。
しかし前のマップを消すとメモリ使用量は改善されたが前に試した方法に比べて劇的に改善されているかというとそんなことはなかった。
オブジェクトプールについても検証してみる。

オブジェクトプールの方針で試してみましたが、こちらは非常にメモリ使用量が高くなりました。
フレームレートは安定して入力遅延は抑えられたものの良くない方法だと結論づけざるを得ないように感じます。

結果として最初のやり方が一番安定しているように思いました。

最初のやり方の際には正直マップが小さかったです。
そのことを加味していなかったせいか改めて試すとこちらでもメモリ使用量が大きいです。
ManagedHeapが大きいのでそもそもコードに問題がある可能性が大きいです。
しばらく色々と軽量化してみます……。

フレームレートが落ちている際もcpu、gpuの使用率は共に20%を上回らないようです。
パソコンの設定のせいなのかこれでは本当の負荷が測れていない可能性がありそうな気がする。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

様々な検討を重ねた結果以下のような方法に落ち着きました

・ゲーム全体を一つの大きなシーンにする。
・ステージが5つとするなら5つはそれぞれステージを複数に分割したいくつかのTileMapオブジェクトと環境物、敵、ギミックなどで占められていると仮定する。
これらの要素を含むステージを分割した欠片を以下ではひとかたまりでマップパーツと呼ぶ。
・ステージに加えてそれぞれのステージをつなぐ通路的な小さなマップがあるとする。
・この通路ではテクスチャデータなどのロード、アンロードを行う。
・マップパーツはプレハブにしておいて、普段は現在地点周囲のマップパーツのみをインスタンス化する。不要になれば破棄する。
・マップパーツとマップパーツの継ぎ目にオブジェクトを配置し、プレイヤーがそのオブジェクトに右から触れたか左から触れたかでトリガーイベントを発生させて進行方向の先にあるマップをインスタンス化する。
・この触れるという判定はカメラサイズの3倍ほどの大きさのトリガー判定をプレイヤーにつけて行う。
・また一度生成されたマップはしばらくは消えない。マップパーツの切れ目で行き来することにより何度も生成したり破棄したりするのを避けるため。
・敵のステータスに所属ステージをつけて休憩ポイントで休憩した際とファストトラベルした際に蘇る敵を管理する。
・ギミックと敵はプレイヤーの近くに来るまで機能を停止していて、ある程度離れるとまた機能停止する。しかし元の持ち場?というか縄張りを離れていた場合戻るまでは敵キャラは動く。

自己解決が遅くなりまして大変申し訳ありません。
どなたかの参考になれば幸いです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る