[Unity]ドア開閉ギミックとドアの世界観作り

## はじめに
お疲れ様です、ゆきおです。
今日は[前回の記事](飛ばす先のURL)に引き続き、簡単なゲーム制作をしていこうと思います。
前回は便利なアセットを追加して、実際に動かしてみたり、キャラクターを差し替えたりしてみました。

今回は簡単なドアの開閉アニメーションを作ってみたいと思います。

## 実装するにあたって
まず重要な要素を挙げていきます。

**・Animator**
シーン上にあるオブジェクトを動かすためのUnityの機能です。
Animationというファイルを作成し、それを制御するための機能がAnimatorです。
![スクリーンショット 2024-01-07 223858.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562437/d5425485-c543-b03c-ce44-5b9c566ca7ad.png)
オレンジだったりグレーだったりするパーツがAnimationファイルです。
それらを写真のように繋げて、どの入力でどのAnimationをどういう順番で再生するかなどを制御しています。

**・Input System**
UnityにはInput Systemという入力を管理する非常に便利な機能があります。
![スクリーンショット 2024-01-07 224427.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562437/2f528390-da94-f559-025b-d7bd4e29d75a.png)
イベント(移動やジャンプなど)と入力するキーをペアとして登録し、管理できる機能です。
移動を例にとってみると、WASDキーとゲームパッドが接続されている場合の左スティックが登録されています。

このシステムを使わないと、たとえば「移動」をスクリプトで呼び出すときに入力キーの数だけif文の条件に||で追加しなければなりませんので非常にめんどくさいコードを書くことになります。
![スクリーンショット 2024-01-11 191515.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562437/12f18239-5829-0131-4723-6f2ec1cc04cc.png)

しかしInputSystemを間に挟むことで「何のキーが入力されたか」はカプセル化され、「Moveイベントが呼ばれた」ということを検知するだけになります。
![スクリーンショット 2024-01-11 191532.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562437/fa8eace7-9a7b-7767-6f59-a31f056307dc.png)

もしWASD以外にも矢印キーで移動もしたいなーと思ったら、該当するイベントにキーを登録するだけでよくなります。
今回はこの機能をつかって「Fキーをインタラクションキーにする」というのを後述するレイキャストと組み合わせて実装していきたいと思います。

**・Raycast**
レイキャストとはレーザーのようなものをオブジェクトから一直線に発し、当たり判定(コライダー)を持つ他のオブジェクトを検知するために使います。
Unityに限らず3D制作においては欠かせない機能となっています。
ほかにもSphereCastといって円形に発するものもあり、普段プレイしているゲームにも頻繁に用いられていると思います。

今回はAnimationの実装を進めていきたいと思います

## ドアの作成
なわけでアニメーションファイルを作成してドアを動かしましょう

まずは適当にドアっぽい物体を用意します
今回はキューブの大きさや厚さを調整して簡単なドアっぽい形のものを作成しました。
![スクリーンショット 2024-03-27 093818.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562437/a43bd49c-8a82-8e8a-45a3-e13955ac7836.png)

これを使って動きを付けていきます
ドアの開閉なので、Y軸を100度くらい回転させるという簡単なアニメーションです。

がしかし、そのままY軸のRotationを動かしても、ドアの中心を軸に回転してしまいます。
なぜならオブジェクトの原点が中心にあるからですね。

3Dモデルには中心となる「**原点(ピボット)**」というものがあり、ギズモの表示されている部分がそのオブジェクトの原点で、そこを中心に回転したり大きさが変わったりします。
BlenderやUnrealEngineだと動かせるのですがUnityでは原点を動かす方法がいまいち分からないので、めんどくさいですがドアオブジェクトを親子関係にします。

まずCreateEmptyからParentとか名前を付けてその中にドアを入れます。
そして子にしたドアオブジェクトを左(-X方向)に少しずらします。
その上で**親のY軸**を回転させてみるとドアっぽい動きになるかなと思います。
スターターアセットの地面には目盛りがついているので加減がわかりやすいと思います。

![ezgif-1-310fb5d0bc.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562437/dfb4a073-aab4-1abf-f2fe-83cdf20d95c6.gif)

こんな感じでとりあえず動きは良さそうですね。
これを二つ扉にしたい場合はCtrl+Dで複製して鏡映しになるようZ方向に180度回転させて横並びにしましょう。

この動きをアニメーションにしていくわけですが、まずどこまで開くかの角度を覚えておきます。
今回は引いて開けるタイプで「Y軸を-120度」とします。

## ドアの開き方
ここで1つ考えたいのがドアの**開き方**です。
ゲームを制作するうえで世界観作りというのは非常に重要な要素です。

例えば「戦国時代や江戸時代など昔の日本を舞台にしたゲームを作ろう！」
ってなったとき、ドアとなるものは大抵は襖や障子ですよね。
昭和ごろの日本も、玄関は大抵引き戸で、ガラガラ開けるタイプが多いですよね。
つまりY軸の回転ではなく、X軸を移動するようなアニメーションを作成します。

「バイオハザードやグランドセフトオートみたいな海外が舞台のゲームを作ろう！」
ってなった場合、ちゃんと舞台設定に合ったドアを考えなければなりません。
それが何かというと、**内開き**か**外開き**かです。

日本は洋式ドアの場合、外に向かって開く場合がほとんどです。
玄関で靴を脱ぐという習慣があるので、中に向かって開くと靴が引っかかったりするので外開きになります。

一方海外では押して開けるのがほとんどです。
もし犯罪者が押しかけてきても全体重をドアにかければ抑え込むことができるからとか、防犯的な理由が多いです。
ホラー映画なんかでも、悪者やゾンビに追い込まれたとき必死に押さえつけたり、近くにある棚を倒したりして開かないようにしますよね。

もちろん日本にも防犯対策として、鍵だけではなく「チェーン」がついてますよね。
それで無理やり引っ張り開けられることを防ぐことができます。

このように国柄や時代でドアの開き方やドアについている鍵などに違いが出るので、その辺も考えてドアのアニメーションを作成するといいと思います。

## アニメーションを作成
それではアニメーションを作っていきます。
まずはAssets内にAnimetionフォルダを作っておきましょう。

そしたらドアの親要素を選択した状態で上部メニューのWindow→Animation→Animation(Ctrl+6)でAnimationファイルを作成します。
表示されたウィンドウの真ん中にある「Create」を押し、今作ったAnimationフォルダを保存先にしてファイル名はOpenとします。
![スクリーンショット 2024-03-28 120712.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562437/1d5739d1-2824-c82b-768c-53517e95029f.png)
すると何やら映像編集ソフトのタイムラインのようなものが出てきます
左上の**Add Property**から親要素のRotationを追加すると0と1：00のところに♦マークが打たれます。
それぞれのキーにRotationを設定してあげると、0：00から1：00に向かう間の動きを補完してくれます。

プロパティを追加したら右上の赤丸ボタンを押し、レコーディングを開始します。
上の秒数が書いてある部分をドラッグすると白い線を動かせるので1：00のところまで動かし、プロパティのRotation.Yを好みの角度に設定しエンターキーを押すと完成です。

![スクリーンショット 2024-03-28 123239.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562437/d0a9623b-130a-1905-855b-3f190690bc46.png)
今回は-135にしました。
アニメーションウィンドウの再生ボタンを押すとSceneやGame画面に動きが反映されます。

![ezgif-3-bc69126e15.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562437/74fd47cc-ee8d-90d2-5b34-bc3e1726327d.gif)
良い感じですね。

このアニメーションはOpenとし、あとは同じ要領でCloseと、何もしないIdleの3つのアニメーションを作ります。

アニメーションが作成出来たら、それをAnimatorという機能で制御します。
アニメーションファイルを作成すると自動的に生成されるので開きます

![スクリーンショット 2024-03-28 132201.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562437/43e49921-024b-e828-ee1d-c5a79cdae6f3.png)
こんなウィンドウが現れます。こいつでアニメーションを制御しています。
例えばWを押してるときはWalkアニメーションを再生し、その状態からShiftを押すとRunアニメーションに移動する。なんてのをこのステート同士を→で繋いで条件付けたりして制御するわけですね。

Animatorはプロジェクトを実行するとEntryからデフォルトステートというステートに向かいます。オレンジ色のやつですね。
これは変更することができるので、Idleを右クリックして**Set as Layer Default State**を設定します。
こうすることでIdleがデフォルトとなるのでドアが閉まった状態でスタートします。
あとはステートをダブルクリックしてインスペクターに表示されるLoop Timeのチェックを外したらとりあえずアニメーションの作成はOKです。

## おわり
次回はInput SystemとRaycastを使用し、Fキーでこれらのアニメーションを呼び出せるようスクリプトを書いていきたいと思います。