自分が関わっているプロジェクトの関係で、後輩からいくつか質問を受けたので、ここに回答を書きます。自分も Unity ライトユーザーなのでご指摘あればどうぞ。
Hierarchy ウィンドウにあるオブジェクト等の元データを調べたい
原文は「■■■(筆者の名前)さんが作ったものに使われている「人間」はどのパックを使っているのか」ですが、せっかくなので自分で調べる方法を書いておきます。(というか、どれのことを言っているのか情報がなかった。)
この話をするには、まず Unity におけるアセット等のフォルダ構成が一般的にどのようなものか共有しておくべきかもしれません。
インポート済みのデータは基本的に Project ウィンドウから閲覧できるようになっています。最上位に Assets および Packages の2つのフォルダがあり、おおよそ、エディタ利用者が直接扱わないものは Packages、閲覧や編集を活発に行うものは Assets に配置されます。(この振り分けはアセットないしパッケージの開発者が設定する部分です。)
さて、Hierarchy 上に配置されるものは大抵、Assets フォルダの配下にありますが、Hierarchy 上(シーン内)に配置されたオブジェクトや、そのテクスチャを探すのに少し手間取ることもあると思います。というのも、Unity の Assets におけるフォルダ構成はエディタ利用者が自由に変更できるため、想定されていない配置になっている可能性もあるからです。
ただ、個々人のフォルダ構成の流儀には色々あるとはいえ、普通はフォルダ名にソースに関わる情報を記述するはずです。アセットストアで配布されているアセットも、少なくともトップレベルのフォルダには、パブリッシャーないしアセットの名称といった、ほかのアセットと混合しない Unique な(一意に識別できる)名前が採用されています。
少し遠回りになりましたが、つまり「どのパックを使っているのか」は、そのデータがどのフォルダに所属しているのかを見ることで分かることが多いということです。逆に分からないものが混じっていた場合は、内部での実験用として使うに留め、誤って外部に公開しないよう適切に管理するか、いっそ削除する必要があります。
ところで Hierarchy 上のオブジェクトを見ても、それが Assets 配下のどこにあるのか分からない/忘れてしまった場合はどうすれば良いのでしょうか?もう、そのオブジェクトは出典不明としてお蔵入りさせるしかないのでしょうか?
救済策はあります。Inspector ウィンドウです。Inspector ウィンドウは選択中のオブジェクトの詳細設定を行うだけでなく、実は元データの位置を示すリンクも載せています。確認してみましょう。
手元の Unity プロジェクト(Project ウィンドウではありません)を UnityHub から開き、Hierarchy ウィンドウから、どれでも良いので青いキューブが添えられたオブジェクトを選択します。Inspector ウィンドウにはそのオブジェクトに関する各種設定項目が表示されています。
Inspector の上端に目を移しましょう。Tag や Layer の設定の下に項目があります。Prefab や Variant あるいは Model と書かれている項目があり(これは対象の設定によって違います)、その横に Open | Select ボタンが配置されています。
Open は元データである Prefab を直接編集したり、3Dファイルであれば、該当ファイルを専用のビューアー等で直接閲覧する際に使うボタンです。そして Select こそ、今回必要としていた元データの位置を示してくれるリンクボタンです。クリックすると Project ウィンドウ内の適切なフォルダが展開され、該当データがハイライトされます。
ちなみに Overrides は同じ Prefab を利用している他のオブジェクトに、選択中のオブジェクトの変更を同期させるボタンです。
ようやく話が繋がりました。まとめると「Hierarchy で対象を選び、Inspector のリンクから Project ウィンドウに飛んで、フォルダ名や構成から、ソースを推定する」というのが一連の手順になります。
でもちょっと待ってください。オブジェクト表面に描かれた模様(マテリアルや、それを構成するテクスチャ)の元ファイルはどうやって探せばよいのでしょうか。これも Inspector から調べられます。
マテリアルに関する項目は Inspector の最下部にあります。「ナントカかんとか(Material)」と書かれた箇所の右側にあるケバブメニュー(︙1)を押下すると、Select Shader 等のメニューが出現し、Select Material という項目も出てきます。
これでマテリアルの所在が分かります。また、マテリアルに利用されているテクスチャの所在が知りたければ、該当マテリアルを Project から選択した際に Inspector に表示される項目から、添えられている画像部分をクリックすることでも該当ファイルがハイライトされます。
おおよそ、素材のソースを確認する方法は分かったでしょうか。
地震を実装したい
こちらの回答は、もう少し焦点を絞ります。
Unity において地震を実装するということは、地盤のずれや振動、その伝搬をシミュレーションしたいというよりも、単に部屋などを前後左右に揺らしたいということだと思われるので、その方法についてざっくり書きます。
まず既存の実装を利用する方法が挙げられます。
テキトウに GitHub で検索したら上のリポジトリが見つかりました。YouTube のタイトルには「with real data」とありますが、出典は明かされていません。(それか、自分が見逃しているだけかも)
データは用途に合わせて置き換える必要があります。詳しい実装内容は忘れましたが、たしか X-Z平面における加速度データが用意されていて、それを読み取って AddForce()
で地震動を再現していました。加速度データは Resorces/Data/Earthquake 配下にあります。必要ならこれを置き換えましょう。
データは以下のサイトなどから取得できます。(防災科研は登録が必要だったかも?)
・気象庁|強震観測データ
・防災科学技術研究所 強震観測網(K-NET,KiK-net)
・地震検索&ダウンロード
なお、このシステムのコードは若干エンタープライズ気味で、初心者としてはメンテナンスがしづらいものがあります。というわけで、スクリプティングが少しでもできるのであれば、上記データをパースしたものを、順次 AddForce()
していくシステムを自作すると良いです。
加速度データを変位に変換して MovePosition()
を回しても良いのですが、普通に時間で二階積分するだけだと位置ずれが大きいです。バターワースフィルタでどうのこうのするらしいですが、具体的な式がよくわからなかったので強制変位を反映する方法は保留にしています。
AddForce()
の場合も、そのままのデータを使っていると、どんどん位置がずれていきますが、物理演算を使っているので、バネで動きに制約を加えることができます。Configurable Joint なら伸縮・回転の制限を細かく設定できます。
ちなみに、バネをひとつ付けるだけだと、反動がなかなか収束せず、回転運動が生じます。移動方向を制限したバネで各方位から押さえつけるような構造にしておくと安定します。(スクリプトで制御しても良いのですが、精度が必要な案件でもないですし、書かなくて済むものは書きたくないので、自分はこうしています。)
さて、自分で組み上げる際の注意点ですが、Unity の物理は わりと雑 速度優先なので、オブジェクト間の相互干渉をできるだけ避けたり、シンプルな構造を採用するほうが良いです。
なので部屋を直接揺らしたり、直接バネを取り付けたりせず、まずは上の挿入画像のように地震動を再現する機構のみ作り、その動きを部屋に同期させるようにすると良いです。
結局同期させるなら、部屋を直接操作したほうが良さそうに思うかもしれませんが、Rigidbody が効いた箱のなかに Rigidbody を入れると箱やオブジェクト同士の干渉がひどくて地震体験どころではなくなります。何もしなくても本棚から本が飛び出て、椅子が転がり、机が跳ね回るならまだ良くて、設定次第ではあらゆるオブジェクトが爆発四散します。(あくまで設定次第ですが。)
箱(部屋)のなかのオブジェクトの挙動をある程度安定させるには、箱の「面」が物理的な反動を持たないようにしておく必要があります。そのため、箱には Rigidbody をかけつつも、当該コンポーネントにて isKinematic を True に(Inspector 上では✅)しなければいけません。
こういった諸設定を行ったうえで、加速度データに沿って AddForce()
された地震動オブジェクトを参照し、MovePosition()
で位置を同期すると、地震動を簡易的に再現できます。
物理系コンポーネントの要不要について
Rigidbody や Collider を付けるべきオブジェクトはどう考えれば良いでしょうか?
単純な話、とりあえずシーンを再生(プレイ)してみて、なにか不都合があったときに、その問題に応じて必要なコンポーネントを設置すれば OK です。物理演算は軽くはないので、利用せずに済むなら、そうすべきだからです。一方、今回は地震を扱うということもあり、インタラクティブ性を維持するには物理系コンポーネントを多用することになると思います。
例えば、上の章では、地震動を再現する部分と、その動きに同期して揺れる部屋の部分と、それぞれに Rigidbody がアタッチされることを前提に書きました。もし部屋のほうに Rigidbody がなく、単に Transform コンポーネントの position プロパティの更新を直接行った場合、部屋の壁や床だけが動いて、家具類がまったく動かない、という状況が起きたりします。
これは仕様上、位置更新は実質テレポートであり、物理的干渉が観測できないことが原因です。確実に物理干渉を起こすには、Rigidbody コンポーネントの AddForce()
メソッド or MovePosition()
メソッドから対象を操作する必要があります。また、こうした物理系の処理は Update()
メソッドではなく、物理演算のタイミングと同期できる FixedUpdate()
メソッド内で実行することが一般的です(要件によっては例外あり)。
さて、質問の原文は「家具などを配置しましたが、重力や当たり判定などは付ける必要があるのか」でした。すでに述べたように、これはケースバイケースです。自分で動いてほしい(周囲の状況に反応してほしい)オブジェクトには Rigidbody を付ける必要があります。また、衝突判定や接触判定を反映させるためには、Collider が必要です。
次の例を考えてみて下さい。本棚が一つあり、なかにはいくつかの本や小物が入っています。このとき、どのオブジェクトにどのようなコンポーネントが必要でしょうか。もし、よく見るようなシンプルな脱出ゲームであれば、isTrigger にチェックを入れた Box Collider と、接触判定に応じて任意の処理を実行するスクリプトコンポーネントが棚にだけアタッチされていれば間に合いそうです。単に 3D で家具や部屋の内装をチェックするだけなら、それすら不要です。
逆に、棚を押したときに揺れたり倒れたりしてほしくて、また、内容物が(棚との相対座標・回転ではなく)慣性に従って動いてほしいのであれば、すべてのオブジェクトに Rigidbody と Collider が必要でしょう。(オブジェクト間の干渉がひどい場合は、部屋と同様に isKinematic を設定した外枠を併用する形式で対応できます。ほかにベターな方法はないものか…。)
ところで、Mesh Collider を持つオブジェクトに Rigidbody を付けてシーンを再生すると、Mesh Collider を Convex に設定するよう警告が出ます。おそらく Unity が利用する NVIDEA の物理エンジン PhysX の仕様による問題だと思いますが、Convex にすると穴やくぼみが塞がれるため、オブジェクトの内部に Rigidbody と Collider を持ったオブジェクトを保持することが難しくなります。(そのままだと射出される。)
Box Collider や Sphere Collider のようなプリミティブな Collider であれば、この問題は起きません。しかし、オブジェクトの形状に合わせて、複数の Collider を手作業でセット・調整するのは骨が折れます。そういった作業が必要ということなら、SA Collider Builder を使うことができます。
利用するアセットによっては、すでにこういったセッティングが済んでいるのですが、そうでない場合は上記のようなことを念頭にいじってください。
なお、物理演算が期待通りの挙動になっているかの確認には、Physics Debugger を使うことができます。また、あまりに早く動いてしまい、目視で状態を追えなかったり、インスペクター上の値の確認が間に合わなかったりする場合には、Edit > Project Settings > Time の Time Scale を小さい値に変更することで時間の流れを遅くできます。必要に応じて利用してください。