VR、ゲーム制作、プログラミング。Unity とか Oculus Rift とか。

2014年11月25日火曜日

[Unity]OculusSDK 0.4.3 メモ

OculusSDK 0.4.2 -> 0.4.3 (0.4.3.1) で結構大きな変更があったので情報を集めているところです。

週末のOcuJamに向けて重い腰を上げて 0.4.3.1 (Unity) を試しはじめたところで、まだドキュメントも読んでいません…

以下、いつも以上にひどい内容でお送りします。

とりいそぎ追加でこれを (2014/11/29)

API とか


  • OVRCameraController -> OVRCameraRig
    • 右目/左目が RightEyeAnchor/LeftEyeAnchor に変更
      • NearClip は各カメラの値がそのまま使われる
    • オーディオリスナが右目から中心 (CenterEyeAnchor) に移動
    • FollowOrientation がなくなり、標準で親に追従するように
      • オフにする場合は多分親の回転を無視するか親なしで移動だけ追従させる処理を Update/LateUpdate/OnPreRender のどれかあたりでやって、TimeWarp をどうにかする感じになる気がします
      • Follow Orientation in SDK 0.4.3 | Unity Integration | Oculus VR Forums (途中までしか読んでいないです)
    • Texture 関連
      • Scale は粗くすると画質とトレードオフでパフォーマンス稼げるみたいな話だったような…
      • Eye Texture のほうは調べないと…
  • OVRPlayerController
    • NeckPosition がなくなった気がします
    • あまり使っていないので調べていません…

パフォーマンス

まだ情報集まっていませんすみません。

TimeWarp + Extended が良くないとか Mirror + Direct が良くないみたいなのを見かける気がします。

互換性

まだ(略)

古い SDK でビルドしたソフトが動かないみたいな話がありますが 0.4.2 製は OK で 0.4.1 製は NG みたいなのを見かけたような気がします。Unity 4.5 製か Unity 5 Beta 製か純 C++ 製か、みたいな話もあるようですがよくわかりません…。

Unity 4.5.2f1 + SDK 0.4.1 でビルドした拙作は DX9 + Extended で動いているようなのですが…。

Game ビューの表示

OVRCameraRig を使たっときに Game ビューにカメラの内容が出なくなりました。

原因はカメラの FOV が 0 になっていること(実行時に調整される)なので、適当にいじってしまえば表示されます。



左右の Field of View を 105 - 110 くらいに、左の Viewport Rect の W を 0.5 に、右の Viewport Rect の X と W を 0.5 にするといい感じです。
いずれも実行時に修正される部分なので大丈夫だと思います。

参考


2014年10月26日日曜日

[Unity]OculusDK2 ポジトラでモデルを動かしたかった話

以前の OculusRift 勉強会 OcuBen で発表したスライドです。

どちらかというと Unity のアニメーションブレンディングの話です。


2014年10月25日土曜日

[Unity]uVRAudio:OculusRift用オーディオリスナ

uVRAudio は Unity で OculusRift コンテンツを作る際のオーディオリスナの設定を調整するためのスクリプトです。

主にヘッドセットではなくスピーカーを使う場合に、トラッキングによる移動や回転をしないようにします。

詳細はこちらのスライドをご確認ください。

ダウンロード

uVRAudio v0.9.1 for SDK 0.4.3.1 (2014/11/29)
uVRAudio v0.9.0 for SDK 0.4.2 (2014/10/25)

使い方 (v0.9.1 for SDK 0.4.3.1)

  1. SDK 0.4.3.1 インポート済みプロジェクトに対して、uVRAudio の unitypackage をインポート
  2. uVRAudioListener を OVRCameraRig にアタッチ
  3. ヘッドフォンなら isHeadphone を true に、スピーカーなら false に
    1. (ヘッドフォンのみなら使う意味はもうないです)
  4. forwardDirection はおまけです。通常使わなくてよいです

Examples のデモについて
  • (見るほどのものではないです)
  • 音がまだ入っていませんすみません。止まってるオブジェクトや動いてるオブジェクトに適当につけてください
  • オーディオとは無関係ですが、DemoManager はプロジェクト初期に放り込んでおくとさんじゅうびょうくらい浮くかもしれません

使い方 (v0.9.0 for SDK 0.4.2)

  • uVRAudioListener を OVRCameraController にアタッチ
  • ヘッドフォンなら isHeadphone を true に、スピーカーなら false に
  • OVRDevice.ResetOrientation() の代わりに uVRAudioListener の ResetOrientaion() を呼ぶ
    • スピーカーの場合は正しい向きを向いてから呼ぶ

補足 (v0.9.0 for SDK 0.4.2)

  • 標準だとオーディオリスナは右目の位置なのを顔の中心に
  • オーディオリスナはの位置を調整したいなら earPosition を使う
  • NeckPosition, FollowOrientation, TrackerRotateY の変更にもだいたい対応
    • 一部例外があります。FollowOrientaion せずに OVRCameraController を X or Z 軸回転など
  • SDK 0.4.2 で確認しています。0.4.3 は試していません 以下 v0.9.1 で対応
    • OVRCameraController -> OVRCameraRig の変更に対応していません
    • オーディオリスナは標準で顔の中心になりました(CenterEyeAnchor)
    • FollowOrientation はなくなりました。親の回転に常に追従します
    • NeckPosition はどこかに行ったようです


2014/10/26 : スライドを追加、説明を追加
2014/11/25 : SDK 0.4.3 について少し追記
2014/11/29 : SDK 0.4.3.1 対応版 uVRAudio 0.9.1 公開
2015/6/3 : 補足を一部修正

2014年8月11日月曜日

[OculusRIft]DK2でUnityが落ちる問題の対処法

OculusRift DK2 の SDK 0.4.0 と Unity で開発時に、"too many threads" というダイアログが出て Unity が落ちてしまう問題の対処法です。


結論としては DK2 を Extend モードにしてメインディスプレイにすることになります。

ウィンドウが DK2 側に行ってしまい不便ですが、この情報で少し幸せになれました。

Game ビューを DK2 で見る場合は、Game ビューを分離して DK2 側に持って行ってがんばって右上の最大化ボタンを押します。fps があまり出ないのと、ウィンドウ枠の分多少表示がずれているかもしれませんが一応見られます。



以下補足です。

私の環境
  • GALLERIA QF870HE, Windows 8.1, 64bit
    • NVIDIA GeForce GTX 870M + Intel HD Graphics 4600
      • Optimus はグローバル設定で「高パフォーマンス NVIDIA プロセッサ」
      • ビデオカードのドライバは最新(NVIDIA : 340.52, Intal : 15.33.22.64.3621)
  • Unity 4.5.2f1
  • Direct HMD Access from Apps モードは全く映らない

現象
  • Unity エディタで Oculus の SDK を使うシーンを開いて Play する、または開くだけでも、数秒で "too many threads" というダイアログが出て、OK を押すと Unity が終了する

試したこと
  • Direct モード : NG (映らないし落ちる)
  • DX11 : 落ちないが Game ビューにも映らない
  • Unity の Quality Settings で VSync をオフ : NG
  • OculusConfigUtil 終了 : NG
  • OVRService_x64 終了 : NG (Play するとサービスが復活する?)
  • DK2 を接続しない : 落ちない

その他

  • Unity 起動中に Direct と Extend を切り替えるのは Unity が固まったりするのでおすすめしません

参考


まとめ

  • やっと DK2 のコンテンツ開発に進めるぞ…!

2014年7月4日金曜日

[OculusRift]素人がVRソフトを展示しながら考えた、没入体験中の説明のしかたについて

OculusRift をはじめとするヘッドマウントディスプレイを使った体験の操作方法等を説明するとき、体験者には画面以外の現実世界が見えないことによる難しさがあります。

さらに、ヘッドフォンを併用する場合には外の音声も聞こえづらくなるため、より難しさが上がります。

また、より高い没入感を実現するためには、コンテンツ内容に合った形での説明が望ましいと考えられます。

本記事では、このように視覚、聴覚に制約のある中で、没入感を損なわない説明のしかたについて思うところを書いていきます。

筆者について

素人です。

OculusRift の体験会 Ocufes で何度かコンテンツを展示し、百名以上の方に目の前で体験いただきました。本記事はほぼこの経験によってのみ書かれたもので、専門的な知識は含まれません。

筆者のコンテンツについて

少し宣伝になってしまいますが、具体例として使うために説明させてください。

見習い空賊と天空の少女 という、映画のような世界で主人公の少年になって少女を救出しに行くフライトアトラクションです。


体験者は OculusRift とヘッドフォンを装着し、背もたれのない椅子に座ります。

VR 空間の中では、体験者は飛行機の後部座席に座っており、序盤~中盤は船長の操縦により少女のいる塔を目指すフライトを体験します(下図左)。

終盤では、少女をキャッチするために上図のような姿勢を体験者が実際にとる必要があり、半回転して後ろを向いた上で足の間から前を見るような動作を行います(下図右)。


操作および操作説明に関係する点をまとめると以下になります。

  • OculusRift 体験が初めての方を主に想定
    • 操作は少なくし、マウス、キーボード等の入力デバイスは使わない
    • 飛行機の操縦も自動で、進行に必要な操作は終盤の姿勢変更のみ
    • おまけとして、特定の場所を注視するとリアクションが返る
  • 展示等で説明員がいる状況を想定
    • ただし、操作説明的には個人でもプレイ可能なものを目指している
    • 展示に限っているのは周辺機材が特殊なことと、お借りした MMD モデル/ステージの都合、またオマージュ色が濃い内容のため
  • 座ってのプレイを想定
    • 現実の姿勢と一致していた方が没入感が高く、説明もしやすい
  • ヘッドフォンの利用を想定
    • より没入感を高めるため
    • コンテンツ内の音声による説明をより聞き取りやすくするため

プレイ形態について

説明のしかたについて考える前に、前提条件を検討します。

まず、コンテンツがどのような状況でプレイされるかを、説明員がいる状況でのデモと、ダウンロード配布等で個人でプレイする場合に大別することにします。

説明員ありのデモの場合、事前またはリアルタイムでの口頭説明が可能ですが、人数を回転させる必要がある場合が多く、一人ひとりの説明やプレイそのものに割ける時間は短くなりがちです。

個人でプレイする場合はそうした説明は当然不可能ですが、マニュアルを読んだりトライ&エラーをする時間はもう少し長くとれます(飽きられなければ)。

スピーカーかヘッドフォンか

音を出すのにスピーカーを使うかヘッドフォンを使うかについて考えます。

ヘッドフォンをつけると説明員の声が届きにくくなります。特にBGMなどで常時音を出す場合は、体験中のリアルタイムな説明は難しくなります。

しかし、コンテンツ内の音はよく聞こえる上に、周囲の喧騒もカットできるため、より没入感の高い体験を提供できると考えられます。

スピーカーを使うメリットとしては、観客にも音が聞こえる点が挙げられます。また、コンテンツによっては観客の反応をあえて体験者に届けたい、体験の一部として使いたいこともあるでしょう。

ただしスピーカーの場合、体験者が首を回したときに音のステレオ位置が合わなくなるのを避けるため、あらかじめコンテンツ側で工夫が必要です。例えば Unity であれば、AudioListener がカメラに追従して回転しないようにします。

オーディオ出力を分岐してヘッドフォンとスピーカーを併用することも考えられますが、上記した音の位置のずれは注意しておいたほうがよいでしょう。

入力デバイスと操作系について

VR 体験中に体験者が何かをする場合、入力デバイスが必要になります。

個別に解説すると記事の範囲を超えてしまうので簡単にですが、以下のようなものがあります。

  • マウスやキーボード、ゲームパッドなどの一般的なデバイス
  • より VR に適した入力デバイス
    • 空中で手のジェスチャを認識できる Leap Motion
    • 手に握ったデバイスの角度と位置を取得できる Razer Hydra (販売終了?) や STEM System (発売予定)
    • 全方位ルームランナーのような Virtuix Omni (発売予定)
    • グローブ型デバイス Control VR (Kicksterter で資金調達成功)
  • 既存の直感入力デバイス流用
    • Kinect、Wii リモコン、PlayStation Move などのゲーム用デバイス
    • スマートフォン、マイク+音声認識、カメラ+画像認識など
  • OculusRift を入力デバイスとして利用するアプローチ

マウスやキーボード、ゲームパッド等のデバイスには、手元が見えないという問題があります。ゲーム等のように画面内にボタン配置の画像を出しても、実際のデバイスが見えない状態では画像と見比べることができません。

こうしたデバイスを利用する場合は、使うボタンを絞って指の配置を変えずに操作できるようにするとよいでしょう。しかし、こうしたデバイスにもプレイ環境を揃えやすいというメリットがあります。

より直感的な入力方法を採用することは没入感の向上につながりますが、それでも大抵の体験者はそうした入力方法に慣れていないので、少なからず説明が必要になります。むしろ、こうした操作系はまだ一般化されていなかったり、技術的な制約があることが理解されていないことで、直感的でありつつも「ボタンを押してください」以上の説明が必要になりがちです。体験者は自分の体が見えていないためか、正確な運動ができないことがあることも覚えておくとよいかもしれません。

(中には一瞬で理解できるものもあります。視線や傾きだけで操作するものは比較的わかりやすいものが多い印象があります。何ができるか体験前でも一目でわかるミクミク握手もデザインが優れていますね。)

こうした入力方法は説明自体にも工夫が必要で、体験者の様子を見つつ「もっと素早く首を振ってください」といった説明の仕方や、場合によっては手を添えて体勢を誘導するような方法が有効であることも多くあります。この点は、説明員なしでプレイする場合や、リアルタイムにコンテンツ外部からの説明が難しい場合には課題となります。

もっとも操作説明が簡単なのは、操作を必要としないことです。逆説的ですが、少なくとも HMD が一般化していない現時点では、見るだけのコンテンツも十分なインパクトを持つことができます。OculusRift 入門ソフトとして不動の地位を築いているジェットコースター体験、RiftCoaster がその最たる例でしょう。

見るだけといっても、体験中にどこを見ていたかでそれぞれの体験者は自分だけの体験をすることができます。なお、視線によって対象物がリアクション(キャラクターが見つめ返す等)する場合、現状はアイトラッキングがないため横目で見ていることを検出できないという課題があります。

なお、これらを複数組み合わせることももちろん可能ですが、操作できることが増えると説明が多くなり難しくなるので、特に短時間の体験向けであれば絞ることも大切です。

コンテンツ内での説明

前置きが長くなりました。ここまでの条件とコンテンツの内容で、実際に何について説明が必要かが決まってくると思います。

マニュアルや説明員によって説明する方法もありますが、なるべくならマニュアルは読まずにすぐプレイしたいと思うものですし、事前の説明はイベント等では回転率を下げる要因となり、体験中の外部からの説明は没入感を損ないます。

そこで、まずは可能な限りコンテンツ内で説明を行うことを考えます。

方法はいろいろと考えられますが、いずれの方法でも気をつけたいのは、没入感を損なわないためになるべくVR 空間での視界と、世界観に合った説明をするということです。

このあたりの話題はゲームの操作説明と重なる部分が大いにあって、例えばキャラクターにぶしつけに A ボタンと発言させるかわりにちょっと言い回しを工夫したり、システム的な内容は字幕で出したりといったものです。

特に VR コンテンツではこうした点はより配慮したいところで、画面に文字や情報を出すにしても例えば SF 作品ならそれらしい HUD や電光掲示板に出すとか、ファンタジーなら看板や魔法っぽいビジョンに映すなどとするとよさそうですし、注目してほしい方向に矢印を出すかわりにエフェクトや音で注意を引くとよいですし、キャラクターが話すときはテキストボックスは出さずに音声で話すべきです(もちろん、声が文字で見える拡張空間にいるといった設定なら話は別です)。

説明を出すタイミングも、体験者の状況を推察して適切に出せると効果的です。

見習い空賊~の例になりますが、終盤のシーンではまず概要として「機体の後ろから身を乗り出して、体験者が少女をつかむ」ということを船長が音声で伝えたあと、後ろを向く指示をします。OculusRift の角度だけでは体の向きはわからず、実際には首をひねっている方が多く見られたため、体ごと向くように念を押しつつ、後ろを向いていなかったら説明を繰り返したり、角度が少し足りないだけならもう少し右などとセリフを変えたりして、段階を追って説明しています。

なお、視界や世界観に合わせた説明は、ある程度以上のところはわかりやすさとのトレードオフになるため、場合によっては割り切る判断も必要かもしれません。その場合、一定時間以上操作に成功していないようなら世界観から外れた説明も行ったり、チュートリアルシーンを用意して本編には説明を持ち込まないというのも選択肢に入ると思います。

また、コンテンツ内での説明の実装コストは軽視できないため、現実的にはこれも考慮に入れる必要があります。

コンテンツ外での説明

コンテンツ内での説明がどうしても難しい、あるいはコスト上の問題で説明を実装できない場合、コンテンツ外での説明が必要になってきます。

個人でダウンロードしてプレイする場合はマニュアルやビデオになりますが、これについてはあまり知識がないことと、一般的な情報として探せば見つかりそうな内容ですのでここでは書きません。

説明員が説明する場合については、事前説明であればあまり世界観に配慮しなくてもよく、体験中の説明は世界観に配慮するか、そもそもしないことが望ましいと思います。

ただし、事前説明はイベント等で人数を回転させる場合にはネックになります。また、操作を事前に説明することによってそれが強く意識されてしまい、その操作ができそうに見える別のシーンでもそれ(ばかり)が実行されてしまう可能性があります。

見習い空賊~の例ですが、終盤でとる姿勢について事前に説明すると、音声での指示がなくても途中で姿勢をとってしまう方が数名みられました。

直接の説明のほかに、イベント等で列がある状況なら、並んでいる方に簡単な資料を渡しておく手も考えられます。また、並んでいる間に体験している方や画面を見ることで、多少雰囲気がつかめるということはあるかもしれません。この効果を狙うなら音はスピーカーから出した方がよいですが、ネタバレしてしまう欠点もあります。

なお、そうそうないとは思いますが、体験中にヘッドマウントディスプレイを外すと、継続プレイが困難なほどにものすごく醒めてしまいます。説明のしかたとは少しずれますが、とあるホラーゲームをびくびくしながらプレイしている最中に、どうしても攻略方法がわからず検索するためにヘッドマウントディスプレイを外したとき、怖さがなくなってしまいやめてしまったことがあります。途中でマニュアルを見るようなつくりは避けたほうがよいでしょう。

(完全に余談ですが、長時間プレイする作品やゲーム外のデータベースが実質必要になるような作品がこれから出てくる際には、安全にヘッドマウントディスプレイを外せるフェードのような表現や、コンテンツ内ブラウザが重要になると思います。そのころには、それでマニュアルを見る選択肢も出てくるかもしれません。)

コンテンツ内外での複合的な説明

ここまででほとんどの内容を書いてきましたが、最後に、コンテンツ内と外の連携をはかる案をいくつか書きたいと思います。

ひとつは、説明員の声や動作をコンテンツとして取り入れる方法です。説明員の操作によって動くオブジェクトや、声をマイクで拾ってヘッドフォンから再生するなどが考えられます。この場合、説明員のアバターとなる NPC を用意しておいたり、電話がかかってくる演出を入れることで違和感を減らせるかもしれません(ヘッドフォン越しに叫ぶのと比べて随分コストがかかるのが難点です)。

事前の説明を、コンテンツの一部のように演出する方法も考えられます。テーマパークのアトラクションの待ち時間や説明時のやり方です。

VR 空間内と現実を合わせることで、状況の理解を早める手もありかもしれません。Ovrvision で現実のコントローラーや姿勢を見せてしまうとか、VR 空間内がコクピットであれば現実側にもそのような装飾を施しておくとか、最近の例ですと現実と同じソファが VR 空間内にもあることでスムーズに入り込めるエクストリームソファのような取り組みもありました。

これらは単に説明のためとして見るには大掛かりですが、うまく使えば体験自体をよりおもしろくできる可能性があると思います。

おわりに

長文にお付き合いいただきありがとうございました。

なんだかすごく考えてる風に書きましたが、見習い空賊と天空の少女の終盤の姿勢をコンテンツ内の説明だけで正しくできる方はまだ半分くらいで、それ以外の方には外からサポートをしている状況です。

今後の改良のためにもと思い、一度まとめてみることにしました。何かのお役に立てば思います。

2014年5月25日日曜日

[OculusRift]見習い空賊と天空の少女

「見習い空賊と天空の少女」は、映画のような世界で主人公の少年になって少女を救出しに行く没入型フライトアトラクションです。

ゴーグルに見立てた最新のヘッドマウントディスプレイ OculusRift を身に付け、子供の頃に誰もが一度は憧れた映画のように、飛行機に乗り込み少女の待つ塔へと向かいます。

クライマックスで少女を助け出すには、飛行機の後ろから身を乗り出す「あの姿勢」をリアルでも取らなくてはいけません。あなたは、無事に彼女を助け出すことができるでしょうか?

ギャラリー

(モバイル表示 / YouTube) ※ネタバレあり

体験者の様子 ※ネタバレ控え目、旧バージョン、HMD 同期ズレは別撮りのため

「4 秒で支度しな!」

風を切って進みます

「…どこ見てるんだい」

「パズお!」「シーたん!」

プレイ時間はたった 2 分ほどですが、テーマパークのストーリーライドのような展開にインタラクション性をプラスした本作で、これまでにないアトラクション体験をお楽しみいただけるのではないかと思います。

出展情報


メディア情報


クレジット

モデル
(MMD モデル/ステージついては、各作者氏にメールにて利用許可を頂いております)

BGM
  • 希望~Esperance, 遠い空 (ZIADARA / DAIZ 氏)
  • 女性が舞うような感じの戦 (Ferne Welt / Piro 氏)

SE

ツール

アセット


2014/06/09 : 出展情報更新、メディア情報更新、クレジット追加
2014/10/10 : 出展情報更新
2014/10/24 : 動画を追加
2015/6/3 : ギャラリー、出展情報、クレジットを最新版に合わせて更新

2014年5月21日水曜日

[Unity]iTweenでのパス移動を使う前に知っておいた方がいいこと

Unity で位置や回転などを簡単にアニメーションさせることができるアセット iTween はよく知られています。

iTween ではパスに沿っての移動もできるのですが、ハードに使うにはあまり向いていない面もあるので事前に知っておくといいかもしれません。

良い点
  • そこそこいい感じにポイント間のカーブを描いてくれる
    • ただし接線は編集できないので、完全に意図通りにするのは難しい
  • easing オプションがけっこう豊富
  • 進行方向に向くように回転するオプション orienttopath がある


困った点
  • 速度の調整が非常に困難
    • speed または time パラメータがあるものの、ポイント間の直線距離に依存する=2点間は近いが生成されたカーブは長い場合に意図通りにならない(ただしうろ覚えです)
    • パス移動中に変更できない
  • カーブの接線が変更できないため、一度カーブした後に特に完全な直線を作るのは難しい
    • 前後 2 点までしか影響を受けないようなので、一応点を増やせば直線を作れるが、その前後がふくらんだりする問題の調整に追われる
  • 複数のパスを滑らかに接続するのが非常に困難
    • movetopath オプションを使えば線はつながるが、滑らかなカーブにはならない
  • すでに終了している Tween に対して iTween.Stop() すると例外が発生することがある
    • onComplete を使ってフラグ管理できなくもないが面倒
    • とりあえず try-catch しておけばスクリプトの停止は避けられる
  • iTweenPath でパスはエディタ上で編集できるが、あとで調整はしにくい

上記を知った上でツールの選択をされるのがよいと思います。

2014年5月18日日曜日

[Unity]uState : スクリプトベースのステートマシン

uState は Unity 用のスクリプトベースなステートマシンです。

ダウンロード

uState v0.9.1

過去のバージョン
uState v0.9.0

概要

スクリプトの記述を前提としたステートマシンです。


  • 基本 1 ステート 1 ファイル。100% スクリプトだけでも記述可能
  • パラメータ、遷移条件、各状態での動作などは自由に記述可能
  • 継承による一部改変が容易
といった色気のなさを特徴としています。

使い方 - はじめに

以下、慣れないうちは Examples/00_Common/Scripts にある TemplateStateMachine.csTemplateState.cs をコピーして編集するのがおすすめです。

また、ある程度 C# スクリプトを書くことに慣れた方であれば、これらのファイルやパッケージ内のサンプルを眺めながら以下の説明を読んでいただいた方が理解が早いかもしれません。

使い方 - ステートマシンとステートの作成

ステートマシン作成
  1. 新しい C# スクリプトを作成し、uStateMachine を継承する
    public class MyStateMachine : uStateMachine
    
  2. 作成したスクリプトを適当なオブジェクトに追加する
ステート作成
  1. まず、後の利便性のため、ベースとなるスクリプトを作成しておく
    1. 新しい C# スクリプトを作成し、uStateGeneric<MyStateMachine> を継承する
      public abstract class MyStateBase : uStateGeneric<MyStateMachine>
  2. 実際に利用するステートを作成する
    1. 新しい C# スクリプトを作成し、MyStateBase を継承する
      public class MyState1 : MyStateBase
    2. MyStateMachine を追加したオブジェクトに子オブジェクトを作成し、MyState1 を追加する
    3. インスペクタなどから、MyState1 の State Name を適宜設定する
初期ステートの設定
  1. MyStateMachine の Default State Name を、さきほど設定した MyState1 の State Name にする
これで、状態が 1 つだけで何もしないステートマシンができました。

使い方 - 動作の記述

各ステートでの動作は、以下のメソッドに記述します。
  • OnStateUpdate : 状態遷移判定の前
  • OnStateEnter : ステートに遷移した直後
  • OnStateExit : ステートから遷移する直前
  • OnStateStay : そのステートである間、Update ごとに呼び出される

使い方 - ステートマシンのパラメータ

ステートマシン全体のパラメータは、ステートマシンのスクリプトに public 変数などで通常の MonoBehaviour と同様に記述します。

各ステートではステートマシンに stateMachine フィールドでアクセスできます。

使い方 - 状態遷移

指定時間で遷移する方法と、bool を返す関数の結果で遷移する方法があります。

時間で遷移する場合は、ステートの Exit By Time に時間と遷移先状態名を指定してください。

関数の結果で遷移する場合は、以下のような関数をステートに用意しておき、ステートの Transitions の配列サイズを変更、関数名と遷移先状態名を指定してください。関数は public である必要があり、true が返ったときに遷移します。引数は取れません。

public bool IsParam1Large ()
{
    return stateMachine.param1 > 10; // true for transition and false for not
}

遷移関数は配列の若い番号のものほど優先されます。

使い方 - ステートの初期化をスクリプトだけで行う

ステートの各パラメータはインスペクタからも設定できますが、スクリプトに書いてしまった方が管理が楽になる面もあります。

Monobehaviour の Reset 関数に記述する方法がおすすめです。

using System.Linq; // for Concat()

protected override void Reset ()
{
    base.Reset();

    stateName = "State1";
    exitByTime = new ExitByTime(1.0f, "State2");
    transitions = (new Transition[] {
        new Transition("IsToState3", "State3"),
        new Transition("IsToState4", "State4")
    }).Concat(transitions).ToArray();
}

使い方 - ステートマシンの初期化をスクリプトだけで行う

ステートの生成を含め、全ての初期化をスクリプトで書くことも可能です。

こちらも Monobehaviour の Reset 関数で、パラメータの初期化やステートの生成を行います。

ステートの生成については、利便性のために DestroyAllStates() と CreateStates() が用意されています。

protected override void Reset ()
{
    base.Reset();

    defaultStateName = "State1";

    DestroyAllStates();
    CreateStates(new System.Type[] {
        typeof(State2),
        typeof(State3)
    });
}

使い方 - その他

  • 自分自身と同じステートに遷移できます
    • OnStateExit(), OnStateEnter() が呼び出されます
  • 遷移条件を満たす限り、1 フレーム内で複数ステート先まで遷移可能です
    • ステートマシンの transitionLimit で遷移回数の上限を指定します(デフォルトは 10)
    • 0 にすると無制限になりますが、無限ループにならないよう注意してください
    • ただし、自分自身と同じステートへの遷移は 1 回で止まります

サンプル

パッケージ内のサンプルの説明です。
  • 00_Common : サンプルで共通に使うスクリプトや、スクリプトの雛形があります
  • 01_Signal : 時間で状態遷移する信号機のようなものです。日本以外だとダメそうですね
遷移関数 transitions を使うサンプルがまだありません。すみません。追って追加予定です。

今後の予定

主にスクリプト作成支援系のエディタ拡張などを行い、アセットストアに出すことを検討しています。

その場合でもコア部分(少なくとも v0.9.0 相当)のスクリプトは体験版も兼ねて公開を続けます。ただし、メジャーバージョンアップや仕様上の欠陥が見つかった場合は後方互換性が保障されませんのでご了承ください。


2014/05/20 : v0.9.1 リリース。1 フレーム内の遷移回数制限追加など

2014年5月13日火曜日

[Unity]iTweenでパスの編集を便利にする

Unity で手軽にパス移動できるアセットとして、iTween とそのパスをエディタ上で編集できる iTweenPath は広く知られています。

が、iTweenPath は中間点の挿入/削除パス全体の平行移動/回転/拡大縮小が実質ほぼ不可能で調整がかなり厳しいので、できるやつを書きました。

WayPoint for iTween (GitHub)


使い方はざっくりと、
  1. iTween を入れる。iTweenPath は不要
  2. WayPointPath.cs をつけたオブジェクトを親にする。pathName を適当に決める
  3. WayPoint.cs をつけたオブジェクトを子にする。親の head をこのオブジェクトにする
  4. WayPoint.cs をつけたオブジェクトを複製する。さきほどのオブジェクトの next をこのオブジェクトにする
  5. パス移動は WayPointAgentSample.cs を参考に
です。

エディタ拡張まで作りこんでいないので最初の手動連結はちょっと面倒ですが、あとで楽になると思います。

…iTween も結構クセが強くて、使い込むと色々ハマるので、そのあたりも気が向いたら書こうかなあと。

2014年5月6日火曜日

[OculusRift]Nekolus : バーチャルリアリティで猫と遊ぶ

OculusRift で猫と遊べる、Nekolus (ねこらす) を公開しています。




  • 気ままに歩き回ったり
  • ボールを投げると拾ってきたり
  • 猫じゃらしにむらがったり
  • 増えたり
します。

マンション住まいだったり、仕事で日中世話できなかったり、好きなのに猫アレルギーだったりしても大丈夫!

手軽にプレイできるようにということで、どこにでもあるマウス操作です。といってもクリックだけでポインタは不要。またはキーボードでも可です。


クレジット

[モデル]
Cu Cat (Ts-Time)
Free Furniture Props (Vertex Studio)
Round Carpet (Olof Hagelin)
Speeping bed (Vertex Studio)

[BGM]
Ferne Welt (Piro 氏) [neko]

[SE]
フリー素材 -SpiderWorks-  [猫1, 猫2]

[ツール]
Unity  (ユニティ・テクノロジーズ)
VRGUI  (boone188)


2014/05/06 : 動画追加、クレジット追加
2014/06/09 : クレジット追加
2014/07/12 : Oculus VR Share のリンク追加
2014/07/17 : Oculus VR Share 上でのタイトルを "Nekolus - Cats in the Rift" に変更したことに伴い、リンク先 URL 変更
2014/08/03 : DK2 暫定対応版
2014/10/10 : DK2 対応版

2014年3月17日月曜日

[Unity]OculusRiftでモデルの首をスクリプトで動かせないときの対処

OculusRift でプレイヤーモデルの首を動かしたいのにうまく動かない、というときのための対処法です。

基本的にプレイヤーモデルの顔はカメラに映りませんが、カメラを目の位置=顔の中心からずれた位置に設置している場合、OculusRift の回転に合わせて顔も回転させておかないと、上を向いたときに髪の毛が映ったり頭の中が見えたりしてしまいます。


(モデルは Mukilus でお借りした Tda 式ミク さんと hzeo 式 KAITO さん)

カメラが顔の中心ではないため NearClip では対処しづらく、特に借り物のモデルでは顔だけを非表示にするのは難しいと思います。

そこで顔は表示させたまま首を動かし、カメラとモデルの目の位置が合っている状態を維持しようと考えるのですが、普通にやると初めは以下のような問題にぶつかるのではないかと思います。
  • OculusRift のカメラの Rotation をモデルの首に代入するスクリプトを作成し、単体では正しく動く
  • モデルにメカニムアニメーションを適用すると、アニメーションによって首が制御されスクリプトがうまく動かない
これについては、まずは以下のサイトなどを参考に、アニメーション側で首ボーンを動かさないように設定できるか試してみるのがよいと思います。

MMD for Unity を使って Oculus 用アプリを作ってみた - 凹みTips

メカ徒然日記 OculusRift+Unity失敗 解決事例 主にカメラ


しかし、自分のケースでは上記がうまく行かなかった(アニメーション側のマスク設定で、首のチェックを外せなかった)ため、以下のようなちょっと強引な方法で解決しました。


画像のように、アバターの Head にモデルの Neck を関連付けることでモデルの Head をメカニム制御対象外として、スクリプトではモデルの Head を回転させるという方法です。

トライ&エラーの上でのいわゆる dirty hack のため、詳細はあまり書いても仕方がないですが、

  • アバターの Head は必須
  • アバターの Head を正しく設定したまま Neck だけ外し、スクリプトで Neck を制御するのはうまく行かない
といったことを挙げておきます。


余談として、メカニムで特定の部位だけを動かすのはアバターボディマスクを使うのが正当なやり方ですが、Base Layer にはマスクを設定できません。

今回は試していませんが、Base Layer にはアニメーションを全く設定せずに、頭部を除外したボディマスクを指定したレイヤにのみアニメーションを設定すれば、こちらでもうまく行くかもしれません。(2013/3/23 追記 : これはうまく行かなさそうです)

スクリプトで直接 rotation を操作するのではなく、各向きの顔アニメーションを用意して 2D ブレンディング を使うのが真っ当なやり方のような気はしますが、これはけっこう面倒なので…。


2014/3/23 : ボディマスクの方法も試したので追記

2014年3月15日土曜日

[ドット絵]ユニティちゃん

ユニティちゃんやユニティ関連のみなさんのドット絵を置いていくかもしれないページです。

まだユニティちゃんだけです。




32x32 (実質 24x32), 32 色です。

ユニティちゃんライセンス
このアセットは、『ユニティちゃんライセンス』で提供されています。
このアセットをご利用される場合は、『キャラクター利用のガイドライン』も併せてご確認ください。

2014/3/16 : 素材画像のサイズが 2 倍になっていたのを修正
2015/2/22 : ユニティちゃんライセンス表記

2014年3月2日日曜日

[OculusRift]Mukilus : 初音ミクとあっち向いてホイ

OculusRift で目の前の初音ミクさんとあっち向いてホイで遊べる、Mukilus (むきらす) を作ってみました。


>>> ダウンロード (for Windows) <<<
(DK1 / 個人利用の範囲のみでお願いします)




  • 「正直この発想はあった」であろう、OculusRift の角度センサーであっち向いてホイを実際に作ってみたらこうなりました
  • ミクといえば歌とニコニコ動画。みんな知ってるあの曲から、BPM240 のあの曲まで、弾幕あふれる世界の中でリズムに乗ってノンストップあっち向いてホイ!
  • プレイヤーの手はみんな持ってるマウスでの操作です

参加予定だったニコニコ自作ゲームフェス3にはちょっと遅れてしまいましたが、OculusRift をお持ちの方はぜひミクさんと遊んでみてください。

粗い部分も多々ありますが 現在バージョンアップ版も鋭意作成中です


2014/3/7 : ページ更新
2014/11/9 : 注意書きなど追記

2014年2月22日土曜日

[Unity]MMD4MFaceBlink - MMD4Mecanimでまばたき

MMD モデルを Unity で利用できる、Stereoarts さんの MMD4Mecanim で簡単にまばたきをさせるスクリプトです。

配布はこちらの MMD4MFace とまとめて行っています。(どちらかだけでも動きます)

使い方は、以下の画像のように、


モデルかモデルの親に MMD4MFaceBlink をアタッチして、まばたきの表情モーフ名(複数可)を入力するだけです。時間に関するパラメーターは適宜調整してください。

preferredMorphs にモーフ名を入力すると、そのモーフの値が 0 でない間はまばたきしません。笑って目を閉じたり、目が点になっているときにまばたきをしないようにできます。

(Blink Name は空でもよいです。最新版では削除しました。(2015/2/27))


2015/2/27 変更 : blinkName パラメータを削除(使っていませんでした)

[Unity]MMD4MFace - MMD4Mecanimの表情制御

MMD モデルを Unity で利用できる、Stereoarts さんの MMD4Mecanim での表情制御をすこし便利にするスクリプトです。

GitHub : udasan/unity-mmd4mface (GitHub なにそれという方は右下の Download ZIP をどうぞ)

表情モーフを複数まとめたものを一つの表情として管理、制御できます。

使い方は、だいたい以下の画像で伝わるかと思いますが、


モデルかモデルの親に MMD4MFaceController と MMD4MFace (1 つにつき表情 1 つ分) をアタッチして、表情の名前 (faceName) とモーフの情報を入力するだけです。

あとは SetFace(faceName) で表情を変更できます。

また、各 MMD4MFace を無効にするとその表情を無効にできます。

その他、MMD4MFaceController には状態取得系のプロパティ / メソッドがいくつかあります。(詳しくはソース)


利点

  • 複数の表情モーフをまとめられる
  • 表情変更するときに、前の表情モーフのリセットを考えなくてよい
  • モデルごとの表情モーフ名の違いを吸収できる
  • スクリプトに日本語を書かなくて済む

注意点

  • timescale の影響を受ける


もちろん非公式です。(MMD4Mecanim_Alpha_20140216 でいちおうの動作を確認)

Unity 4.3.3f1 現在、インスペクタでの日本語入力がおかしいようですが、以下の記事が参考になると思います。

Unity4.3のインスペクターで日本語入力する方法 | ケットシーウェア


更新があればこの記事に追記していく予定です。


2014/2/20 追記 : 注意点を追記
2014/2/20 更新 : まばたき用スクリプトを追加しました。MMD4MFaceBlink

2014年2月19日水曜日

[Unity]MMD4Mecanimの表情制御 とりあえず版

最新はこちら : [Unity]MMD4MFace - MMD4Mecanimの表情制御

MMD4Mecanim で表情モーフのセットをひとつの表情として管理、制御するスクリプトです。

MMD4MFaceController ダウンロードは上記最新ページから行ってください

画像のようにモデルに MMD4MFaceController.cs と複数の MMD4MFace.cs をつけて、あとはスクリプトで Controller の SetFace("angry") などとしてください。


制御対象のモーフを認識して、明示指定のないモーフは自動で 0 にします。

もちろんMMD4Mecanim非公式です。

開発途上で後方互換性は非保証ですので、それでも良い場合かサンプルとしての利用でお願いします。

(外出中のため粗い文章で失礼しました。)

2014/2/20 追記 : MMD4MFaceController を更新(親オブジェクトにアタッチしてもいいように、他。詳細は Readme)、説明を追加
2014/2/22 追記 : 最新はこちら : [Unity]MMD4MFace - MMD4Mecanimの表情制御

2014年2月16日日曜日

[Unity]Tda式アペミクさんを使う際の設定

MMD モデルを Unity で扱える FBX に変換してくれる MMD4Mecanim などの登場により、Unity & Oculus 界隈で MMD モデルの利用が進んでいるようです。

中でも特によく使われているモデルの一つに Tda 式初音ミク・アペンド さんがありますが、使う際は AL 未使用モーフを 1 にしましょう。


…readme に書いてある内容ですが、MMD4Mecanim があまりにも簡単に使えることも相まって、読んでない人もいるかなーということで。

詳しくはもう Tda 式アペミクさんの readme (よんでね.txt) を見ていただければいいのですが、いちおう簡単に説明すると、上の図の左のほうは発光パーツの色がくすんでいたり、目のハイライトが水色になってたりします。

Tda 式アペミクさんは AutoLuminous というエフェクトを MME で適用させることを想定して作られていますが、エフェクトをかけない場合用の色変えも AL 未使用モーフとして用意されています。

MMD4Mecanim を使っているなら、この設定は MorphHelper を使うのが簡単です。


あと、LightOff モーフも 1 にしてと書いてあるので、合わせてこれもやった方がよいでしょう。ただ、こちらは画面上で違いを見つけられませんでした。

以下は、MMD 上での AutoLuminous と AL 未使用モーフの比較です。


Unity 上でも本気を出してもらうには、特定パーツを発光させるシェーダーを書いたり?したほうがよいのかもしれませんが、できるかどうか含めて詳しくないのでわかりません…。

ほかの推奨エフェクトである Diffusion と SSAO 相当のエフェクトをかけるためにも、やっぱりシェーダーとかアンビエントオクルージョンの勉強もしないとなあ。

2014年2月11日火曜日

[Unity]アップ時に可愛く撮る(カメラの視野角)

写真か 3D について少しでも知識のある人には常識だと思うので、何をいまさらという話になるかと思いますが、自分はこれを今日知って衝撃を受けました。

まずは以下を。


左右ともに、モデルは全く同じで Tda 式初音ミク・アペンド さんです。

違いはカメラだけで、左が視野角 60 度(広角) で被写体に近付いて撮ったもの、右が視野角 10 度(望遠) でやや遠くから撮ったものです。(画面は MMD でキャプチャしたものですが、Unity でも同様です)

顔の大きさがだいたい同じになるようにしましたが、左はかなり歪んでいるのがわかりますね。左しか知らないうちは、これでも可愛いと思っていたのですが…右と比べると差は歴然。

そして、Unity のカメラはデフォルトで視野角 (Field of view) が 60 なのです。


Unity スクリプトリファレンス - Camera.fieldOfView (4.3.3f1 現在)

カメラにあまり造詣がないので、広角かつアップの使い道も実はあるのかもしれませんが、Unity でもアップの画を撮るとき通常は画角(視野角)を狭めて撮るのがよさそうです。

Oculus Rift? あれ用のカメラは現実の視野角に合わせて自動で 90 度超に調整されるから…

参考



2014/2/11 追記 : 参考サイトを追記。

2014年1月28日火曜日

[Unity]ナビメッシュでの経路探索の使い方と注意点

Unity で簡単に経路探索を実装するにはナビメッシュが便利です。

今回は、基本的な使い方と、使ってみた上での注意点などを書いていきます。

基本

ナビメッシュを使うと、こんな感じで障害物を避けて目的地まで移動させることができます。


(日本語マニュアル)
ナビメッシュおよび経路探索 - Unity Manual

(英語マニュアル)
Unity - Navigation Meshes

現時点で日本語マニュアル(ちょっと古い?)には Pro のみと書いてありますが、英語マニュアルには書いていないので使えるみたいです。

(多分。英語でもページによって Pro only と書いてあったりします。 Unity - Pathfinding とか Unity - NavMesh Layers とか。Free 版での動作は未確認。)


とりあえず移動させるだけなら
  1. シーンに床や障害物を置く
  2. それらを Navigation Static にする(インスペクタ右上。Static チェックで OK、下三角マークで詳細)
  3. メニュー -> Window -> Navigation -> Bake タブ -> Bake ボタンで通れる場所を焼き込み
  4. 移動させたいオブジェクトに NavMeshAgent コンポーネントをつける
  5. 自前のスクリプトで、移動させたいオブジェクトの NavMeshAgent を取得して目的地を SetDestination で指定する
と簡単です。



さらに、
といったこともできます。

注意点

ここから注意点などです。

  • 微調整が効かない
    • Bake したナビメッシュ自体の手動調整はできません
    • Bake 時の設定やナビメッシュレイヤー、Navigation Static のオンオフ、果てはオブジェクト自体の位置を微調整して Bake を繰り返すことになります

  • 微妙に浮く
    • 下の画像のように、焼き込んだナビメッシュが床から離れることがあります
    • おそらく壁や手すりが悪さをしているのだと思いますが、原因不明です(上のモデルは床、壁、手すりが一体化していて分割できない)
    • Bake 時の radius (エージェントと壁までの距離) を小さくするとより顕著に起きるようにも見えましたが、本当の原因かどうかはわかりません
    • エージェントは物理無視でナビメッシュに沿って移動するため、当然床から浮きます。ちなみに、この状態でエージェントを重力で落としてみましたが上下に震動してダメでした

  • メッシュを分割しておく
    • たとえば床と壁が一体化していると、調整時に非常に困ります
    • 地面と遠景用の Terrain がつながっていると無駄に Bake に時間がかかります
    • 自前でないアセットを使う場合はどうにもならないこともあります

  • 異なるナビメッシュレイヤーが重ならないように注意する
    • あるエージェントが移動可能なレイヤーと移動不可なレイヤーが重なっていると挙動があやしくなるので避けるようにします
    • 地盤(一部エージェントのみ通行可)の上に道路(全エージェントが通行可)を置く場合などにこの状況になりやすいです
    • 上記の場合はほんの少し地盤を下げるとうまく行くこともありますが、地盤と道路のナビメッシュが離れてしまうこともあります

  • さいごの調整手段その 1 : オフメッシュリンク
    • メッシュがつながらない問題はほぼこれで解決できるとおもいます
    • 量が多くなりがちで非常に面倒です

  • さいごの調整手段その 2 : 対象をコピーする
    • たとえば床のナビメッシュがうまくできないとき、床をコピーして、元々の床から Navigation Static のチェックを外し、コピーの床の座標やサイズを調整し、Bake し、コピーを非アクティブ(or 削除)にします
    • 当然面倒です

  • 経路探索のコストに気をつける
    • 経路探索は軽い処理ではないので、使いすぎには注意が必要です
    • 毎フレーム同じ目的地を SetDestination したことがあったのですが、フレーム内に計算が終わらなかったため(?)か、たまに動かないということがありました
      • 筋が悪いと自覚しつつも、ゲームジャムで急ぎだった上にジャム終盤(いろいろ追加して重くなる?)まで動いてたので…

  • 地上でしか使えない
    • これは注意点というよりメモですが、空中や水中を移動するエージェントには不向きです
    • 空中を水平移動するだけなら不可視のメッシュ沿いに移動で問題ないですが、上下左右自在に移動するケースでは使えません

参考


おわりに

注意点などいろいろと書きましたが、Bake さえうまくできてしまえばスクリプトは少なくて済み、他の探索方法のように経路にマーカーオブジェクトを配置する必要もないため非常に便利です。