- 投稿日:2020-11-08T21:13:23+09:00
もなふわすい~とる~む in the VRChat
この記事は、もなふわすい~とる~む Advent Calendar 2020の7日目です。
6日目の記事は、izmさんによる「東京都内おすすめグルメマップ (推しの勧めてた店に行ってみた)」でした!
ねこねこチーズケーキは通販もやっているので、ぜひクリスマスのケーキなどに食べてみてください!TL;DR
VRChatのアバター・ワールドアップツールであるUnityのインストールから、ワールドを作成しVRchatへワールドをアップロードするまでのワークフローを解説する記事です。
この記事は、公式のドキュメントに含まれる内容を、日本語に訳し図を加えて解説したものです。Creating Your First Worldに、この記事に書いてある内容はすべて書いてあります。
リンク先の内容より、日本語での解説+画像のキャプチャによる補足で、少しだけわかりやすくなっています。前提
ワールドをアップロードすることができるのは、Trust LevelがNew User以降なので、VRChatを始めてから少しだけ経っている人向けの記事となります。
また、この記事では静的なワールドの作成及びアップロードにとどまり、UDONやVRSDKのコンポーネントを用いたワールドギミックなどについては取り扱いません。環境設定
VRChatのワールドを作成して、作成したワールドをアップロードするための環境を整えます。
Unity Hub、Unityのインストール
1. Unityのアカウント登録を行います。
2. Unity Hubをダウンロードおよびインストールをします。
3. 後述するVRCHAT SDK3に対応するUnityのバージョンのインストーラ(今回は2018.4.20f1)をダウンロードおよびインストールします。
4. 画面の指示に従って、インストールを進めます。
5. Unity Hubを起動し、インストールしたUnityのバージョンを追加する設定をします。
6. インストールしたUnityのディレクトリ以下にある「Unity.exe」を指定します。
VRCHAT SDK3のダウンロード
- VRCHATSDK3のDownload SDK3 - Worldをクリックし、SDKをダウンロードします。
Unityプロジェクトの作成
- VRCHAT SDK3のダウンロードの項でダウンロードしたSDKのファイルをダブルクリックしてプロジェクトにインポートを行います。
ワールドの作成
シーン上にVRCWorld(Assets/VRChat Examples/Prefabs/VRCWorld.prefab)というプレハブを配置します。
画面下部の青枠に囲われた、青色のまm立方体のアイコンを、画面左のタブ内にドラッグアンドドロップをすることで配置することができます。
シーン上にPlaneを配置します(作成時の状態がPositionが0,0,0以外の場合があるので、注意してください。)
画面左のHierarchyタブ内で右クリックをし、表示されたメニューの「3D Objects > Plane」を選択することで配置することができます。
ここまでで、VRChatにアップロードする最低限の要素はそろいました。
ワールドのアップロード
表示されたVRChat SDKウィンドウのAuthenticationタブを開き、VRChatのアカウントでログインをします。
Builderタブを開き、ウィンドウ下部のBuild & Testをクリックします。
- 表示された入力フィールドに、ワールドの説明などを入力したりし、チェック項目を確認しチェックを入れたりし、最後にUploadをクリックします。
ワールドに入ってみる
テスト
アップロードする際に、Builderタブの「Online Publishing」ではなく、その上の「Local Testing」の「Build & Test」をクリックすることで、アップロード前に自分だけが入ることができるワールドでテストをすることができます。
Private
SteamでVRChatのクライアントを起動し、WorldタブからMineの欄を探します。
Public
New Userだと、Publicにアップロードできません。。。
下記の画像の緑色の枠内の部分に、チェックを入れられるようになり、チェックを入れることでPublicでアップロードすることができます。
VRChat+に加入すれば、すぐにアップロードできるようになるのかな?試したら記事更新します。
https://docs.vrchat.com/docs/vrchat-community-labs感想
いかがでしたか?
解説する記事と言いながら、VRChatのワールドのアップロードは初めてだったので、わからないことは調べながら書きました。
ギミックを実装しなければノンコーディングで完結するので、Clusterと同様に簡単にできますね!Unity AssetStoreやBoothの3Dモデルを組みあわせて、君だけの最強のもなふわすい~とる~むを作ろう!
(年末年始の休暇中にPublicでもなふわすい~とる~むをアップロードしなおします。よろしくお願いします。)本当は、もなふわすい~とる~むに由来するものを置いたワールドを作成しPublicで公開するまで終えたかったですが、ひとまずここまで(随時更新していきます。)
もなふわすい~とる~む Advent Calendar 2020の8日目の記事は、バーチャルHigh Performance C#erもといスーギ・ノウコ自治区さんの「C# Source GeneratorによるAOSOAを活用したDOTSプログラミング補助の試みとそのUnityにおける敗北」です。
果たして、彼女は敗北の先に何を見たのか?最後に推し語り
巻乃もなかさんに出会って、大体1年くらいが立ちました。
はじめの出会いは、Twitterの人が「たすけて!!!もなふわすい~とる~む!!!」と言っているのを見て、そのひとが貼っていた配信のリンクから飛んだのが始まりだと記憶しています。配信を開いて1分くらいは「ふーん、おもしれー女」くらいの感想だったんですが、あいさつしたら「あ、サンマックスさんだ~!」と言われ、その印象は一瞬で「やべー女」に変わりました。たぶん、ふぁぼかRTか何かの通知から名前を見かけられていたんでしょうけど、すごいですよね。すごい。。。配信に来るかどうかもわからない人の名前を覚えられる・・・?
たしか、その初めましての配信ではバイクだったか工具だったかの話題に触れられていて、自分の前職がその手の職だったり、趣味でバイクに乗っていたことも併せて、とても惹かれる配信内容でした。
息継ぎもせずに語られるそのフルスロットルなトーク、その趣味に通じている人なら「こいつ、わかっている」と思わせる、浅くない内容。僕が「バイクの排ガスのにおい良いよね」とコメントすると「2stのにおいすき~!」と返される。思わずニヤリとしてしまいました。
そのほかにも、女の子らしい(最近はこういう表現は憚られますが、前述の話題とのギャップもあって、あえて女の子らしいと表現します)「最近みつけたコンビニスイーツ」や「動物の話(猫やカニ、ゴリラ(どうして?))」、「お星さまの話」など様々なジャンルでトークを展開しています。
また、「お星さまの話」といえば、巻乃もなかさんの趣味の一つに「天体観測」もあります。
これも前述のバイクと同じように「オッ」と思わせる内容です。以下、参考リンク
みんなもハマろうレンズ沼端書ですが、これにてもなふわアドベントカレンダーの7日目の記事を締めたいと思います。
後日談というか今回のオチ
もなふわアドベントカレンダー 26日目です。
25日目は巻乃もなかさんの記事でした!以下、7日目の続き。
VRChat+に登録したら、「New User」から「User」を飛び越え「Known User」になりました!
ということで、さっそく作成したワールドをPublicにアップロードしてみました!(アップロードの仕方については前述のとおりです!
)
パブリックリンクはこちらで、ワールドの様子は以下のような感じです!使用したアセットについての紹介
- Suburb Neighborhood House Pack (Modular)
- 家の概観(屋根、床、壁など)、道路などを構成しているアセットです。年末年始セール中で$69→$34.5になっているので、気になった方はぜひ。
- House Furniture Pack
- 上記と同じパブリッシャさんのインテリアのパックです。上記同様年末年始セール中で半額になっています。
- Farm Animals FullPack
- かわいい動物たちのアニメーション付きのモデルが入っているパックです。
- Animating Bunting Flags
- もなふわすい~とる~むの背景をかざるフラッグです。
- Dessert Heaven Pack
- もなふわすい~とる~むの背景を飾るアイスです。
- JSGorilla
- もなふわすい~とる~むの背景をかざるゴリラです。
- Snow Crab (Chionoecetes)
- + もなふわすい~とる~むのゆかいな仲間たちのカニです。探してみてね。年末年始セール中で半額。
- Next-gen Camera
- もなふわすい~とる~むにおいてあるカメラです。
- Cloudy Day Skybox - Vol. 2
- スカイボックスに使用しました。年末年始セール中で30%オフ。
- 14 Arrow Animations
- 矢印です。家の中にある矢印を追うといいことあるよ。
- Deserted Village
- ガレージを抜けた庭にある机に使用しています。年末年始セール中で半額。
- Old Motorcycle PBR
- ガレージにあるバイクです。
- BMW R75
- BMW・R75は、BMW製のサイドカー付きオートバイである。
- 概要
- 主に第二次世界大戦中のナチス・ドイツ軍において使用された。その出自はやや特殊で、オートバイではあるがサイドカーの装着を前提としている。サイドカー側の車輪もレバーで駆動させることができる「パートタイム二輪駆動」構造になっていて、不整地走破性能は当時のサイドカー付きオートバイとしては、非常に高いものであった。
- 戦後、本車両のデザイン、二輪駆動構造を模倣・参考にしたソ連-ロシア製「IMZ・ウラル」や、現ウクライナ製「KMZ-DNEPR」が現在でも製造されている。また、戦後の東ドイツでは、本車のエンジン改良型「AWO-700」というサイドカーも製造されていた。
- なお、後年BMW・R75/5と呼ばれる車種が生産されたが、これは、上記車種とはエンジンのシリンダーレイアウトなどに共通性を見出すことができるものの、実質的には別の車両である。
- Garage Props Collection
- ガレージ内のツールや棚などに使用しています。
- ビール
- ガレージを抜けた庭にあるビールに使用しています。
酒やめろ
— 巻乃もなか⛄️ (@monaka_0_0_7) December 27, 2020- オリジナル3Dモデル Rgray【アルグレイ】
- 前述のワールド紹介に使用しているアバターです。僕の愛用のアバターでもあります。
- 期間限定でベルガモッド(バイク)が付属していました。どこかZX-10Rみのあるバイク。
- Kawasakiはいいぞ。
- 投稿日:2020-11-08T18:18:41+09:00
Unityの非同期復帰の実装を覗いてみた(Async/Await/Coroutine)
WPFの非同期復帰の実装を覗いてみた(Async/Await/Dispatch.BeginInvoke)
のUnity版です。合わせて読んでいただきたい想定です。Unityのコルーチンシステム
Unityの非同期システムは基本的にはイテレーターオブジェクトを転用したコルーチンです。
StartCoroutine(MethodAsync()); IEnumerator MethodAsync() { // メインスレッド yield return new WaitForSecond(10); m_UIText.color = Color.black; // メインスレッド bool isWaiting = true; int result = 0; // メインスレッド new Thread(() => { // ワーカースレッド for(int i = 0; i < 100000000; i++) result += i; // ハチャメチャ重い処理 isWaiting = false; // ワーカースレッド }).Start() // メインスレッド while(isWaiting) yield return null; // ワーカースレッドの処理が終わるまでフレームを送り続ける m_UIText.text = $"RESULT: {result}"; }WPFでは、ワーカースレッド側のコンテキスト(≒スレッド)で
Dispatch.BeginInvoke
を叩くことで、後続のメインスレッドでやって欲しい処理をキューに積んでいました。Unityでは「終わってるかどうかをメインスレッド側から積極的に確認しに行く」という実装ができます。
そして多分このやり方が一般なんじゃないかなと個人的には思います。言葉を濁しているのは、ゲームというアプリケーションの特性上、ワーカースレッドを使うよりもタイムスライス(複数フレームでちょっとずつ進める)や、そもそも待つほど重い処理をすることが稀で待ちが発生するのはディスクアクセスやネットワークアクセス等標準ライブラリで事足りてワーカースレッドを意識しなくてもよい場合が多いからです。そしてそれら標準ライブラリの中身がどうなっているのかは公開されていません。
その代わりに、WPFの
Dispatcher.BeginInvoke
を使った場合だとどんどんネストが深くなっていくのに対して、コルーチンでは結構フラットに書くことができます。内部は公開されていないのですが、おそらく次のような実装になっているものと思われます。(あくまでイメージです)
static void Main(string[] _) { var coroutinIterators = new List<IEnumerator<YieldInstruction>>(); // 終了していないコルーチンのリスト while(true) // 半無限ループ { var frameTime = StopWatch.Start(); foreach(var coroutine in coroutinIterators.ToArray()) { var completed = !coroutine.MoveNext(); var next = coroutine.Current; if(completed) { coroutinIterators.Remove(coroutine); } else if(next != null) { coroutinIterators.Remove(coroutine); coroutinIterators.Add(WaitInstruction(instruction, coroutine)); } } while(frameTime.Elapsed < TimeSpan.FromSeconds(1.0/60)); // 60FPS Repaint(); } } static IEnumerator WaitInstruction(YieldInstruction instruction, IEnumerator<YieldInstruction> continueCoroutinr) { while(instruction.keepWaiting) yield return null; forech(var item in continueCoroutinr) { yield return item; } }AsyncAwaitの動作の実装
UnityでもC#である以上、awaitすると
SynchronizationContext.Current.Post
によってメインスレッドに復帰するということは代わりません。WPFではSynchronizationContext.Current
にDispatcherSynchronizationContext
というDispatcher.BeginInvoke
に流す実装になっていました。Unityではこれに相当するUnitySynchronizationContext
があります。
https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Scripting/UnitySynchronizationContext.cs#L59
m_AsyncWorkerQueue
というのが出てきますが、これは恐らくコルーチンのリストとは別のキューだと思われます。
そしてこのm_AsyncWorkerQueue
の中身を実行しているのがUnitySynchronizationContext.ExecuteTasks
…なのですが、これはネイティブから呼ばれているのでこの先は公になっていないところです。おそらくですが、以下のようなコルーチンがグローバルで走っているイメージなんじゃないかなと思います。StartCoroutine(ExecuteTaskCoroutin()); // エンジンの初期化タイミング(ユーザーコードが走りだす前に) IEnumerator ExecuteTaskCoroutin() { while(true) { UnitySynchronizationContext.ExecuteTasks(); yield return null; } }Coroutine vs AsyncAwait
UnityのC#は周回遅れということもあって、そもそもAsyncAwaitが使えないPJも多々あると思います。
また、長いことコルーチンでやってきた中に現れたAsyncAwaitは眉唾ものとして扱われがちな気がします…
(いやC#に入ったのもう10年前なんですけど…)パフォーマンスの観点からみると、コルーチンはアクティブなコルーチン全てに対して毎フレーム監視をする必要がああります。(さすがにWaitForSecondとかは最適化が入ってそうですが)一方でAwaitでは、毎フレームの監視対象はキュー一つだけで済みます。確かにTaskや取れに類するオブジェクトは軽くはないですが、それはEnumeratorも同じです。故にAsyncAwaitに軍配が上がるケースが大半に思われます。
表現力の観点からみると、コルーチンにはいいところが一つもありません。Awaitでは「戻り値が返せる」「例外を伝播できる」「ラムダ式で書ける」「Task関連の便利ライブラリが使える」などありますが、コルーチンでは一切できません。強いて言うなら普通の配列から
GetEterator
でコルーチンをつくることもできますが、使い道はないでしょう。読みやすさの観点からみると、これは主観に依るところが大きいので何とも言えませんが…。Coroutineではメソッド中でコンテキストが変わってしまう可能性がありませんが、Asyncの場合それがありえます。
ConfigureAwait(false)
は完了後の呼び出し元コンテキストへの復帰を無効にします。こういったけ―スは多くはないでしょうけど。まとめというか余談
実際に中身を覗いてみると、特性がよくわかりますね。
私は今、幸いにもAwait書いてもいいよーな環境にしばらく居るのですが、頑張ってコルーチンこねこねしているところを直すときなどに何か言われそうな気がしてしまします。そういったときにちゃんと説明できないと「やっぱりレガシーの方が良いんじゃないの?」ってなっちゃいますし、コードレビューをする際にも自信をもって「Awaitですっきり書けないでしょうか?」と提案ができるものです。
そんなことを思って書いた二本でした。
- 投稿日:2020-11-08T17:29:03+09:00
Unityでプログレスバー(ライフゲージ)を実装する
プログレスバーとは、よくゲームで見かけるライフゲージとかローディング中とかに使えわれるこんなやつ、
自分で作るのは大変だけど、Unityのアセットを利用したら簡単に実装できる。
動作確認バージョン
Unity 2019.4.13f1
手順
アセットのダウンロード
いろいろあるけど、無料で簡単そうな
ProgressBar Pack
をダウンロード&インポートCanvasでの作業
スクリプト作成
空のGameObjectを作成
Hierachy > + > Create Empty
Scriptを新規作成
project > + > C#Script名前をDemoScriptとしておく。(なんでもいい)
以下のコードを書く
DemoScript.csusing System.Collections; using System.Collections.Generic; using UnityEngine; public class DemoScript : MonoBehaviour { public ProgressBar Pb; public int value = 60; void Update() { Pb.BarValue = value; } }GameObjectのInspector
DemoScript(Script) > Pb に
UI ProgressBar(ProgressBar)
をセット
PLAY
参考サイト
- 投稿日:2020-11-08T17:29:03+09:00
Unityでライフゲージなどに使われるプログレスバーを実装する
プログレスバーとは、よくゲームで見かけるライフゲージとかローディング中とかに使われるこんなやつ、
自分で作るのは大変だけど、Unityのアセットを利用したら簡単に実装できる。
動作確認バージョン
Unity 2019.4.13f1
手順
アセットのダウンロード
いろいろあるけど、無料で簡単そうな
ProgressBar Pack
をダウンロード&インポートCanvasでの作業
スクリプト作成
空のGameObjectを作成
Hierachy > + > Create Empty
Scriptを新規作成
project > + > C#Script名前をDemoScriptとしておく。
以下のコードを書く
DemoScript.csusing System.Collections; using System.Collections.Generic; using UnityEngine; public class DemoScript : MonoBehaviour { public ProgressBar Pb; public int value = 60; void Update() { Pb.BarValue = value; } }
GameObjectのInspector
DemoScript(Script) > Pb に
UI ProgressBar(ProgressBar)
をセット
PLAY
参考サイト
- 投稿日:2020-11-08T16:18:14+09:00
DepthFade(ソフトパーティクル)を利用したシェーダーをUnityで実装する
初めに
DepthFadeでこんなの作れます
シェーダーをアタッチした半透明オブジェクトが、不透明オブジェクトに触れている時、その境界線に色が描画される
DepthFadeとは
元々はUE4のマテリアルノードの一つ
これから描画しようとするオブジェクトの深度と、既に描画されている深度バッファの差を算出して、値に応じて透過処理を行う
これにより半透明オブジェクトが不透明オブジェクトに対して、めり込んだり刺さっているように見える状態を緩和してくれるメリットがある
名前の由来はその名の通り、深度値を利用してフェード処理を行っている所から付けられている因みに全く同じ手法をパーティクルに当て嵌めたものを「ソフトパーティクル」と言い、主に煙のパーティクルなどでめり込みを防いだり重なりを緩和する目的で使われている
DepthFadeの機能を使って交差位置に線を描画する
今回はDepthFadeの「これから描画しようとするオブジェクトの深度と、既に描画されている深度バッファの差を算出して、値に応じて透過処理を行う」部分を利用して「透過処理」を「指定した色の描画に置き換える」という事をする
こうすることにより、オブジェクトの交差部分に境界線を描画する事が出来る
※バリアの境界線や、空間スキャン、水際の境界線などで良く見る表現シェーダーコード概要
UnityのUnlitシェーダーを改造して実装。以下の流れで処理を行っている
※シェーダーコードの一部を抜粋
※シェーダー内で使われている定義関数(ComputeScreenPosとか)については、ページ下部の参考サイトで詳しく説明されているのでそちらを参照「頂点シェーダー」
v2f vert (appdata v) { v2f o; // 3次元座標をクリップ空間座標に変換 o.vertex = UnityObjectToClipPos(v.vertex); // テクスチャスケールとオフセットを考慮した値を格納 o.uv = TRANSFORM_TEX(v.uv, _MainTex); // ワールド座標系のカメラ方向のベクトルを取得する o.viewDir = normalize(WorldSpaceViewDir(v.vertex)); // ワールド空間上の法線を取得 o.normal = UnityObjectToWorldNormal(v.normal); // クリップ空間座標を元にスクリーンスペースでの位置を求める(xyが0~wの値になる) // プラットフォームごとのY座標上下反転問題も修正 o.screenPosition = ComputeScreenPos(o.vertex); // ビュー空間におけるZ値(深度値)をscreenPosition.zに格納 COMPUTE_EYEDEPTH(o.screenPosition.z); return o; }「フラグメントシェーダー(リムライトの処理は無くても問題無し)」
// リム値の取得 inline fixed CalculateRim(half3 viewDir, half3 normal, half fPow, half fMul) { // 視線ベクトルと法線ベクトルの内積を求める half inverse = 1 - abs(dot(viewDir, normal)); // 減衰させるため乗算を行い0~1に丸め込んで返す return saturate(pow(inverse, fPow) * fMul); } fixed4 frag (v2f i) : SV_Target { // メインテクスチャ読み込み fixed4 texColor = tex2D(_MainTex, i.uv); // リムライト計算 fixed rim = CalculateRim(i.viewDir, i.normal, _FresnelPow, _FresnelMul); // デプスフェード計算 float depth = abs(LinearEyeDepth(SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.screenPosition))) - i.screenPosition.z); fixed depthIntersect = saturate(depth / _DepthFadeMul); fixed4 depthIntersectColor = (1 - depthIntersect) * _DepthIntersectColor; /* // 以下はデプスフェード計算をもう少し分かりやすく行ったもの // このシェーダーが実行される前のscreenPos上のカメラ深度値を取得する float depthSample = tex2Dproj(_CameraDepthTexture, i.screenPosition).r; // 深度値をカメラからのワールド空間における距離として取得する(線形化) float depth = LinearEyeDepth(depthSample); // 頂点シェーダーで求めた深度値を引いて、交差部分の値を求める(0になっていると完全に交差している) float screenDepth = abs(depth - i.screenPosition.z); // パラメーターに定義した値で交差値を調整して0~1の範囲に丸める fixed depthIntersect = saturate(screenDepth / _DepthFadeMul); // 1が交差、0が非交差という形にするため1から引いている。その結果に指定した色を反映させている fixed4 depthIntersectColor = (1 - depthIntersect) * _DepthIntersectColor; */ // 出力色設定 fixed4 col = texColor * _FresnelColor * rim + depthIntersectColor; return col; }サンプルプロジェクト
コード全文は以下のプロジェクトを参照してください
※Windows10 + Unity2019.4.11f1で動作確認済み。
※URPプロジェクトを使用していますが、DepthTextureの取得をONにすればStandardプロジェクトやHDRPプロジェクトでも動作すると思います
(逆に言うとDepthTextureをONにしないとURP環境下でも動きません)
https://github.com/madoramu/DepthFade_URP実行結果(UnlitDepthFade.shader, UnlitDepthFade.mat)
ノーマルマップ、マスクテクスチャ付きUVアニメーションを追加したバージョン(Barrier.shader, Barrier.mat)
余談
DepthFadeとソフトパーティクルって手法は全く同じですがどっちが通じやすいんでしょうね・・・?
参考サイト
Depth Expressions
https://docs.unrealengine.com/en-US/Engine/Rendering/Materials/ExpressionReference/Depth/index.html
[UE4] マテリアルノードの解説 その3
http://monsho.blog63.fc2.com/blog-entry-136.html
Unityで水際シェーダー
https://makingt.hatenablog.com/entry/2018/08/31/154247
Shield shader
https://medium.com/@aarhed/shield-shader-85cdaf903db7
[Tutorial] Hexagon Barrier
https://darkcatgame.tistory.com/87
【Unity】Shaderでオブジェクトの交差位置に色をつける
https://www.wwwmaplesyrup-cs6.work/entry/2020/08/11/172850
【Unity】【シェーダ】カメラから見た深度を描画する
https://light11.hatenadiary.com/entry/2018/05/08/012149
ソフトパーティクルの仕組みを応用した表現
https://edom18.hateblo.jp/entry/2019/07/30/091403
Unity のソフトパーティクルのシェーダについて調べてみた
http://tips.hecomi.com/entry/2018/09/15/014050
- 投稿日:2020-11-08T11:11:51+09:00
【Mac】Unity Hubでインストールが失敗した話
今回はMacのUnityHubで新しいバージョンのエディタやモジュールが
インストールできず苦労したので備忘録を書くことにしました。
同じ問題で苦労されている方の参考になれば幸いです。ブログ本文はこちらです。
https://tedenglish.site/mac-unityhub-installation-failed/
- 投稿日:2020-11-08T03:33:06+09:00
EVMC4UとBoltを連携させる
はじめに
拙作のEVMC4UとBoltを連携させたいというツイートを見かけました。
Boltは、最近Unity Technologiesに買収され無償化された、ビジュアルスクリプティング環境です私自身Boltを触ったことがあまりないのですが、手探りで試してみましたので記録しておきます。
環境
- Unity 2020.1.2f1
- EVMC4U v3.7
- Bolt Version 1.4.13 - September 28, 2020
EVMC4Uのセットアップ
EVMC4U v3.7は以下からダウンロードして使用します。
booth
https://booth.pm/ja/items/1801535
もしくはgithub
https://github.com/gpsnmeajp/EasyVirtualMotionCaptureForUnityEVMC4U自体のセットアップは、UnityPackageを導入した直後に出るチュートリアルに従ってください。
Bolt のセットアップ
導入
Boltは、AssetStoreで導入後、PackageManagerから導入します。
Download後、Importできなくて困ったのですが、Toolsから「Install Bolt」をクリックで導入されるようです。
その後、セットアップに入るのですが、重要な手順がいくつかあります。
Programmer Namingを選択してください。
Assembly Optionsは特に変更ありません
Type Options にてEVMC4U関係のTypeを追加してください
完了
作例
MIDI CC値を取り出す
直接取り出せます。
キャリブレーション状態を取り出す
トラッカーの姿勢をTransformにセットする
直接取り出せますが、少し工夫が必要です。
どのデバイスが、どの位置に格納されるかは一定ではないため、リストをスキャンして、予め設定したシリアル番号に一致する姿勢にセットしています。コントローラー情報を取り出す
以下の補助スクリプトを導入してください。
https://github.com/gpsnmeajp/EVMC4U-Bolt-Bridge/blob/main/InputReceiverForBolt.cs適当なオブジェクトにアタッチし、ReceiverにEVMC4UのInputReceiverのGameObjectを登録します。
そして以下のように組むと、スティック操作でオブジェクトが動きます。
#EVMC4U pic.twitter.com/PHJCjcHXKQ
— Segmentation Fault (@Seg_Faul) November 8, 2020入力状態は以下のようにInspectorから確認できます。
執筆時点のバーチャルモーションキャプチャーの動作に合わせて作成しています。