🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

3052閲覧

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

cushionA

総合スコア90

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2020/12/30 07:53

編集2020/12/31 14:32

前提・実現したいこと

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

現在考えている仕様

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

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

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

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

### 追記

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

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

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

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

### さらに追記

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

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

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

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

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

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

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

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

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

投稿2021/03/05 02:38

cushionA

総合スコア90

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問