MRが楽しい

MRやVRについて学習したことを書き残す

Unityに設計おけるクラス設計を考える その11(視線追従処理)

おいかけっこアプリの修正枠です。
本日は視線追従の機能実装と、コメント記述によるコード自体のブラッシュアップを行いました。
bluebirdofoz.hatenablog.com


視線追従に関しては色々と悩んだ結果、モデルオブジェクトの同階層オブジェクトとして実装しました。
f:id:bluebirdofoz:20170606032142j:plain
視線追従はキャラクタのモデル操作のスクリプトなので、モデルマネージャに入れ込みたいところです。
しかし、キャラクタオブジェクトはあくまでモデルポリゴンのオブジェクトとし、判定用の新規オブジェクトを追加したくなかったという理由です。

機能の担当箇所として分かりづらい気もします。作り込みの内で、良い設計が思いついたら改修していきます。
明日からはまた3Dモデリング学習やチュートリアル実施を再開していきます。

Unityに設計おけるクラス設計を考える その10(フィールド処理)

おいかけっこアプリの修正枠です。
ゲーム開始時のエフェクト、音声認識、空間マッピング(フィールド処理)の実装が完了しました。
パネルUI、視線追従の機能実装が残っていますが、少し設計を悩みたいのでひとまず再設計作業を完了とします。
bluebirdofoz.hatenablog.com


ゲーム開始時のエフェクトの管理クラスとして、MainCharactorオブジェクト内に新たに「EffectManager」を追加しました。
本オブジェクトがゲーム開始時の「球体が弾け飛び、ユニティちゃんが現れる」という演出を管理します。
f:id:bluebirdofoz:20170605043342j:plain
「EffectManager」が球体オブジェクトを管理しており、初期化時にマテリアルを有効化します。
このため、実装作業時には球体オブジェクトのメッシュを無効にしておけます。
f:id:bluebirdofoz:20170605043349j:plain
再設計前と比べ、シーン画面が見やすくなりました。


空間マッピングのフィールド処理は「GameField」オブジェクトが担当しています。
Unityデバッグ上では「SpatialMapping」の代わりに「TestField」オブジェクトを有効化します。
このため、Unity上で「TestField」を編集することで様々なフィールドでのデバッグ操作が可能です。
f:id:bluebirdofoz:20170605043357j:plain
フィールド処理そのものはシグナルを受け取ると、メッシュの変更処理を行います。
「SpatialMapping」と「TestField」で管理を共通化しているため、Unity上で空間マッピングへの処理のデバッグが可能です。
f:id:bluebirdofoz:20170605043405j:plain
Iguanaシグナルを受け取るとメッシュが変わります。


音声認識は「GameUI」オブジェクトの下位スクリプト「Speech」オブジェクトとしてアタッチされています。
また同じくキーボード認識には「Keyboard」オブジェクトがアタッチされています。
f:id:bluebirdofoz:20170605043416j:plain

前述のIguanaシグナルはキーボード操作の「I」キーが押下されたとき、「Keyboard」オブジェクトがこれを検出し、「GameUI」オブジェクトを通してPresenterへと通知されます。
・Keyboard.cs(抜粋)

if (Input.GetKey(KeyCode.I))
{
    // 「I」キーを検出したとき、「Iguana」シグナルをキャストする
    EFreeSignal signal = EFreeSignal.Iguana;
    p_GameUI.EventOnFreeSignalClicked(signal);
}

また、音声認識では"メッシュ"の音声が認識されたとき、「Speech」オブジェクトがこれを検出し、「GameUI」オブジェクトを通してPresenterへと通知されます。
・Speech.cs(抜粋)

// "mesh"を辞書に登録
p_DictionaryKeywords.Add("mesh", () =>
{
    // メッシュ効果を切り替え
    if (p_GameUI != null)
    {
        // 「mesh」音声を検出したとき、「Iguana」シグナルをキャストする
        EFreeSignal signal = EFreeSignal.Iguana;
        p_GameUI.EventOnFreeSignalClicked(signal);
    }
});


今回で一通り、実装として形が固まりましたが、まだ完了ではありません。
次はコメント記述や不要コードの削除など、コード自体のブラッシュアップを行います。

会社は有休を取っておいたので、明日の内に終わらせてしまいます。

Unityに設計おけるクラス設計を考える その9(追いかけっこロジックの移植)

おいかけっこアプリの修正枠です。
現在、ようやく追いかけっこロジックの移植が完了しました。長かった…。
bluebirdofoz.hatenablog.com


上記事の設計にある通り、追いかけっこのロジックはメインキャラクタ統合オブジェクトの中で閉じています。
追いかけっこモードが有効の時、キャラクタの移動はViewの中で完結し、ゲームロジックを通したやり取りは発生しません。

しかし、コントロールロジックとモデルマネージャは明確に分けているため、Viewの中でも切り分けが行われています。
Viewの中はインタフェースクラスを通してオブジェクト間のやり取りを行っています。
パーツ毎の修正は可能ですが、それぞれは互いの機能を知っていることが前提であり、少し結び付きが強めのイメージです。

コントロールロジックとモデルマネージャを分けたため、追いかけっこロジックで使用するアタリ判定をモデルから切り分けることができました。
f:id:bluebirdofoz:20170604035410j:plain
修正前はモデルオブジェクトにあらゆるスクリプトや判定用オブジェクトがアタッチされていたので非常にすっきりしました。
新しい移動ロジックを追加することも容易になりそうです。

ただし、この手法を用いる場合、キャラクタの移動には注意が必要です。
モデルのみを移動した場合、アタリ判定はモデルに追従しないため、予期しない動作となります。

キャラクタを移動させる際は、以下のようにViewのルートオブジェクトを移動させることで移動を実現する必要があります。
ActionController.cs(抜粋)

Vector3 AnimDir = p_Velocity;
AnimDir.y = 0;
if (AnimDir.sqrMagnitude > 0.001)
{
    // 前進する方向に旋回(ルートオブジェクトを対象とする)
    Vector3 newDir = Vector3.RotateTowards(transform.root.forward, AnimDir, 10f * Time.deltaTime, 0f);
    transform.root.rotation = Quaternion.LookRotation(newDir);
}

// 移動処理(ルートオブジェクトを対象とする)
transform.root.position += p_Velocity * Time.fixedDeltaTime;

これに伴い、キャラクタのアタリ判定もルートオブジェクトにアタッチされています。
f:id:bluebirdofoz:20170604035432j:plain
Viewそのものがキャラクタを示すオブジェクトなので正しい考え方とは思いますが、モデルそのものにアタッチしないことが問題にならないか、今後、注意が必要です。


ゲームを開始し、Fキーを押下するとキャラクタがメインカメラを追跡します。
追跡完了のアタリ判定がカメラに触れた時点で、アクションを行い、追いかけっこを完了しました。
f:id:bluebirdofoz:20170604035459j:plain

追いかけっこロジックの移植完了です。
残るは、ゲーム開始時のエフェクト、パネルUI、音声認識、空間マッピングです。

Unityに設計おけるクラス設計を考える その8(ゲーム通知の仕組み)

おいかけっこアプリの修正枠です。
ひとまずPresenterによってゲーム全体のオブジェクト間通信が成功したので、一部リファクタリングを実施しました。
bluebirdofoz.hatenablog.com


本日、再設計を実施したのはPresenterを介してのユーザ操作の通知の仕組みです。
前回の記事では「キーボードのBを押したとき、キャラクタが休憩動作をする」という動作例をお見せしました。
bluebirdofoz.hatenablog.com


このとき、「キーボードの B がキャラクタの休憩動作である」という判定をゲームUI側オブジェクトが行うのか。
それともキャラクター操作側のオブジェクトが行うかという設計の悩みが発生します。

Viewは通知先の実体を知らないべきという考えから、キャラクター操作側のオブジェクトでこの判定を行うよう修正を行いました。
修正後は下記のような処理の流れが発生します。

「ゲームUIオブジェクトがキーボードの B の押下を検出したとき、Presenterが Bear というシグナルを受け取る」

「Presenterが Bear というシグナルをキャラクター操作オブジェクトに送る」

「キャラクター操作オブジェクトは Bear というシグナルを休憩動作の実行と解釈する」

これならばView同士はお互いの実体を全く知らないため、ゲームUIの差し替えも、キャラクターロジックの差し替えも容易に実施できます。
f:id:bluebirdofoz:20170602012039j:plain


一方でゲームUI上に「休憩」ボタン、「ジャンプ」ボタンなどのゲームの実体を知っている前提の画面UIを出すことが難しくなるというデメリットもあります。
この辺りはメリット、デメリットの綱引きですが、とりあえずは当初の設計思想を守ることを優先していきます。

blenderのモディファイアをまとめる(生成)

モディファイアの生成機能について、調べた結果をまとめます。
★マークのものは個人的によく使いそう、または、抑えておくべきと感じた機能です。

・配列複製
 オブジェクトを一定の軸に並べて配列複製できる機能。
 元のオブジェクトの形状を変化させると複製オブジェクトも同じように変化する。
 - Blenderモディファイア(Array)
  http://cg.xyamu.net/Blender/entry195.html
 - 配列モディファイア
  https://wiki.blender.org/index.php/Doc:JA/2.6/Manual/Modifiers/Objects/Array

・ベベル★
 オブジェクトの角を丸めるモディファイアです。
 鋭すぎる縁に滑らかさを与えオブジェクトの形状をより引き立てる効果もある。
 - Blenderモディファイア(Bevel
  http://cg.xyamu.net/Blender/entry194.html
 - ベベルモディファイア
  https://wiki.blender.org/index.php/Doc:JA/2.6/Manual/Modifiers/Mesh/Bevel
 - Blenderで面取りはモディファイアのBevel
  http://ringsbell.blog117.fc2.com/blog-entry-908.html
 - 〈復習〉シャープなエッジの設定方法
  http://blender.u5kun.com/?p=862
 ※ Ctrl+Bで利用できるベベル(bevel)とは非破壊的な代替手段である点が異なる。
  - ベベル(Bevel
   https://wiki.blender.org/index.php/Doc:JA/2.6/Manual/Modeling/Meshes/Editing/Subdividing/Bevel

ブーリアン
 2つのオブジェクトを組み合わせて加算、減算などの演算により新しい形状を作成する機能。
 既存のオブジェクトに穴を開けたり、重なった部分のみ取り出すことなどが可能となる。
 - Blenderモディファイア(Boolean)
  http://cg.xyamu.net/Blender/entry178.html
 -
Blenderブーリアンモディファイアー【オブジェクト同士の合成・足し算・引き算】

  http://blender-cg.net/boolean/
 -
Blenderブーリアンシュリンクラップを使い分けると幸せに慣れそうだったので覚書【Tips】
  http://madeinpc.blog50.fc2.com/blog-entry-1094.html

・ビルドアニメ
 オブジェクトが出現する過程のようなアニメーションを作るモディファイア。
 - Blenderモディファイア(Build)
  http://cg.xyamu.net/Blender/entry209.html
 - Buildモディファイア
  https://wiki.blender.org/index.php/Doc:JA/2.6/Manual/Modifiers/Generate/Build
 - 【Blender】ビルドアニメモディファイアー【アニメーションで登場・退場】
  http://blender-cg.net/build/

・ポリゴン数削減
 オブジェクトのポリゴン数を手軽に削減できるモディファイア。
 頂点数が非常に多いハイポリゴンモデルに対し、頂点をある程度減らす用途に使用する。
 - Blenderモディファイア(Decimate)
  http://cg.xyamu.net/Blender/entry210.html
 - Blenderを用いたポリゴン数削減
  http://slis.tsukuba.ac.jp/~fujisawa.makoto.fu/lecture/iml/text/blender.html
 - Decimateモディファイア
  https://wiki.blender.org/index.php/Doc:JA/2.6/Manual/Modifiers/Generate/Decimate

・辺分離
 辺や面をメッシュから分離できるモディファイア。
 四角面の辺4つを「辺の分離」すれば、その四角面はメッシュから切り離されたポリゴンとなる。
 - EdgeSplitモディファイア
  https://wiki.blender.org/index.php/Doc:JA/2.6/Manual/Modifiers/Generate/Edge_Split
 - 【Blender】辺の分離(切り分け)と切り裂き方法
  http://blender-cg.net/edge-split-rip/

・マスク
 指定した頂点グループ以外の部分を隠すモディファイア
 レンダリングの際にも表示させたくない場合はMaskモディファイアを使用する。
 - Blenderモディファイア(Mask)
  http://cg.xyamu.net/Blender/entry243.html
 - Maskモディファイア
  https://wiki.blender.org/index.php/Doc:JA/2.6/Manual/Modifiers/Generate/Mask
 - Maskモディファイアの使い方
  http://6b.u5ch.com/2012/12/mask.html

・ミラー★
 指定軸方向にミラーを生成するモディファイア。
 メッシュの中心を通るローカルなX、Y、Z軸に沿って自動的に鏡像を作り出す。
 (鏡面は選んだ軸以外の二つの軸で規定されることになる)
 他のオブジェクトの中心および軸を鏡として使うこともできる。
 鏡面から指定した許容値内の距離にある頂点を鏡面で結合することもできる。
 - Blenderモディファイア(Mirror)
  http://cg.xyamu.net/Blender/entry30.html
 - Mirrorモディファイア
  https://wiki.blender.org/index.php/Doc:JA/2.6/Manual/Modifiers/Generate/Mirror
 - 【Blender】ミラーモディファイアー
  http://blender-cg.net/mirror/

・多重解像度★
 多重解像度は単純にモデリングされたオブジェクトを、スカルプトモードで編集することで、
 複雑なオブジェクトに見せることができるモディファイア。
 ポリゴン数を増やすのは細分割曲面と似ているがハイポリ化した面をスカルプトで形状変更できる。
 - 多重解像度を使ったローポリモデリング
  http://tafurublender.blog.fc2.com/blog-entry-18.html
 - 【Blender】多重解像度モディファイアの簡単な使い方【覚書】
  http://madeinpc.blog50.fc2.com/blog-entry-1048.html
 - [Blender]神饌のプリントその6[Working]
  https://buildinginblender.blogspot.jp/2015/07/blenderworking_18.html#!/2015/07/blenderworking_18.html

・リメッシュ
 オブジェクトのメッシュを再構築し、新しい構造にするモディファイア。
 ナイフツールやブーリアン使用後などに生成された鋭角な面を修正したり、モデリングしやすい構造に変えたりできる。
 - Blenderモディファイア(Remesh)
  http://cg.xyamu.net/Blender/entry274.html
 - Remesh Modifier
  https://wiki.blender.org/index.php/Doc:JA/2.6/Manual/Modifiers/Generate/Remesh

・スクリュー★
 回転体を作るモディファイア。
 断面図を規定するメッシュオブジェクトやカーブオブジェクトを使って、らせんのような形状を生み出す。
 - Screwモディファイア
  https://wiki.blender.org/index.php/Doc:JA/2.6/Manual/Modifiers/Generate/Screw
 - 【Blender】モディファイアー「スクリュー」
  http://sou-was.jugem.jp/?eid=48
 - 【Blender】スクリューの使い方
  http://blender-cg.net/screw/

・スキン★
 メッシュの頂点や辺を芯に肉付けした新しいメッシュ(スキン)を生成するモディファイア。
 例えば、立方体にスキンを適用すると、立方体の”頂点”と”辺”にのみ肉付けされる。面部分は無視される。
 - Blenderモディファイア(Skin)
  http://cg.xyamu.net/Blender/entry275.html
 - スキンモディファイア
  https://wiki.blender.org/index.php/Dev:JA/Ref/Release_Notes/2.64/Skin_Modifier
 - 【Blender】スキンモディファイアー【辺に厚みを持たせる】
  http://blender-cg.net/skin/

・厚み付け★
 メッシュに自動で厚みを付ける事ができるモディファイア。
 頂点数を増やさずに厚みを加えることができる。
 - Blenderモディファイア(Solidify)
  http://cg.xyamu.net/Blender/entry238.html
 - Solidifyモディファイア
  https://wiki.blender.org/index.php/Doc:JA/2.6/Manual/Modifiers/Generate/Solidify
 - 【Blender】厚み付けモディファイアー
  http://blender-cg.net/solidify-modi/

・細分割曲面★
 オブジェクトの面を分割し、より精細な表示を可能にするモディファイア。
 Subdivideを使った分割とは違い、コントロールできる頂点数を保ちつつ表示のみに影響する。
 - Blenderモディファイア(Subsurf)
  http://cg.xyamu.net/Blender/entry176.html
 - 【Blender】細分割曲面モディファイアー
  http://blender-cg.net/subsurf/

・三角面化★
 オブジェクトのメッシュに含まれる四角形の面をを全て三角形に変えるモディファイア。
 外部レンダリングソフトの中には全ての面を三角形にする必要があるものもあり、
 Blender上で作成したオブジェクトをエクスポートする前にこのモディファイアを適用するとよい。
 - Blenderモディファイア(Triangulate)
  http://cg.xyamu.net/Blender/entry273.html
 - 三角面化(Triangulate)モディファイアー
  https://wiki.blender.org/index.php/Doc:JA/2.6/Manual/Modifiers/Generate/Triangulate
 - 初心者がBlenderMMDモデル作る時の注意事項
  http://ch.nicovideo.jp/yudedaco/blomaga/ar623537

ワイヤーフレーム
 メッシュの辺をポリゴン化し、立体的なワイヤーフレームの外観に変えるモディファイア。
 細いワイヤー状のメッシュを作成することができる。
 - Blenderモディファイア(Wireframe)
  http://cg.xyamu.net/Blender/entry309.html
 - Blenderモディファイア(Wireframe)
  http://illustworks.seesaa.net/article/395112425.html
 - ワイヤーフレーム(wire frame)モディファイア
  http://youkan.info/wp/%E3%83%AF%E3%82%A4%E3%83%A4%E3%83%BC%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0wire-frame%E3%83%A2%E3%83%87%E3%82%A3%E3%83%95%E3%82%A1%E3%82%A4%E3%82%A2/
 - Blender2.70のワイヤーフレームモディファイアで遊んでみた
  http://ch.nicovideo.jp/Arasen/blomaga/ar467470

Unityに設計おけるクラス設計を考える その7(デバッグ)

おいかけっこアプリの修正枠です。
本日は昨日発生していたキーボード操作の異常に関するデバッグを実施しました。
bluebirdofoz.hatenablog.com


デバッグの方法については以下を参照しました。
ログから簡単にスタックトレースが確認できるのは便利です。
docs.unity3d.com
tsubakit1.hateblo.jp

アニメーションの状態遷移の条件と、キーボード操作のトリガー条件に問題がありました。
修正して動かしてみます。
f:id:bluebirdofoz:20170531021102j:plain

キーボード入力に従い、キャラクターが正しく動きました。
Presenterによる接続が上手くいったということなので、今後、キャラクターの操作とゲームUIについては、個々に作り込みができます。

例えばキーボードの「B」を押せば、キャラクタが休憩動作をします。
f:id:bluebirdofoz:20170531024912j:plain
このとき、キャラクタViewは休憩動作の通知をpresenterを通して受け取っているだけです。ゲームUI側Viewも通知先の実体はPresenterを含め、全く知りません。
よって、「休め」と音声認識させて同じ処理を追加しようとした際、ゲームUIに新たな通知処理を追加するのみで、キャラクタ側のコードは全く関与しません。

また、キーボードのキーを割り当ててしまえば、マイクによる音声認識を始めとして、UI通知で行う処理をUnity上のキーボード操作のみでデバッグすることもできます。
hololens上での動作確認はセンサの処理動作のみでよくなるので、デバッグも楽になりそうです。

設計の根幹の動作を確認でき、一段落です。
次からはマテリアルや追いかけっこロジックの移植など各Viewを作り込んでいきます。

Unityに設計おけるクラス設計を考える その6(Presenter)

おいかけっこアプリの修正枠です。
再設計開始から約一か月…寄り道を多々していたこともありますが、少々時間がかかり過ぎです。
よって、今週はおいかけっこアプリの修正の強化週間とします。次の日曜日までに元々の機能を全て再実装するのが目標です。
勿論、再設計が主目的なのでスピードは重視しつつ、作り込みは疎かにしません。

今回はViewとModelの橋渡しを行うPresenterの実装を行いました。
bluebirdofoz.hatenablog.com

記事のサンプルを参考に、Presenter部分となるゲームロジックオブジェクトを実装しました。
developers.cyberagent.co.jp

以下の通り、「GameLogic」というゲームオブジェクトのみが全てのViewとModelへの参照を知っており、それらの間で行われる処理のやり取りを統括します。
f:id:bluebirdofoz:20170530015206j:plain

キーボード操作に関する実装を完了し、試しに動かしてみました。
f:id:bluebirdofoz:20170530015330j:plain


キャラクタがキーボード入力に従ってフィールドを歩くことが確認できました。
ひとまずは成功です…が、微妙にキーボードの操作と動きが合っていません。
タイミングの問題かインタフェースの問題でしょうか。

処理は繋がったことが確認できたので、明日以降デバッグして詰めていきます。先はもう少し長そうです。