迫真工学部~Unityの裏技~第三章

この記事は約6分で読めます。

1・経過

今まではBlenderで毎度毎度FBXファイルを出力し、寸法ミスがあるたびにBlenderに戻って、再びFBXファイルを出力するということをしていました。しかしながらこの方法では、四六時中あらゆるシステム/ステージの変更・再設計を要求されるゲーム開発にとって大きな負担となります。従ってUnity内で仮置きとしてステージを作る方法に切り替えました。デフォルトでもUnityで3Dオブジェクトを生成・設置することはできますか、今回はProBuildというアセットを導入して作成しています。いちいちBlenderでやる必要がなくて、結構色々と試行錯誤ができるのでお勧めです。

InputSystemについて

ゲームは基本的にキーボードやマウス、タッチパネル、ゲームコントローラー等のハードウェアから入力された情報を取得して(例えば「キーボードのwキーが押された」みたいな)、ゲーム内に操作を反映します。Unityにおいては、この入力情報の取得する役割はInputManagerが担っていましたが、複数のデバイス(キーボードやコントローラー)からの入力を一括して取得するInputSytemなるもの新たに追加されました。これによってUnityに行動を指定しておけば、InputSystemによってすぐに対応できるようになりました。ちなみにこれを学習するまでに三週間ぐらいかかりました(憤怒)。

using Inputsystem;//これがないと使えない
private Vector2 moveInput;//var型でも問題なし
public void OnMove(InputValue value)//必ずpublicに
{
moveInput = value.GetValue<Vector2>//moveInputにVector2型で入力を代入
}

↑の例は、”Player Input”コンポーネントをアタッチした後、”Send Messages”に設定。InputSystemにおいて”Move”というアクションを作成後、Vector2型に設定した時の場合.

もしInputSystemの名前を”Look”などにしたら、スクリプト内のイベント呼び出し時のものは、

On(アクション名)、(例では”OnLook”)として書きます。さらにどのようなデバイスからの入力情報(例えばキーの押し具合)を受け取るのかによって、public void On(アクション名)()の一番後ろの引数(?)に”InputValue”型だったりの変数で受け取らなければいけません。ただしこれは入力情報を必要とするものだけであって、ただ入力情報があったという事実だけを知りたいとき、具体的に言うなれば、

スペースキーを押した → ジャンプをする

といったような場合、わざわざスペースキーの押し具合でジャンプの高さを変えるひつようがないなら、先ほどのような引数は不要で、

public void OnJump()

{

具体的な処理

}

と書くことができます。

さらにPlayerInputコンポーネントは、一つのオブジェクトに対して、一つのみです。親子関係になっているオブジェクトに対してそれぞれコンポーネントをアタッチしてしまうと動作しません。

しかし、注意してほしいのは、これらはPlayerInputコンポーネントで入力情報を送る手段を

「send Message」にしているときだけの処理です。これをまた「Invoke Unity Event」などの他の手段に変更するとそれによってまた記述する内容は変化していきます。よって色々なところから自分にとってわかりやすい(なおかつ信頼性の高い)情報を入手していったほうがよさそうです。

2.NPC(non player character)の制作

 ゲーム内でプレイヤーに敵対、または協力して行動のできるNPCの制作をしています。目指しているのは、個々で自律的に行動でき、集団でいるときは連携して組織的に行動するというものです。具体的には近代軍隊を想像してもらえばよいかと思います。

 今はAI Navigationを使用して常にプレイヤーの背後を追跡してくるようにして、ある程度の距離になったときに弾丸を乱射してくるようなシステムになっています。最初は乱射されすぎてフィールドからたたき落とされました()。

 また現在はさらに、(寝る/食べる/戦う/休憩する)といったステート(状態)の間を変数や条件分岐などで遷移を作って状況に合わせてステートの変更を行う、有限状態マシーン(FSM)のようなNPCを目指して勉強しています。将来的に一つやってみたいのは、”眠気”、”好奇心”などのパラメータなどによって毎回変化していく人間の一日を再現することです。

3.Lightによる情景描写

 リアルなシーンを構成する要素には、音声、造形物の作りこみなど、たくさん列挙できると思いますが、その中でもプレイヤーにも印象的であるのはやはり光の描写であると思います。そこで、Unityにおいてどのようにライトを使用すればよいか、その中でも室内における光の描写をやってみようと思いました。

 その実験の成果が次の写真です。

 

 一見ただのろくでもない部屋ですが、次のように構成されています。

黄色は下側の描写に影響しない要素で、赤が下側の描写に関係する要素です。順番に説明していきます。

①電球

現実の電球は透明で内部から光を出します。しかし、Unityで再現しようとすると微妙だったので、発光マテリアルの適用して電球本体が光っているようにしています。もし消灯するときがきたら半透明の非発光マテリアルに変更するのも良いかもしれません。

②Point Light(ポイントライト)

Point Lightは、全方向に光を出す光源です。これは電球についているカバーに光を投影するのと、点線で示したようなカバーから漏れた光が天井に移るようにするために置いています。

③Spot Light(スポットライト)

Spot Lightは、限定された角度にのみ光を出す、指向性のある光源です。具体的には街灯や車のヘッドライトなどを想像してもらった方がよいかも。これは直接下に光を落とすために使用しています。

④家具

これらのオブジェクトはすべて静的(static)として扱っています。Unityでは、ライトの描写の計算を事前に行いテクスチャに焼き付けるBake(ベイク)というのが行えます。しかしこれらは、動きのないオブジェクトのみで、フィールドの各地を動きまくるプレイヤーやNPCなどには使用できません。しかしベイクしたものには、他の「リアルタイム」などといったモードなどよりも影の描写がよくなります。さらにベイクするとプレイ中に行われるライトの計算が減り、処理が軽くなるという利点があります。ですから、プロジェクトの内容に合わせて適度にベイクを取り入れることが望ましいと思います。(ベイクの時間はかかりますが)

一応比較のため制作途中でベイクを行っていたときの画像を載せておきます。画面直撮りですがご容赦ください。

↑ライトの設定をベイクにする前の制作途中の写真

椅子の影がどこか浮いているような感じがすると思います。

最初の設定にさらにCameraの方でPostEffectをつけてみた結果を載せておきます。

今後について

当たり前と言われれば当たり前ですが、Unityの物理演算(特にRigidbody)は、高校物理(斜方投射など)などの知識をさも当然のように要求されます。少し遊ぼうと思って、Unityでミサイルのような何かを作ろうとしたのですが、まんまとそれに騙され3~4時間ぐらい奪われました。改めて、物理の重要性を心から思い知らされたので、セミナー物理基礎を毎日1時間でも勉強していこうと思います。

コメント

タイトルとURLをコピーしました