Raspberlyのブログ

Raspberlyのブログ

Unityネタをメインとした技術系ブログです。にゃんこ大戦争や日常なども。そろそろブログタイトル決めたい

イベントレポ : Oculus Quest ゆるゆるハッカソン #01

イベントへの参加レポになります。
参加したのはこちら、「Oculus Quest ゆるゆるハッカソン #01」
会場はメルカリさんです。

questloverstokyo.connpass.com

ハッシュタグ : #QuestHackathon

 

 

 

f:id:Raspberly:20190630014036j:plain

f:id:Raspberly:20190630013916p:plain

 

 

 

 

タイムテーブル

時間 内容
9:00-9:15 受付集合
9:30 イベント説明開始
10:00 アイディアソン
10:30 チーム分け
11:00-19:00 ハッカソン
19:00 成果物プレゼン
20:00 懇親会&体験会
21:30 撤収

 

 

 

 

イデアソン

最初にアイデアソン、その後投票して案を絞りチーム分けを行いました。
イデアソンのアイデア一覧はこちら。

docs.google.com

私は3Dエアホッケーチームです。

 

 

 

 

担当箇所

今回作るゲームは3Dのエアホッケーになります。
通常のエアホッケーと違い上下にも動くのが特徴です。
対戦相手はNPCです。先に3点先取したほうの勝ちです。

 

プレイヤーの作成

ホッケーのプレイヤー部分の作成。
手を広げることでスマッシャーと呼ばれるラケットのようなものを生成し、
飛んでくるボールを打ち返します。

f:id:Raspberly:20190630000238p:plain

このスマッシャーは両手を広げれば広げるほど大きくなります。
また、両手の中間地点で固定したいため以下のリンクを参考にしました。 

teratail.com

 最初はスマッシャーの角度をHMDの角度と同期させていましたが、
両手の角度の中間値をスマッシャーと角度とするよう修正しました。

qiita.com

 

制作初期のgif

f:id:Raspberly:20190630005730g:plain

 

トレイルの追加

今回のボールに限らず、銃弾など高速で動くオブジェクトにトレイルを与えると
見栄えが非常によくなります。

f:id:Raspberly:20190630000012g:plain

f:id:Raspberly:20190630010123g:plain

こちらもTrailRendererをアタッチするだけで簡単に実装できます。
ただ、Trailの幅を設定する項目が見つからない所で少し詰まりました。
ここはテラシュールブログさんが参考になります。

tsubakit1.hateblo.jp

 

効果音の設定

ボールを跳ね返した時の効果音の設定。よくあるやつ。
OnCollisionEnterでPlayOneShotしています。

 

ソナーエフェクトの追加

意外と好評だったソナーエフェクトの作成。
使ったのはこちらのアセットです。

assetstore.unity.com

 使い方はコガネブログさんで詳しく解説されています。

baba-s.hatenablog.com

シェーダーを変えてスクリプトを1つアタッチするだけで簡単にエフェクトを出せるのでオススメ。
いろいろカスタマイズできそうではありますが、デフォルトの設定そのままでやりました。
最終更新が2年前ですので少し怪しい部分もありますが。

 

リザルト画面の作成

勝ったらWin、負けたらLoseと表示させます。
Dotweenでわちゃわちゃアニメーションさせたかったのですが、ここを作ってちょうど時間切れ。

 

 

 

 

完成品

時間内に無事完成しました。
スマッシャーの範囲が小さいほど強く跳ね返す案もありましたがオミット。
ボールがループすることがまれにありますが、きちんと対戦することができリトライもすぐにできます。
敵のAIもとてもよく動きます。

f:id:Raspberly:20190630012547g:plain



 

 

 

 

 

 

体験会

全5チームの作品体験会となります。
お酒やお菓子、おにぎりがでました。

f:id:Raspberly:20190630003310j:plain



 

※実際のプレイ画面はないです、また各作品の正式名称も不明なので命名は勝手にしています。

VRコースター

アトラクション風の作品。椅子に座った状態で後ろの人に押してもらいながら進みます。

f:id:Raspberly:20190630003344j:plain

広いスペースを活かしたステージ構成になっており、体験者が次の押す係を務めるというフローも面白い。

 

 

ロボットあてゲーム

唯一の通信機能をもったゲームです。
Questをかぶったプレイヤーと、スマホでロボットを操作するプレイヤーの二人で遊ぶことができます。

シーン内には自立行動しているロボットがたくさんおり、
スマホを持ったプレイヤーはロボット達に紛れこみます。

Questのプレイヤーはロボットの中から人間が操作しているロボットを見つけ出すことを目的とします。

つまり、スマホ側はロボットっぽい動きをし、Quest側はそれを見破るといった内容です。

 

 

脱出できない脱出ゲーム

脱出ゲームですが、製作途中で脱出できないゲームです。
プレイヤーは体の大きさを変化する能力を持ち、この能力でギミックを解除していくようです。

 

 

イカ割り

とても斬新な協力プレイゲーム。
協力プレイといってもオンライン通信をするというわけではなく、
Questをかぶっている人とTouchコントローラーを持っている人に分かれ、
それぞれコミュニケーションを取りながらスイカを割っていくゲームです。

ステージ内にはスイカとスイカを割る棒、そして美女?がいます。

 

 

 

タイムライン

 

 

 

 

 間違っている所、消してほしいツイートなどがありましたらコメントにお願いします。

【Oculus Quest開発メモ】VR空間内を歩き回る OVR PlayerController編 【Unity】

今回はOculus Questの開発ネタをやっていきます。
内容的にはOculus Rift Sなどにもそのまま応用できるかと思います。

 

VR開発の基本、空間内で自由に歩き回る方法について解説します。
VR空間での移動方法はいろいろありますが、今回はワープを使わない方法でやります。

 

 

8月29日追記

OculusIntegration1.40時点で、この記事の手順通りだとうまくいかない箇所があります。
解決次第追記します。

 

 

 

 

 

開発環境

Windows 10

Unity 2018.4.1f

Oculus Integration ver1.37

Oculus Quest

 

 

 

セットアップ

事前に前回の開発メモを読んでおくと理解がスムーズになると思いますのでまだの方はどうぞ。

raspberly.hateblo.jp

raspberly.hateblo.jp

 

 

 

 

 

サンプルシーンの確認

Assets/SampleFramework/Usageに様々なサンプルシーンがあります。
学習や挙動の確認にとても有益です。

今回の主要コンポーネントであるOVRCharacterControllerですが、
実はいろいろなシーンで使用されています

前回のDistanceGrabberのシーンでも使用されていました。

それだけ汎用性のある機能です。

 

 

 

 

主要コンポーネント

こちらもOculusの方で予めコンポーネントが用意されています。 

OVR Character Controller

VR空間で動き回るのに使用するコンポーネントです。

 

 

 

 

 

 

OVRPlayerController

このコンポーネントはUnity標準のCharacterControllerを使用します。
ただしRequireComponentで勝手にアタッチされるので特に気にする必要はないです。

f:id:Raspberly:20190629011930p:plain

インスペクターパラメーター

DistanceGrabberに負けず劣らずのパラメーター量です。

float Acceleration

 移動中の加速度

float Damping

 移動速度の減衰率、これの値が大きいほどすぐ止まる。

float BackAndSideDampen

 移動中に反対方向に移動した時の追加の減衰率。

float JumpForce

 ジャンプ中にキャラクターにかかる力。
実は定義されているだけで実装されているわけではありません。(後述)

float RotationAmount

 ゲームパッドを使用している時の回転速度。

float RotationRatchet

 キーボードを使用している時の回転速度。

bool SnapRotation

 スナップ回転を有効にするかどうか。
スナップ回転とは、方向転換時にプレイヤーを一定の角度ごとに回転させること。

f:id:Raspberly:20190629000450g:plain

f:id:Raspberly:20190629000516g:plain

上のgifがスナップ回転有効時の挙動、下のgifは無効時の挙動です。
スナップ回転は一見カクカクしているように見えますが、
プレイヤーのベクションを回避し、VR酔いを軽減する効果があります。

int FixedSpeedSteps

 直線移動で使用する固定速度。

bool HmdResetsY

 trueの場合、HMDポーズが再び中央に戻った時にプレイヤーコントローラーのヨーをリセットします。

bool HmdRotatesY

 trueの場合、OVRCameraRigの回転に合わせて移動方向を変更します。
つまりHMDの向きがそのままCharacterControllerに反映されます。
より直観的な動きが可能になります。

以下のgifは常に前進している様子です。
前進しているだけですが顔(HMD)の向きを変えるだけで方向転換しています。

f:id:Raspberly:20190629015808g:plain



float GravityModifier

 重力の設定RigidbodyのGravityと同じです。0にすると落下しません。

bool useProfileData

 プレイヤーの身長を使用するかどうか

float CameraHeight

 シーン内におけるカメラの高さの設定。
「低い天井の場所は移動させないなど」の制限を与えることができます

bool Teleported

 プレイヤーがテレポートするときにTrueになります。
外部からの参照用のようです

bool EnableLinearMovement

 ユーザー入力を直線的にする

bool EnableRotation

 ユーザー入力を回転に適応する

bool RotationEitherThumbstick

 回転を2-Axisなものにするかどうかデフォルトだとオンになります 。

 

 

 

 

 

 

 

実際に歩いてみる

サンプルシーンを動かせばすぐに歩き回れますが、
新しいシーンを作って一からセットアップしてみます。

 

まずはNew Sceneで新しいシーンを作ります。
何もないので、地面となるPlaneを作りましょう。
また、MainCameraは必要ないので消しておきます。

f:id:Raspberly:20190628230756p:plain

 

 

プレハブの準備

Asset/Oculus/VR/Prefabsの中にOVRPlayerControllerがありますので、
これをシーン内に配置します。

f:id:Raspberly:20190628234310p:plain

 

これだけで準備OK!
シーン内を動き回ることができます。

f:id:Raspberly:20190629000335g:plain



 

 

 

 

手を出したい

動き回れるからには手も表示したいものです。実際にやってみましょう。
今回はDistanceGrabbableを使ってみます。OVRGrabberも同様の手順です

f:id:Raspberly:20190629001915p:plain

Assets/Oculus/SampleFramework/Core/DistanceGrab/Prefabsにある
DistanceGrabプレハブを右手左手共にシーンに配置します。

OVRGrabberを使用したい時はAssets/Oculus/SampleFramework/Core/AvatarGrab/Prefabsにあるプレハブを使いましょう。

シーン内のHierarchyビューはこんな感じになります。

f:id:Raspberly:20190629002251p:plain



このまま実行したいところですが、手の方に親を設定してあげる必要があります。
各種Grabのインスペクターを見てみましょう。

注目すべきはParentTransformPlayerです。

f:id:Raspberly:20190629002514p:plain

ParentTransformには、OVRPlayerControllerの子オブジェクトであるOVRCameraRigをアタッチします。
PlayerにはOVRPlayerControllerをそのままアタッチします。

 

ここで実はもう一つやることがあります、ちょっとだけ詰まった個所です。
OVRPlayerControllerのHmd RotateYのチェックを外しておきましょう。
これをしないと正しく追従しないことがありました。

f:id:Raspberly:20190629010255p:plain

 

これで手が表示され、Playerの移動や回転に合わせて追従します。
間違えやすい点として、GrabberプレハブはPlayerの子オブジェクトにしない点に注意しましょう。

f:id:Raspberly:20190629011751g:plain

 

 

 

 

 

 

ジャンプしたい

コンポーネントの説明でもしましたが、
デフォルトではジャンプ機能は定義されていますが、実装はされていません。
実際にOVRPlayerController.csを見てみると、ジャンプ関数がこのようになっています。

f:id:Raspberly:20190629003237p:plain

この関数はどこからも呼ばれておらず、サマリーには「手動で有効にしましょう」と書いてあります。

なので実際に以下のようなコードをOVRPlayerController.cs内あるいは独自スクリプト内に追加しましょう。

OVRPlayerController.csに追加する場合はUpdateController()UpdateMovement()内に記述するのがよさそうです。

独自スクリプトの場合はUpdate()でいいでしょう。

 

ここまでやればジャンプできるようになります。

f:id:Raspberly:20190629010510g:plain


JumpForceを大きくすると瞬時に飛び上がるようになり、
Gravityを小さくするとふわふわと降りるようにできたりもします。

f:id:Raspberly:20190629010531g:plain



 

 

 

 

 

 

 

 

他のアプローチ

@nkjzmさんが詳しく解説しています。
OVRInputから、Touchコントローラーの入力を取得することができるので、
そこから作りたいコンテンツに合わせた最適な移動システムを作ることができます。

qiita.com

 

 

 

 

 

まとめ

VR空間で歩き回りたい時はOVRPlayerControllerを使うとよい

手っ取り早く用意するのであれば、Asset/Oculus/VR/Prefabsにあるプレハブを使うのがおすすめ。

 

 

 

 

おまけ

 

追記:Oculus Linkがあるのならそちらの方がよいです。

 

私は開発環境にALVRを導入しています。
Oculus Rift sの場合はそのままエディタで動作確認ができますが、
Oculus Questの場合はいちいちビルドしなければならずかなり大変です


ALVRなら、Rift sのようにUnity上で実行できSceneビューからも客観的に確認できます。

f:id:Raspberly:20191008013547g:plain

ALVRについてはこちらでも最初の方で簡単に紹介しています。

 

 

 

 

 

公式リファレンスはこちらです。記事執筆時はバージョン1.37です。

https://developer.oculus.com/reference/unity/1.37/class_o_v_r_player_controller/

 

他間違っている箇所、不明な点、わかりにくい点がありましたらコメントにお願いします。

勉強会レポ : Unity道場6月〜新しいPrefabワークフロー入門とVectorGraphics〜

勉強会のレポート(メモ)です。
参加したのはこちら、「Unity道場6月〜新しいPrefabワークフロー入門とVectorGraphics〜」
会場はユニティ・テクノロジーズ・ジャパンさんです。

meetup.unity3d.jp

ハッシュタグ : #Unity道場

 

f:id:Raspberly:20190628063511j:plain



 

 

 

動画はこちら

www.youtube.com

www.youtube.com

 


Unity道場 2019 6月

 

 

 

 

 

1. 新しいPrefabワークフロー 入門

スライドはこちら

learning.unity3d.jp

新しいプレハブワークフローは実質NestedPrefab(ネステッドプレハブ)です
これと和解できるのかどうかというお話を今回はします。

事前アンケート

2018.3以降使っている方は74.4%もいました。
新しいプレハブワークフローを理解している方は20%。

そもそもプレハブとは

インスタンスしたオブジェクトをアセット化する機能
これはアタッチしたコンポーネントなどもまとめてロードしてくれます
また、プレハブを参照して動的に生成することもできる

特徴

・またプレハブの大本を書き換えることで、全てのプレハブも更新できる
・分業しやすい

シーンに配置したプレハブはシーン内で値を変更するとユニークな値になり、
大本の変更を受けなくなる

プレハブの編集方法

2つあります
・シーンに配置後、変更してアプライ
・アセットエディターで編集

2018からプレハブの階層関係を作ることができるようになりました(ネスト)
これでプレハブを持ったプレハブを作ることができます

新機能 Variant

Variant(バリアント)プレハブでは普通のプレハブと同様、個別でパラメータを持たせることができるが、
これは変更してもハンドルが切れることなく、オリジナルの変更を受け取ることができるため、
マテリアルなどサクッと一括変更でき、手軽にキャラクターを量産できる。

 

 


ここまでが基本的な部分

ここからは修羅の道

 

NestedPrefabとハンドル

プレハブはIDしか持っておらず参照しているだけ(Unity4までは全部書き込んでいました)

パラメータを書き換えた時、差分となるその値だけ保持します。
これはNestedでも基本的に同じで、バリアントも基本は同じ。

Nestedではオブジェクト、コンポーネントの順番変更とオブジェクトの削除は追跡できず対応できない。

そのため大きく書き換えるときは、右クリックからUnpackPrefabでハンドルを解除しましょう。

ビルド時の動き

Nestedはビルドすると全部ベイクされます(IDを追っかけたりしない)
バリアントも同様。

参照してる(重複しているように見える)ことはあるが実際に格納されているわけではない。

 

NestedPrefabとの付き合い方

プレハブは必要な項目のみ変更、競合を起こさないように変更しましょう。
変更したパラメータにはは青いマーカーがつきます。
Apply時にどれが変更されているのか確認することがdけいます

プレハブエディターはアセットを直接変更するエディター

つまり差分などは生まれないため、どれを変更したのかが読めない。
そのため競合に注意。

YAML Marge

プレハブを構文的に解析して、競合を起こしている箇所だけをマージしてくれる機能
マイナーですがとてもいい機能です


プレハブエディターではApplyするな

階層構造を持つプレハブを編集した場合、
階層が浅いほど(親に近いほど)影響を受けにくく、深いほど影響が大きい

なので影響をうけるものをできるだけ減らすようにしましょう。

(例えば、孫オブジェクトを変更した場合、それを参照している全ての親プレハブ、子プレハブに影響がでます)

そのためApplyしない方が無難

バリアントはぜひ使ってほしい

エディター拡張を使わなくても一括変更できます

キャラクターなどのモデル変換もバリアントを使いましょう。
ボーンの構造の変更やコライダーの変更も全て追跡してくれます。

バリアントを使う場合、バリアントであることがわかる名前にしておきましょう。
(V〇〇とか〇〇Variantのように)

なぜこんなにバリアントを推すのか

2018.3及び、2018.4では複数選択でプレハブの編集ができないため
(2019.1では復活します)

 

Unity2018.3~2018.4で複数のプレハブを編集したい場合どうするか 

スクリプトを自作することでできます。

こちらも参考になります。

github.com

 

 

 

参考になりそうな資料

tsubakit1.hateblo.jp

light11.hatenadiary.com

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2. VectorGraphicsで作るエモい表現

スライドはこちら

learning.unity3d.jp

 

エモい表現とは

動画で確認してみてください。


VectorGraphicsでできること

SVGのインポート
・ランタイムのメッシュ生成
※2018.1以降での利用を推薦

パッケージマネージャーからインポートできます。

ベクターグラフィック

画像には2つあります。
ラスター形式:点が大量に並んで構成される。jpegpngはこっち。
ベクター形式:位置や色を数値で記録したもの、引き延ばし時はラスタライズされるためきれい。


SVGのインポート

パッケージをインストールするとそのままD&Dするだけでプロジェクトに入ります。
昔は専用のアセットを使わないとインポートできなかったらしい。


普通のスプライトとの違い

SVGは元がテキストなのでとても軽い。

じゃあSVGはどこでも使えるかというとそうでもない。
複雑な形状を含まない画像と相性がよい、

 

ランタイムのメッシュ生成

詳しい手順は動画で確認してみてください。

 

 

単純で規則的な図形であればシェーダが速くて良いが、
式に落としにくいものや、有機的な表現であればVectorGraphicsでやるのがよい

 

 

エモいUI

・UI
インフォグラフィック
モーショングラフィックス

こちらも動画がわかりやすいので確認してみてください。

動画編集ソフトとの比較

動画作品をつくるのであれば専用のソフトを使った方がいい。

ただ圧倒的に機能が足りていないため動画作品を作るときは専用ソフトを使った方がいい。
特定のエフェクトやローディング画面でのアクセントで使う分にはいいと思います。

 

 

 

 

 

懇親会

 

f:id:Raspberly:20190628070802j:plain

f:id:Raspberly:20190628070815j:plain



 



 

タイムライン

 

 

 

 

 

 

 

 

 

過去のUnity道場まとめ

raspberly.hateblo.jp

raspberly.hateblo.jp

raspberly.hateblo.jp

raspberly.hateblo.jp

raspberly.hateblo.jp

 

間違っている箇所がありましたらコメントにお願いします。

執筆中【Oculus Quest開発メモ】Spherecastで物を掴む Distance Grabber 編【Unity】

執筆中です。

もうしばらくお待ちください

 

 

 

6/28追記

すみません、なかなかいい資料が見つからず大変苦戦しております。
もう少しお待ちくださいませ。何か知見をお持ちの方はぜひコメントにお願いいたします。

 

 

10/24日追記

まだわからない。

目星をつけたのはこのあたり。
・Playerのコライダーが邪魔をしている可能性
・レイヤーの設定がおかしい可能性

 

1回目の掴みは正常に動くが、2回目以降がおかしい現象がおこっています。
1回目に掴んだGrabbableが、投げた後も何故か保持されてしまう。
別のGrabbableを掴もうとしても、最初に掴んだGrabbableしか掴めない。

 

 

 

 

今回はOculus Questの開発ネタをやっていきます。
内容的にはOculus Rift Sなどにもそのまま応用できるかと思います。

 

前回の記事の補足になります。まだの方はこちらからどうぞ。

raspberly.hateblo.jp

 

 

 

 

 

 

 

f:id:Raspberly:20190616202258p:plain

 

 

 

開発環境

Windows 10

Unity 2018.4.1f

Oculus Integration ver1.37

Oculus Quest

 

 

先行研究

www.youtube.com

 

 

セットアップ

前回の記事をあらかじめ見ておいてください。

raspberly.hateblo.jp

前提として、Project内にAssetStoreからOculus Integrationをインポートしておく必要があります。


 

 

 

 

サンプルシーンの確認

Assets/SampleFramework/Usageに様々なサンプルシーンがあります。
離れた物を掴むサンプルシーンはDistanceGrabになります。
学習や挙動の確認にとても有益です。見てみましょう。

f:id:Raspberly:20190610220845p:plain

 

実行してみるとこんな感じになります。

 

f:id:Raspberly:20190610225504g:plain

 

 

 

DistanceGrabberのGrab判定にはSpherecastを使用することができます。

 

Spherecastは簡単に説明すると、球体の形をしたRaycastです。

 

 

 

 

主要コンポーネント

こちらもOVR Grabber&Grabbable同様Oculus側でコンポーネントが用意されています。
そちらを使っていきましょう。
これらはインポートしたOculus Integrationの
Assets/Oculus/sampleFramework/Core/DistanceGrab/Scriptsにあります。

DistanceGrabber

こちらは物を掴む側、つまり手につけるコンポーネントになります。

DistanceGrabbable

こちらは物を掴まれる側、つまりオブジェクト側につけるコンポーネントになります。

Grab Manager

こちらは物を掴む範囲を決めるコンポーネント、DistanceGrabberを使うのに必須です。

 

 

 

DistanceGrabber

DistanceGrabのシーンにある、DistanceGrabを見てみましょう。

f:id:Raspberly:20190611213013p:plain

f:id:Raspberly:20190611213643p:plain

OVR Grabberコンポーネントがついているのがわかります。
手にあたるオブジェクトにはこのコンポーネントが必要です。
(Rigitbodyも必要)

 

このコンポーネントOVR Grabberを継承して作られています
そのため使い方やインスペクターはOVR Grabberに規準しています。

 

 

インスペクターパラメーター(Spherecast関係のみ)

とても多いです。掴める対象物のことをターゲットと呼称します。

 

Spherecasrt Radius

ターゲットを見つけるSpherecastの半径。
Spherecastを使用している場合、この値が大きいほどターゲットを見つける範囲が大きくなる。

No Snap Threshhold

オブジェクトとの距離がこの値より近い場合は、通常のGrabberと同じように掴みます。
この値より離れている場合は手元に引き寄せます。

Use Spherecast

Spherecastを使ってターゲットを見つけるかどうか。

 

Max Grab Distance

掴むことのできるオブジェクトの範囲。

Grab Objects In Layer & Obstruction Layer

掴むターゲットにするレイヤーの数字。

Player

Playerのオブジェクト、子オブジェクトからGrabManagerのSphereColliderを参照するのに使う。

 

 

 

 

DistanceGrabbable

DIstanceGrabbableに関しては特に変更点はありません。
過去にセットアップしたものをそのまま使う事ができます。

 

 

 

 

GrabManager

これはGrabする範囲を決定するコンポーネントです。これがないとGrabberが動きません
SphereColliderとセットで扱います。(要isTrigger)
サンプルシーンではOVRPlayerControllerの子オブジェクトになっています。
必ずプレイヤーの子オブジェクトにする必要があります

 

Outline Colorから、範囲内のオブジェクトにアウトラインをつけることができます。

f:id:Raspberly:20190616163827p:plain

 

SphereColliderのRadiusの値を変えるだけで簡単に範囲を設定できます。

f:id:Raspberly:20190616163746p:plain

GrabManagerのスクリプト内ではCollider型で参照しているのでSphere以外のColliderも使うことができる・・・
かと思いきや、実はDistanceGrabberがSphereCollider型でGetComponentしているのでSphereしかだめみたいです。

 

 

 

 

実際に掴めるオブジェクトを置いてみる

 

 

 

 

 

まとめ

 

 

 

参考文献

DistanceGrab Sample Scene

Distance Grab Sample Now Available in Oculus Unity Sample Framework | Oculus

 

 

 

 

他間違っている箇所、不明な点、わかりにくい点がありましたらコメントにお願いします。

勉強会レポ : Roppongi.unity #3

勉強会のレポート(メモ)です。
参加したのはこちら、「Roppongi.unity #3」
会場提供は「メルカリ」さんです。

roppongiunity.connpass.com

ハッシュタグ : #roppongiunity

f:id:Raspberly:20190626015329p:plain

 

 

動画はこちらから視聴できます。
後日Unity Learning Materialsにも掲載予定です。

t.co

learning.unity3d.jp

 

 

 

 

LT1. Unityで作ったゲームをDLカードで配布してみた話

なぜDLカード?

同人ゲームは即売会がメイン。
ダウンロード販売のみだと即売会で配布できない。

シリアルコードの認証機構

同じ話を過去にしてるのでこれを見てね。

www.slideshare.net

ダウンロード方式

ダウンロードそのものを縛る方法

シリアルコードを持っている人のみDL可能
違法アップロードに対応できない

ゲーム内の機能解放でやる方法

ゲーム自体は誰でも落とすことができ、シリアルコードで機能を解放する方式

機能解放にはユーザの認証機能が必要です。
ニフクラと自前のサーバーを用意してやりました。

こういう方式は手間がかかるのでオススメしないです。

ダウンロードカードの話

カードどう作るのか、Adobe製品でやるのが正攻法。
今回はUnityでやりました。

結果

手でやるより業者に任せた方がよい。

Unityでごり押しするよりAdobe製品に頼りましょう。

 

 

 


LT2. UnityでARアプリを作る時に面倒なことを解決する

ペチャバトというARゲームを会社でやっています。

ARアプリは主観的な体験なため、アプリ上で起こっていることを全て把握することはできません。

・基本的に動作確認はプレイモードでやりましょう
・ログ出力を積極的にしましょう

客観的にAR空間を見る方法

Photonを使ってプレイモードと同期させて確認する方法をとりました。
プレイモードで動作確認できるときはできるだけデバックしないようにしましょう。

 

これをPhotonを使わずに同期できるライブラリを開発中です。 

 

 

 

 


LT3. ML-Agentsの簡単な環境構築

一番の挫折ポイントは環境構築

ML-Agentはインストールしなければならないものがたくさんあります
そこで環境構築はDocker Composeを使いましょう
ML-Agentは機械学習フレームワークです

Docukerとは

PCに依存せずLinux環境を作れるツールです。

そしてDocker Composeとは複数のDockerを管理するツールです。
立ち上げるDockerは2つです。

開発環境の構築

やることが3つあります。

1.必要なファイルのコピー

必要なファイルが3つあります
公式リポジトリからコピーしましょう

2.Dockerファイルの準備

公式リポジトリから落としてきましょう
ただし最後のエントリーポイントだけ削除しましょう

3.Docker_Compose.ymlの準備

ここまでやれば、後はコマンドを打ち込むだけで動きます
ただし、コンテナのリソースに依存するため学習パフォーマンスは落ちます
勉強目的ならDocker Composeはオススメです

 

 

 

 


LT4. ReorderableListのすすめ

ReorderableListとは

UnityのEditor拡張の1つ、
GUIでListや配列を操作することができます。

あまりメジャーじゃないし、少し扱いづらい
ドキュメントもない。

Simple Reorderable List

便利だけども扱いづらい、そこでラップして使いやすくしました。

github.com

要素の入れ替え、追加削除が自由にできる。
独自クラスも大丈夫で色も変えれる。

汎用的に使え、シンプルさと見やすさを思想としました。
詳しい使い方はブログの方を参照してみてください

synamon.hatenablog.com

Editor拡張の知見

・EditorGUIはとSerializedPropertyを組み合わせると良い

・SerializePropertyの注意点
Countメソッドを使うとイテレーターが勝手に動いてします。
Copyを作ってそっちをカウントするといいでしょう。

・EditorSkinの考慮

Pro版とPersonal版どっちを使っているのか判定できます
それぞれ色を用意してあげるといいでしょう

 

 

 

 

 

LT5. 無線ジャイロコントローラを自前でUnityに実装

 

会社ではモフバンドを開発。
その中核にあるのがM5Stackというモジュールになります。

M5Stack

ESP32を備えた開発モジュール
Bluetoothで通信ができる

やったこと

M5Stackに書き込むファームウェアの作成
送られてきたデータを受け取るdllの作成
dllを組み込んだUnityプラグインの作成
UnityEditorで実行できるよう受け取ったデータをJSonに加工しやり取りするProxy作成

まとめるとこうなります

f:id:Raspberly:20190626003327p:plain

使ってみた感想

送信受信両方書くので敷居が高い

全プラットフォーム対応がつらい

 

 

 

 

 

 

LT6. Androidビルドを自動化しようとして挫折した話

ゼルダはすばらしいゲームです、ぜひともやってみてください。

Unityをやるうえでテラシュールブログさんはとても助かっています。

結論

CloudBuildを使いましょう

Douckerの話

DocukerImageを用意するのが大変
こちらを使うといいでしょう

Docker Hub

他にもめちゃくちゃ手順があり大変
Androidビルドもつらい・・・

そこで私はどうしたかというと、私はCIをあきらめました。

しかし楽はしたいため、エディター拡張でAndroidビルドをする機能を作りました。

まとめ

CIが必要ならCloudBuildを使うといいかも

 

 

 

 

 

 

LT7. Shortcut Manager の仕組みについて

ShortcutManagerとは

Unity2019.1から入った機能
ショートカットを編集できる機能です
View部分はUI Elementで動いています

できるようになったこと

・自由に設定できるようになった
・他のライブラリのショートカットも変更できる
・プロファイルで設定を切り替えることができる

仕組みとしてはプロファイルからマッピングを読み込み、
イベントトリガーに関数を渡しています。

ショートカットの種類

アクション
 普通のショートカット

クラッチ
 押している間動くショートカット

より進化したショートカット

直前の操作の繰り返しや2段階入力のショートカットなど。

二段階入力

入力Aと入力Bで実行されるもの。
(VisualStudioの例で補足すると、Ctr+K、Ctr+Cでコメントアウトができるようなものを指す)

これをやると何がいいのか

・ショートカットの体系化ができます
・外部のショートカットに対応できる

実装方針

キューさえ用意すれば、実装するのは難しいかというとそんなことはなさそう
将来的にはn段階のショートカットもできそうだが、クラッチと競合しそうではある

 

 

 

 

 

 

 

LT8. MagicOnionでマルチプレイゲームを作ってみる

サンプルを作ってみました。触ってみてください。

リアルタイムネットワークエンジンの選択肢はいろいろあります。
これまではモノビットやPhotonを使っていました。

MagicOnionについて

MagicOnion勉強会の資料などを参考にしてみてください。

https://ykimisaki-my.sharepoint.com/:p:/g/personal/y_kimisaki_kimisaki_jp/EX9J_lb_fj1GptYDZ4tX_ZcBanQZ_FfNDIpQDT4wOrZueQ?rtime=5l3fIoX51kg

 

MagicOnionならリアルタイム通信もAPI通信も同じくC#で書けるのが強み。

チュートリアルが容易されているので動かしてみるといいです。
しかし次のステップはどうするか・・・
そこでMagicOnionを使ったアクションゲーム風サンプルプロジェクトを作りました。

作ったサンプル

ルーム管理
キャラクターの同期
テキストチャット

作ってみて

かなり自由だが、Photonなどで用意されていたサクっと作れる機能はないので自作が必要。

 

 

実は今月初頭にMagicOnion勉強会というものがありました。
そちらのレポも残っているので興味のあるかたはどうぞ。

raspberly.hateblo.jp

 

 

 

 

 

 

 

懇親会

今回はお菓子持ちより制です。

f:id:Raspberly:20190626015416p:plain

f:id:Raspberly:20190626015514p:plain

f:id:Raspberly:20190626020553p:plain

 

 

 

 

 

 

 

 

 

告知タイム

書籍発売「Unityサウンド エキスパート養成講座」

前から告知されていました、一条さんの手掛けるUnityオーディオ完全に理解できる書籍が発売です。
会社に1冊、自宅1冊置きましょう。Amazonのページからドシドシ予約注文してください。

Unityサウンド エキスパート養成講座

Unityサウンド エキスパート養成講座

 

 

Gotanda.unity#13

次回の会場はサイバーエージェントさんになります。
既に埋まっていますが、もしかしたら増員できるかもしれないの参加登録よろしくおねがいします。

meetup.unity3d.jp

 

Unity++ 〜ショートセッション勉強会 presented by Unity部〜

豪華メンバーによるショートセッション勉強会です。

meetup.unity3d.jp

 

Unite2019 前々夜祭

Uniteの週の月曜日(祝)にLT大会を予定しています。
(まだ調整段階なので内容が変更になることもあります)

 

 

 

 

これまでのRoppongi.unityはこちら

raspberly.hateblo.jp

raspberly.hateblo.jp

 

 

 

 

間違っている所、消してほしいツイートなどがありましたらコメントにお願いします。

【Oculus Quest開発メモ】物を掴むとき位置と角度を固定する Snap Offset編【Unity】

今回はOculus Questの開発ネタをやっていきます。
内容的にはOculus Rift Sなどにもそのまま応用できるかと思います。

 

銃などを掴む時、取っ手やグリップなど特定のポイントを握るようにしたいと思うことがあると思います。
そういう時はGrabbableについているSnap機能を使うと便利です。 
今回は、とても使い方がわかりにくいことで評判のSnapOffsetについて解説していきます。

f:id:Raspberly:20190624002232p:plain



 

 

2019年9月13日追記

よりわかりやすく解説した補足記事を投稿しました。
こちらも合わせてどうぞ。

raspberly.hateblo.jp

 

 

 

 

 

 

開発環境

Windows 10

Unity 2018.4.1f

Oculus Integration ver1.37

Oculus Quest

 

 

 

 

セットアップ

このメモは前回の続きとなります。
まだの方は先にこちらからどうぞ。

raspberly.hateblo.jp

 

 

使用アセット

今回使用したアセットを紹介します。

刀アセット Wakizashi

f:id:Raspberly:20190623233924p:plain

http://u3d.as/1vSL
高品質な刀です。AssetStoreまとめさんでも紹介されていました。

www.asset-sale.net

ハンドガンアセット

f:id:Raspberly:20190623234141p:plain

http://u3d.as/1jZw

弾丸やマガジンも含まれたハンドガンのアセットです。

 

 

 

 

 

 

サンプルシーンの確認

Assets/SampleFramework/Usageに様々なサンプルシーンがあります。
今回も前回と同じAvatarGrabシーンを改造していきます。

が、今回のSnapOffset機能はDistanceGrabシーンで活用されているのでそちらも併せてどうぞ。

raspberly.hateblo.jp

 

 

 

 

物を持つ時に特定の場所を掴んでほしい

前回の記事では物を持った時にGrabbableのコライダーの範囲内であればどこでも掴んで持つことができました。
しかし、銃や刀のように掴んでほしい位置や角度が明確である場合どうすればいいでしょうか。
刀の場合、刀身部分を掴めるのはあまり好ましくありません。柄を握ってほしいはずです。

f:id:Raspberly:20190623191401g:plain

 

そこで、OVR Grabbable及びDistance Grabbableには物を掴んだ時に位置や角度を矯正する機能があります。
その機能がSnapOffsetです。

 

 

 

OVR Grabbable

OVR Grabbableコンポーネントを見てみると、
SnapPositionとSnapOrientationの項目が確認できます。
ここにチェックを入れると掴んだ時に、SnapOffsetの所に入っているTransformに合わ移動します。

f:id:Raspberly:20190608224838p:plain

 

 

 

 

 

 

 

Snap Offset

このSnapOffsetのTransformの設定ですが、まずOVR Grabbableな3Dオブジェクトに、
掴んでほしいポイントを示す空のゲームオブジェクトを子オブジェクトにする。

f:id:Raspberly:20190623195155p:plain



f:id:Raspberly:20190623190439p:plain

そしてこの空のゲームオブジェクトをSnapOffsetとして登録すれば掴んだ時に位置や角度が矯正されます。

f:id:Raspberly:20190623195233p:plain



 

・・・と思った方が多いかと思います
実はこのやり方は間違いです。

 

 

この手順だと正常にスナップされません。
掴んだ時に位置や角度がおかしな場所になります。

f:id:Raspberly:20190623201114g:plain



 

 

 

 

 

Snap Offsetの本当の使い方

UnityForumの方にもこの問題点が取り上げられていました。

https://forum.unity.com/threads/vr-oculus-sdk-touch-controller-snap-position-snap-offset-grab-a-gun.512853/

正しい使い方は以下に記しますが全く直感的ではない使い方です。

 

Snap Offsetの正しい使い方

1. Unityのシーン内のPosition(0, 0, 0)、Rotation(0, 0, 0)の場所に空のゲームオブジェクトをつくる

f:id:Raspberly:20190623202917p:plain

2. このオブジェクトを矯正させたい位置や角度分だけ値を変更する

f:id:Raspberly:20190623210751p:plain

3. このオブジェクトをSnapOffsetとして登録する

f:id:Raspberly:20190623195233p:plain

以上となります。

 

 

実際にOffsetさせてみる

上記の手順通りに実際にやってみます。
まずはPosition、Rotationともに0のゲームオブジェクトを作り、これをSnapOffsetとしてみます。

f:id:Raspberly:20190623202917p:plain

 

最初のやり方と違い無事手にスナップされました。
Position、Rotationが0の場合はこうなります。

f:id:Raspberly:20190623213318g:plain



次にRotationを変えてみます。Xを-60にしました。

f:id:Raspberly:20190623210751p:plain

すると、掴んだ時の角度が矯正されます。

f:id:Raspberly:20190623213455g:plain

これをひたすら動作確認しながら調整する必要がありますが非常に面倒です。

 

 

 

 

 

 

ベストプラクティス(このやり方がオススメ)

ここのベストプラクティスを@nkjzmさんが紹介していました。

 

結論からいいますと、Snap OffsetはNone(何も設定されてない状態)のまま
掴みたいオブジェクトのレンダラーの座標や角度を調整します

 

銃の場合ですと、Grabbableがアタッチされている親オブジェクトはそのままに、
子オブジェクトの銃の3Dモデルの位置を調整します。

f:id:Raspberly:20190623223015p:plain

 

剣の場合はこちら、剣はRorationのxを-60にするといい感じになります。

f:id:Raspberly:20190623223205p:plain

実際に動作確認して細かく調整する必要はでてきます。

 

 

これで完成です。きちんと手の形に収まるようになりました。
刀を見てみると、刀身を掴もうとしても柄の部分に矯正されているのがわかると思います。

f:id:Raspberly:20190623225845g:plain

 

 

 

 

 

 

まとめ

SnapOffsetはnullのまま、3Dオブジェクト側の座標を調整しよう

 

 

 

 

 

参考資料

 

qiita.com

 

 

 

 

 

 

他間違っている箇所がありましたらコメントにお願いします。

【Oculus Quest開発メモ】掴めるオブジェクトにクロスヘアを表示する Grabbable Crosshair編【Unity】

 

今回はOculus Questの開発ネタをやっていきます。
内容的にはOculus Rift Sなどにもそのまま応用できるかと思います。

 

前回はDistance GrabberとGrabbableで離れた場所にあるオブジェクトを掴みました。

しかしこれには欠点があります、それは掴もうとしているオブジェクトがどれなのかわからない問題です。

f:id:Raspberly:20190623125141g:plain

サンプルシーンでは、オブジェクトにアウトラインを付けることで解決していました。
しかしサンプルシーンにはもう一つ、
オブジェクトにクロスヘアをつける方法がありますのでこちらを解説していきます。

 

 

 

開発環境

Windows 10

Unity 2018.4.1f

Oculus Integration ver1.37

Oculus Quest

 

 

 

セットアップ

この記事は前回の記事の補足になります。
まだ見ていない方はこちらからどうぞ

raspberly.hateblo.jp

 

 

サンプルシーンの確認

Assets/SampleFramework/Usageに様々なサンプルシーンがあります。
離れた物を掴むサンプルシーンはDistanceGrabになります。
学習や挙動の確認にとても有益です。見てみましょう。

f:id:Raspberly:20190610220845p:plain

 

前回もこちらのサンプルシーンを使いましたが、今回注目すべきは右側のテーブルにあるキューブです。
こちらのキューブには予めクロスヘア機能が組み込まれています。

f:id:Raspberly:20190622010859p:plain

 

 

 

 

主要コンポーネント

今回もOculusに標準搭載されているコンポーネントを使用していきます。

GrabbableCrosshair

クロスヘアを表示するコンポーネントで、Grabbableの子オブジェクトにアタッチします。
有効化されたクロスヘアはUpdate内で常にプレイヤーの方を向き続けます

このクロスヘアに使用しているCrosshairZCheatシェーダーはオブジェクトの上にレンダリングされるように、プレイヤーに向かって少し移動しています。
ただし、オブジェクトサイズによっては機能しないこともあります。

 

 

Grabbable Crosshair

このコンポーネントがやっていることは至極単純、3つのステートを切り替えるだけです。

ステートはEnum型で定義されており、
・Disabled ターゲットクロスヘア、イネーブルクロスヘア共に無効化
・Enabled ターゲットクロスヘアを無効化、イネーブルクロスヘアを有効化
・Targeted ターゲットクロスヘアを有効化、イネーブルクロスヘアを無効化
に分かれます。

インスペクターパラメーター

f:id:Raspberly:20190622002548p:plain

Targeted Crosshair

 ターゲットクロスヘア、既に照準が合っていてすぐに掴める状態の時にActiveにするオブジェクト。

Enabled Crosshair

 イネーブルクロスヘア、掴むことができるオブジェクトだが、照準が合っていない状態の時にActiveにするオブジェクト。

 

これらのステートはDistanceGrabberが管理していますが、
何らかの理由で外部からステートを変えたい場合はSetState関数から設定することができます。
ただしGet関数はないので取得することはできません。必要な場合は自分で付け加えましょう。

 

 

 

 

 

 

 

 

実際にクロスヘアを表示してみる

それでは実際にクロスヘアを表示してみましょう。
前回の記事でユニティちゃんを置いた所の続きからやっていきます。 

まだの方はまずそちらからやってみてください。

raspberly.hateblo.jp

 用意できない場合は、サンプルシーンに置いてあるキューブを使ってみてください。

 

 

ユニティちゃんを格納しているゲームオブジェクトに新しく空のゲームゲームオブジェクトを子として追加します。
この子の名前を「Crosshair」とします。

f:id:Raspberly:20190621233855p:plain

Crosshairのインスペクターから、GrabbableCroshairコンポーネントをアタッチします。

f:id:Raspberly:20190622000338p:plain

 

TargetCrosshairの作成

ここまできたら次にクロスヘアオブジェクトを作っていきましょう。
Crosshairの子オブジェクトにCreateObjectからQuadを追加します。
このQuadの名前は「Targeted」にします。

f:id:Raspberly:20190622000704p:plain

f:id:Raspberly:20190622000943p:plain

するとユニティちゃんのモデルにQuadが重なる形で配置されると思います。

f:id:Raspberly:20190622000844p:plain

インスペクターを見てみましょう。

f:id:Raspberly:20190622001236p:plain

この中の内、MeshColliderは不要なのでRemoveComponentしておきましょう。

注目すべきはMeshRendererです。
ここのMaterialsを「TriangleCursorTargeted」に変更します。

f:id:Raspberly:20190622001451p:plain

するとクロスヘアが表示されます。

f:id:Raspberly:20190621233344p:plain

 

大きさを調整しましょう。
このままではクロスヘアがとても大きいのでスケールを調整します。

f:id:Raspberly:20190622003049p:plain

f:id:Raspberly:20190622003404p:plain

 

最終的なTargetedのインスペクターはこうなります。

f:id:Raspberly:20190622003745p:plain

 

 

EnableCrosshairの作成

基本的にターゲットとほとんど同じです。Duplicateで複製してから少しインスペクターをいじるだけです。
複製する場所はTargetedと同じCrosshairの子にします。
複製したら名前を「Untargeted」に変えておきましょう。

f:id:Raspberly:20190622004644p:plain

後はインスペクターのMeshRendererから、Materialsを「TriangleCursorUntargeted」に変えるだけです。

f:id:Raspberly:20190622004336p:plain

 

 

Grabbable Crosshairに登録

最後に親オブジェクトCrosshairにあるGrabbable Crosshairコンポーネントに、
先ほど作ったTargetCrosshairとEnableCrosshairを登録します。

f:id:Raspberly:20190622005001p:plain

これでクロスヘアは完成です。

 

 

 

動作確認

クロスヘアが常にカメラを向いているのがわかります。

f:id:Raspberly:20190622010247g:plain


また、手を向けて掴める状態になるとクロスヘアが変化することが確認できます。

f:id:Raspberly:20190622010331g:plain




 

 

まとめ

クロスヘアを表示するには、Grabbable Crosshairを使う

手っ取り早くクロスヘアを用意したいのであれば、
Assets/Oculus/SampleFramework/Udage/DistanceGrab/Prefabs/OutlineItemsの中にある
DistanceGrabCubeCrosshairを使うことをオススメします。

 

 

 

 

 

クロスヘアの演出追加

もう少しクロスヘアの演出を考えたい場合は独自スクリプトを組み込んでみましょう。

f:id:Raspberly:20190623125513g:plain

先ほど説明した通り、クロスヘアはアクティブ化、非アクティブ化で切り替えられています。
そのため、OnEnable()OnDisable()を記述したスクリプトを各クロスヘアにアタッチすることで
演出を簡単につけることができます。

 

一例として、上のGifにもある掴むことのできる範囲内に入ったオブジェクトに対して、
ウインドウをスケーリング表示するスクリプト

 

他には、Updateの中でRotateさせるといった演出もよくあります。

 

 

 

 

クロスヘアのアセット

今回使ったクロスヘアの素材はOculus側で用意されているクロスヘアです。
他にもアセットストアなどで「crosshair」や「hud」と検索すると、
類似の物がたくさんでてくるので探してみてください。

f:id:Raspberly:20190624095535p:plain

 

 


 

 

 

参考文献

Distance Grab Sample Now Available in Oculus Unity Sample Framework | Oculus

 

 

他間違っている箇所、不明な点、わかりにくい点がありましたらコメントにお願いします。