【Unity5】AC4系のようなカメラワークを再現する
目次
- 目次
- 前置き
- 何でまた今更こんな記事を?
- 注意事項
- ACって?
- 本物のカメラワークはどんなの?
- 1. 準備する
- 2. 照準用オブジェクトを回す
- 3. プレイヤーを回す
- 4. 照準を追従させる
- 5. カメラ追従オブジェクトを移動・回転させる
- 6. カメラを遅れて追従させる
- 7. カメラの注視点をずらす
- 8. 壁埋まりを防ぐ
- 9. 結論
- 10. おまけ
前置き
こちらの記事は Unity Advent Calendar 2016 の17日目記事です。
前回は野生の男さんの記事「Unity 5.4+のVR最適化機能Single Pass Stereo Renderingの使い方と注意点 - Qiita」でした。
何でまた今更こんな記事を?
「Unity カメラワーク」とかで検索すると、よく出てくるのは映画のような動きを作る方法や用語であったり、例えプレイヤーに追従する方のカメラワークでも、
- カメラをプレイヤーの子にする(位置、回転共に追従)
- カメラにプレイヤーの座標のみを与える(回転はしない)
- Leap関数等を使用して少し遅れて追従させる
が主な内容であると感じました。
その為、AC4系のカメラワークを分析して、上記に挙げた方法より少し工夫して何かの参考になればと思った次第です。
注意事項
この記事では説明しやすくするようかなり細かく処理ごとにコンポーネントを切っています。その為スクリプトの数がかなり多めになっています。適宜、処理をまとめた方がよいかもしれません。
また、この記事は「こうしたらそれっぽくなるんじゃね?」のアルゴリズム的な事を書いていくことを主としているので、スクリプトの中身について深く書くことはありませんのであらかじめご了承願います。
さらに、必ずしも述べる方法が正しいとは限らず、本家の方はもっと簡潔に実装が行われているはずだと思います。その点においても、「参考程度」に。
ACって?
株式会社FROMSOFTWARE様から発売されている「アーマードコア(ArmoredCore)」シリーズ、略してACと呼ばれます。
本物のカメラワークはどんなの?
「アーマードコア4(以下AC4)」「アーマードコア・フォーアンサー(以下ACfa)」にて用いられているカメラワークは、まるで背後から人が見ているような視点(TPS視点)で、かつプレイヤーの動きに遅れてきているような動きをします。
最近のゲームのTPS視点なゲームでのカメラは、プレイヤーの動きに遅れてきているような動きをする物が一般的になりつつあります(全てがそうだとは限りません)。
私の知っている中ではこのAC4系のゲームが特に顕著でスピードの速い機体だと画面外に機体が出てしまうこともしばしば。しかしその分スピード感を感じやすくもあります。
最終的にこんな感じなカメラの挙動を目指します。
1. 準備する
それではここから製作に入ります。
まず、計3つの分けられたオブジェクト群を用意します。
1. 照準用オブジェクトを準備する
[追加オブジェクト]
・照準回転用オブジェクト(空オブジェクト)
・メイン照準用オブジェクト(空オブジェクト)
・サブ照準用オブジェクト(空オブジェクト)
このオブジェクトらが、照準の位置を決めるものとなります。
ここで、メインがマウス操作する照準。サブが実際に弾等が飛んでいく照準という体で行きます。サブ照準が不必要だという場合は追加する必要はありません。
メイン照準用オブジェクトは、照準用回転オブジェクトの子にしましょう。これが実際に回転する際の基になります。
メインやサブの距離は任意ですが、プレイヤー(後で追加)、回転、メイン用のオブジェクトそれぞれは一直線になるようにしましょう(サブはメインに付いていくようにするので適当でOK)。絶対にプレイヤーの子にしてはいけません!
2. 照準用オブジェクトの追従先を準備する
[追加オブジェクト]
・追従用オブジェクト(空オブジェクト)
次に必要となるのは照準の回転用オブジェクトの追従先となるオブジェクトです。このオブジェクトが、全ての回転原点の目標座標になります。画像ではとりあえず頭の上あたりに設置しています。
これはプレイヤーの子にしてください。座標を調整するのを忘れずに。
用意する理由はというと、単に照準の回転用オブジェクトそのものをプレイヤーの子にしてしまうと、プレイヤーの回転と一緒に回ってしまうからです。
このオブジェクトの座標を追いかけるだけにしてあげれば、回転は気にしなくてよくなります。
プログラム側で直接座標を入力する方法等の解決法もありますが、それだと一回一回プレイして確認しなければならない上、数字情報が多くなって管理や理解が面倒になるので、個人的にはこちらの方が手間も省けて楽です。視覚的に追従位置を微調整出来ますし。
3. カメラ追従用オブジェクトを準備する
[追加オブジェクト]
・カメラ回転用オブジェクト(空オブジェクト)
・カメラ座標決定用オブジェクト(空オブジェクト)
「カメラ座標決定用オブジェクト」は「回転用オブジェクト」の子にしてください。この座標決定用オブジェクトが、カメラが実際に存在するべき座標を決定します。つまり、このオブジェクトを移動させれば、「後ろから見る視点」でも「左右に少しずれる視点」でも「狙い撃ちするときだけプレイヤー近づける挙動」でも動的に再現できるわけです。後、念のため何度も言いますが、回転用オブジェクトは絶対にプレイヤーの子にしてはいけません!
2. 照準用オブジェクトを回す
さて、オブジェクトの準備が整ったところで、実際に動かしていきます。
なお、以後はソースコードの表示を多用するため、埋め込みではなくリンクを貼って進めていきますのであらかじめご了承ください。
まず、照準用オブジェクトを回していきます。
下記スクリプトを作成してください。
【AimRotate.cs】
このスクリプトを「AimRotateOrigin」にアタッチすれば、マウスでMainAimオブジェクトを回転により動かせるようになるはずです。
また、Inspectorの「SubAimObj」にSubAimオブジェクトをアタッチすればSubAimがMainAimに遅れてくるようになります。
Inspectorの「Clamp Angle」で角度制限を変更することが可能です(初期値は60度)。
また、サブ照準をここで不必要だという事で追加していない場合はサブ照準の追従処理を削除してください。
3. プレイヤーを回す
次にプレイヤーを回転させます。
ここが従来のキャラクターの回転方法とは特に異なるところです。普通は、コントローラやマウスの入力による回転は直接プレイヤーオブジェクトに反映していましたが、今回の手法ではプレイヤーの回転は「MainAim」の方向を向くようにスクリプトで処理します。直接的ユーザー入力による回転を行う事はありません。
では、下記スクリプトを作成してください。
【PlayerRotate.cs】
このスクリプトを「Player」にアタッチすれば、プレイヤーオブジェクトがMainAimの方向に向かって遅れて回転しているはずです。
(下動画ではわかりやすくプレイヤーに鼻を付け、MainAimに球を、SubAimに箱を付けています)
またこのスクリプトでは回転軸の固定を行うことが出来るので、回転させたくない軸にチェックを入れればその軸は回転しなくなります。その為、照準は自由に動かしたいけど、プレイヤーオブジェクトは横回転(Y軸回転)のみ行わせたい時などに使えます。
(下動画ではX軸とZ軸にチェックを入れ、横方向の回転のみ行うようにしています)
4. 照準を追従させる
さて、このままではもちろん照準はその場から動きませんので、照準をプレイヤーに追従させるようにします。
【AimFollow.cs】
このスクリプトを「AimRotateOrigin」にアタッチしてやれば、照準の回転原点がプレイヤーの子になっている追従原点「FollowTarget」に追従するようになります。
ただ、そのままFollowTargetに追従すると、照準の回転原点が頭の上になってしまうので、offsetでFollowTargetからの相対位置を出し、FollowTargetからの相対位置を維持します。
5. カメラ追従オブジェクトを移動・回転させる
次に、カメラ追従オブジェクト(橙色)の処理を追加していきます。
横(Y軸)回転はプレイヤーの回転で賄うので、ここで回転させるのは縦(X軸)回転になります。
【CameraRotate.cs】
このスクリプトを「CameraRotateOrigin」にアタッチしましょう。
Inspectorの「Clamp Angle」で角度制限を変更することが可能です(初期値は60度)。
6. カメラを遅れて追従させる
次に、カメラの追従処理を追加していきます。
【CameraFollow.cs】
このスクリプトを「Main Camera」にアタッチしましょう。
これで、照準の回転やプレイヤーの移動によるカメラの挙動が確認できるかと思います。
移動や回転の速度はとりあえず3にしているだけなのでお好みで調整してください。個人的には移動:10, 回転:8が好みです。
7. カメラの注視点をずらす
ところで、AC4系カメラの特徴として、横にQB(クイックブースト、瞬間的な高速移動)した際、カメラは完全に正面を向かず、若干機体の方向を追うように向いています(4:39辺りの横へQB移動した時が特に分かりやすいかと)。
【参考動画】
ACfa テスト動画 ホワイトグリント戦(HARD) 720p 60fps
また、これもAC4系カメラの特徴として、横移動時「機体の横が見えます」。
どういうことかというと、機体は平行に向き、かつ移動しているにもかかわらず、カメラは機体の横っ腹が見えるような方向を向いています。かといって完全に機体の方向を見ているわけではないようです。
という事は、AC4系でのカメラにおける注視点は、プレイヤー正面方向ではなく別の場所であることが考えられます。
ではカメラはいったいどこを目標として見ているのか、以下の項目で検証してみました。
- プレイヤー正面方向にカメラを向け(初期位置・初期向き)、横移動
- プレイヤーより高い位置から見下ろし、横移動
- プレイヤーより低い位置から見上げ、横移動
以上の3項目の結果を検証してみたところ、どうやらカメラは機体の移動方向とは逆方向の位置を注視しているようでした。下図は予想。
これは私の予測ですが、カメラの回転軸とカメラ移動先は機体よりも遅れて、かつ、一定距離上は離れないようになっているのかもしれません。
【CameraOffset.cs】
このスクリプトを「CameraRotateOrigin」にアタッチしましょう。
ついでに、
【PlayerMove.cs】
こちらのスクリプトをプレイヤーオブジェクトにアタッチしましょう。
Rigidbodyの「Drag」は2にしておきます。
後はテラインで地面作って色々なスピードをいい感じに調節して...
こうなります。
WASDで移動。SPACEでQB。QT(クイックターン)は無し。
8. 壁埋まりを防ぐ
さて、このままだとカメラが地面に埋まってしまいます。
カメラが建物や地面に埋まって裏側が見えてしまうのはどうかと思うので、壁埋まりを防ぐ仕組みを作ります。
前に作ったCameraFollow.csを以下のように修正してください。
また、PlayerオブジェクトにPlayerレイヤーを割り当てることを忘れずに。
【CameraFollow.cs】
これで、障害物にカメラが埋まらなくなりました。
9. 結論
まぁ、今回のように少し凝ったことをするとなると多少なりとも工夫は必要ですが、単純に少しだけ遅れてくるだけで良いという場合は「Leapで遅れて追従させる」で事足ります。時間的コストも少ないですし。
10. おまけ
クリスマスに相手がいる人なんていませんよね?