読者です 読者をやめる 読者になる 読者になる

株式会社ネクスト エンジニアBlog

不動産・住宅情報サイト HOME'Sを運営する株式会社ネクストのエンジニアが提供する技術ブログです。エンジニアに役立つ情報の発信や、弊社エンジニアの活動を中心にお届けします。

Unity初心者が2ヶ月半でOculusRiftを使ったVR開発をした【実装困ったぞUnity編】

どうも上津原です。

今回は、実装時に初心者だから(だと思う)つまずいたポイントと、どう解決したかをUnity操作、Oculus Rift対応それぞれに分けて紹介していきたいと思います。

  • 教える立場の人は、完全初心者が3Dゲームに手を出すとどういうところにぶつかるのか?
  • これから始める人は、ぶつかる前にどこを押さえておけばいいのか?

それらの参考になれば嬉しいです。

では、Unity操作編、始まりです!

3Dゲームの基本

3Dゲームには、Z軸や重力、当たり判定、ライティング、カメラ…いろいろな要素が絡みます。

そんな中、盛大に転んだものを3つお伝えします。

オブジェクトが地面を通り抜けて落ちていく!

f:id:nextdeveloper:20140312183706j:plain

本をひと通り試した私は、ある程度もう知ってるもんね〜という心持ちでプロジェクトを作っていました。

そこで一番最初のつまづきがきました。

「この3Dモデル配置してRigitbodyで重力付きの物が作れるんでしょ?簡単簡単!」

そしてひたすら落下し続けるキャラクター!

アイエエエエ!ノラナイ!?ノラナイナンデ!?

地面にオブジェクトが乗らない!!!

読んだ本ではこんなことはなかったので、かなり頭を悩ませました。まさかこんな落とし穴があるとは(うまい!)

Unity内で生成したもの(CubeとかShpereとか)なら、予め当たり判定が付いているのでうまく動いていました。しかし、ただの3Dデータを外部から持ってきて配置したらコライダーがついていません。

モノの上に乗るには「コライダー」が必要。

そして当時私は、Rigitbodyをつけることが「ものに乗れる条件」だと思っていました。まぎれも無いバカです。

なので私は「どちらともにコライダーがなければものの上に乗らない」ということに気がついていなかったし、なのでそもそも「上に乗ること」を「衝突」だとも考えもしませんでした。

コライダー?メッシュ?シェーダー?なにそれ。

沢山出てくる専門用語。みんなアプリ開発では聞きもしませんでした。

「Unity すりぬける」でググった私が出会った言葉、それが「コライダー」でした。

「コライダー」と聞くと、ライダーの方に意識が取られて、ライダー?とか思ってました。

そして「コライダーとは」でググッた結果、それが「あたり判定」だと知りました。普段ゲームをやるにあたって「あたり判定」という言葉は馴染みがあったので、この言葉を知ってやっとピンときました。

どうやら2つのオブジェクトお互いにコライダーがないと、ものには乗れないらしい。それを知り実践し「なるほど、コライダー」とやっと理解したのでした。

ほかにも、メッシュって?シェーダーって?レンダラー?トランスフォーム??それぞれの専門用語を一個一個調べ、何なのかを理解していきました。

代表的な専門用語は、予め調べておく

  • コライダー
  • メッシュ
  • シェーダー
  • レンダラー
  • トランスフォーム

解説記事にもついていけなくなるのでせめて上記のこれらくらいは把握していたほうがいいと思います。

画像検索で出てくるようなライティングが出来ません!

検索して出てくる、Unityで出来たゲーム画面画像を見ては「これ、俺の持ってるUnityと違う…」状態でした。

ライトを配置し影を描画してもダサイ感じ…。「Proの無料体験版だから、じつは機能制限されてるとか!?」「特殊なプラグイン買わないと出来ないとかじゃないの?」とも考えました。

理想

f:id:nextdeveloper:20140312183438j:plain

現実

f:id:nextdeveloper:20140312183448j:plain

(画像:Unity Manualより)

そこで出た答えが「Lightmapping

ライトマッピングはまだ全然把握できていないし、使いこなせていないのでここでは偉そうなことは書けませんが、Lightmappingを利用することでやわらかな影の描写や、動作を軽くすることなどが実現できるようになりました。

コード

iOSのアプリ開発をやっている中、考えもしない要素がコードにも山積みです。そもそもコードはどういう立場にいるのか?コードでしか出来ないことは?

4つのつまづきポイントを紹介します。

UnityScriptイコールJavaScriptではない!?

そして、舞台はコード実装へ。

UnityはJavaScriptで開発できるんだよ!すごいでしょ!という触れ込みと、最初に読んだ本のコードがJavaScriptだった事もあり、それを使って開発を進めていくとすぐに気が付きました。

「これ、俺が知ってるJavaScriptと違う…。」(またかよ)

「型宣言もしなくちゃいけないし、WebのJavaScriptで使ってた関数を使えない時あるし、そういえば俺、そもそも知ってたのjQueryだわ。

UnityScriptはUnityScript

JavaScriptちょっとかじってたしなんとかなるだろ、と思って安易にJavaScriptを選んだけど、結局はきちんとUnityScriptとしてJavaScriptを覚え直す事になりました。

僕は本当にかじった程度だったのでもっとちゃんと知っている人ならばそうではないのかもしれませんが、僕にとっては違うものに感じました。

遠隔にあるものを認識するには?

ものの持ち上げ判定を得るために、視線の先に対象のものがあるのかを確認する必要がありました。 そこで必要になるのが「Ray」です。

どこのページを見ても「Rayというのは、見えないレーザーみたいなものです」という説明があり「レーザー?レーザー????なんでレーザーなの?」とか考えていました。

しかし動かしてみるとピンときました。設定した長さの棒をだして、それに当たったものを認識するんだな?見えないコリジョンだな?そうなんだな?と。

Rayは見えない物体認識棒

Rayという名前ゆえに「レーザー」と言われるのだと思いますが、僕は「棒」と思ったほうが現実味が合ってしっくりしました。そうして、遠隔のものを認識する、という術を手に入れました。

他オブジェクト内のPublicな変数はどうやって取り出すんだ??

コードを書いていくと、当然この問題にぶつかります。

例えば、Objctive-Cのコードでは、別クラスのPublicな値を手に入れるには

EXObject exObject = [オブジェクト呼び出し];
BOOL flag = exObject.flag;

というふうに書けばいいのですが、これはUnityだしUnityScript。当然同じように書いてみても取れません。

そもそも「オブジェクトにスクリプトを配置する」という行為自体に理解が追いついていないのです。某書籍では、「static publicにしてアクセスすればいいんだよ」という風に書いてあったけど、それだと明らかに柔軟性に欠ける。なにかいい方法はないのか。

GameObject go = GameObject.Find(“exObject “);
EXScript exScript = go.GetCompornent(EXScript);
bool flag = exScript.flag;

となる事を知る。

スクリプトはいちコンポーネント扱い

アプリ開発をしている時、コードこそが本体だった自分としては、コンポーネントの1つとしてScriptがある、という考えにいまいち至らずこの方法を知るまで、static publicで頑張ったり、1つのコードのまとめちゃったりなどをやっていました。

今考えれば馬鹿なことをしていたなあ…。

JavaScriptから、C#のコードにアクセスできるの?

結論から言うと、出来なくないらしいけど僕は出来ませんでした!

とある人曰く「Pluginsフォルダを作ってそこに入れれば、アクセスできるよ」という情報をもらいました。

しかし、やってみるとコンソールで赤が出まくり、「あーもうやだ!アクセスする部分はC#で書くわ!」となりました。

その結果、JavaScriptとC#が混同するプロジェクトとなってしまったのがとても残念です…。

現状のものはデモなので、きちんとしたものを作る場合はC#で統一しよう、と固く心に誓っています。

壁はあれども、使いやすいUnity

まだまだたくさんあるのですが、強く覚えているものは以上です。

知識のなさゆえにぶつかることも沢山ありますが、Unityは使いやすく、作ってゆくのが楽しい開発環境です。

この僕の転んだ例を見て、スムーズな滑り出しができることを祈ります。