北条ゲームズ Hojo Games

錦の北条の開発ブログ

スポンサーサイト 

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

【Unity】ゲームに本当に必要な三人称視点なカメラの実装について【コラム】 

北条です。こんにちは。
Unityにおけるゲーム開発初心者向けの話題ですが、スケーリング可能なゲームシステムについてのとっかかりを得るためのコラムを書いてみようと思いました。社会貢献です。偉いなあ。

今回は簡単で現実的な話題として、三人称視点なカメラについてを書きます。
三人称視点のゲームは非常に多いでしょう。僕も今開発しているゲームはそうです。

さて、早速本題に。
結論をいきなり書いていくよりもインタラクティブに進めてみましょうか。簡単な質問をします。
三人称カメラの挙動をUnityにおけるC#として書くならどのような形が良いでしょうか。

・・・

簡単に思い浮かぶのは三人称視点カメラクラス:MonoBehaviourみたいなものを作って、入力をよしなに受け取り、カメラを動かすみたいな感じにして、そのコンポーネントをCameraのGameObjectにアタッチでしょうか。
何かそんな感じのものが昔StandardAssetsに入っていた気もしますしね。今もありますかね。(気のせいかも)


はい、ハッキリ言って最悪です。最悪ウンコです。ウンコ最悪です。

上の作法には特に二つの死んでほしい点があります。
まず一つは、MonoBehaviourに継承という最凶な密結合をやっている点です。
(this.)transform.positionをそのまま扱うとか、もう作法が完全に決まり切ってしまいますね。

まあ、三人称視点カメラでありCameraにくっつくのはそんなに問題ないじゃん!付ければいいんだし!という話があるかもしれませんが、この負債は次の二つ目の死んでほしい点に強く関連します。
あと、単純にMonoBehaviourは色々抱え込んでるので、要らないなら要らないで付けない方が当然パフォーマンス的にも操作対象の絞り込みの為にも普通にいいです。もちろん、今回のケースでは本来全く必要ないはずです。(本当にそのクラスは、MonoBehaviourのメンバに強く結びつく必要がありますか?生成方法と生成場所がメタに決まり切らないといけなくなる必要がありますか?……これはカメラに限らない話です。)

二つ目は、この手法では想定できる三人称視点への変更に神クラス的な対応が殆ど確定してしまう点です。
軸回転カメラみたいな概念が多分Componentとして誕生するんだと思いますが、恐らく三人称視点のカメラはそれで完結しません。
例えば特定のアクションを決めた時に特定の位置に行ってキマった感じに映したいとか、きちんとゲームを遊んでいれば要求として単なる軸回転なカメラでない機能、結構思い浮かんでくるかなと思います。
銃撃が発生する時にカメラにブレを加えたいといった、軸カメラとしての本質が一致しつつの拡張ならそのまま加えるのも一定問題はないのですが、座標が一気に変わって操作方法も変わるような「軸回転カメラ」としての本質を持たない状態が要求として来ると一気にきつくなるんです。

一旦、その拡張を無理やり加えたとしましょう。行ってほしい座標・角度を受け取るためのメソッドやら実際の処理やらが増えます。ほら見ろ、大丈夫じゃねえか!と叫んだのもつかの間、
今度はシームレスに他の管理手法を持ったカメラになりたい要求が現れます。いいですか、現れます。三人称視点カメラについて、とかテーマにしましたが、一つのカメラシステムでゲームが完結するのは稀なのです。残念!(他の管理手法を持ったカメラとは、例えばあるシーン・操作でシームレスにカメラが移動してFPS視点操作になってほしいとか、上から俯瞰した状態にシームレスに移動してメタに戦局を見るモードにするとか、そういう感じのものです。)
移動・定点になるレベルならまだ許容できたかもしれません。しかしここまでくると、それも複数の手法にもなると、付け加えていくスタイルではもうコードがめちゃくちゃです!最高!
このケースに陥った場合にその場を切り抜けるために即座に考えそうな別の現実的なアプローチは、そもそも別のものとして実装してシームレスなカメラ切り替えにするのは諦めつつ、パフォーマンスを多少犠牲にしてカメラ自体を切り替えるか、分離しつつも最初っからそれぞれの別の操作系のスクリプトをすべてつけておいて必要なものをEnableにするとか。
まあ、よくないですね。悲しいですね。誰もお前を愛さないですね。


では、どうすればよかったのか。
上で散々面倒くさそうなことを書きましたが、実は結論として今回出すアプローチは異常に簡単です。
カメラの操作に必要な情報を一つの概念にしちゃいましょう!

2017y02m19d_020152135.png 
上は一例ですが、カメラ遷移に必要な情報を一まとめにして構造体とかにしちゃうのです。
そして、カメラを操作するクラスは、現在のカメラの状況のこの値を貰って操作し、結果の値を出力するようにします。MonoBehaviourとは一切合切依存しない形になります。つまり、単なるC#クラスになるはずです。
複数のカメラの切り替え要求があった時は新しいカメラクラスにカメラ遷移情報を出力させ、なだらかに以前の状態と合成してうまくクロスさせるようにすれば良い訳です。(Lerp生やしてるのはそのためのものです)
この手法であればMonoBehaviourは管理の為の上層のみになり、カメラ自体のクラスは分離し非常に簡潔で再利用性の高い概念になるでしょう。

このように結論はとても簡単なのですが、導出がちょっと飛んでいるような気がしたので結局このコラムで何が伝えたかったのかって話なんですが、
MonoBehaviourの単位を概念の単位として捉えないでください!MonoBehaviourができる操作とあなたが欲した一つの概念が結びついてパフォーマンスや拡張性が死になってしまいます!
意図はできるだけ疎にする心がけをすれば何かあっても本当の求める形に柔軟に近づけやすくなるでしょう。
というような感じです。何かカメラ関係ないんですけど、カメラの話みたいな簡単なワードで釣ったんですけど、全般的にOOP適切にやろうってことですね。アーキテクチャお兄さんです。
簡単なお試しロジックなんかとしては単体で完結したMonoBehaviourなComponentの形がUnityとしては扱いやすいので正当性はあるんですが、長期的な開発では終わりを齎します。
MonoBehaviourとの付き合い方は公式にあまり明確には示されていないような気もするのですが、結構要注意です。十全なスケールの長期的ゲーム開発においてはあくまでC#な開発であることを意識してやっていきましょう。

雑ですが以上です。ではまた。

Comment

Name - がびこ人形  

Title - No title

記事の内容とすこしずれてしまうかもですが、MonoBehaviourを前提にしたコーディングは確かに微妙です。
挙がってない点で言えば、アプデでUnity関連のクラスの扱いが変わったり、もしくはエンジン自体を乗り換えたり、な場面を考えると、最悪すべてのコードが死にますゆえ。
となると、コアな処理ほど切り離し、MonoはUnityとの対話に専念してもらったほうがよいと思います。
2017.03.19 Sun 10:38
Edit | Reply |  

Name - 錦の北条  

Title - Re: No title

> 記事の内容とすこしずれてしまうかもですが、MonoBehaviourを前提にしたコーディングは確かに微妙です。
> 挙がってない点で言えば、アプデでUnity関連のクラスの扱いが変わったり、もしくはエンジン自体を乗り換えたり、な場面を考えると、最悪すべてのコードが死にますゆえ。
> となると、コアな処理ほど切り離し、MonoはUnityとの対話に専念してもらったほうがよいと思います。

正直この辺は殆どUnityの話では最早なく、物事を抽象化して扱うというごくごく当たり前の話ですね

ランタイムにおけるMono(CLI)は色々な対話をしていると思いますが(w)、確かにMonoBehaviourに関しては入り口の認識で、ただそれでも自分のワークフローのサイズで適切に決めていけるといいですね
僕はこんな記事を書くくらいなので完全にUnity感を外している場所もフロー全般で人並みに多いですが、それでも結構Unityの都合を利用していると自覚している方で、例えばキャラクターのルートが個々に一つだけ僕のMonoBehaviour継承スクリプトを持っていてそこから各キャラクターの人生が始まるようにしてます このあたりはワークフローまで含めた世界全体のOOPに対する認識の戦いだとは思っていて、Editorでのワークフローとの兼ね合いでそう取り決めてます。
まあ特定エンジンに部分的に捧げてしまう書き方があるのはよくないかもしれませんが、そう書いた部分が何のコンテキストで何をやっているのか適切に認識して、理解してさえいれば……という感じですかね
結局Unityをあくまで利用しているので、Unityが素晴らしいものを提供している箇所では出来る限り薄い結合でありながらも阿るような形状をやったほうがいいのは大概そうなので……ってか、そういう部分も普通に堅牢なコード書けって話でしかないかもしれないですね 普通に適切なコーディングやればいいと思います(雑な締め)

少ないリソースの個人レベルの開発では生産性と安全性のラインの取り決めは重要な要素になりますので、上手く考えながら進められるといいですね!
2017.03.19 Sun 19:20
Edit | Reply |  

Add your comment

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。