FC2ブログ
ヽ|∵|ゝ(Fantom) の 開発blog? ホーム »Unityオープンソースライブラリ
このページの記事一覧

【Unity】【C#】ランタイム時にファイルをドラッグ&ドロップして取得する(Windows のみ)  


 Unity では標準でランタイム時のファイルのドラッグ&ドロップには対応してないそうで、結局ググって見つけたオープンソースライブラリで解決できたので、同じように検索している人のためにメモとして残しておこう。



(※) Unity 2018.2.1f1 - 2.16f1 / Windows10(x64) で確認



■Bunny83/UnityWindowsFileDrag-Drop をインポートする

 利用するオープンソースライブラリは「Bunny83/UnityWindowsFileDrag-Drop」だ。Git で落としても良いが、実は dll なども一切無く、実際に利用するファイルは C# ファイル1つだけなので(サンプルは除くとして)、zip で落とした方が楽だろう。


 zip を解凍したら、4つのファイルが出てくるのでプロジェクトにインポートする(プロジェクトビューにドロップで良い)。ちなみにドラッグ&ドロップのライブラリは「B83.Win32.cs」だけで、「FileDragAndDrop.cs」はサンプルとなっている。





■簡単なサンプルを作ってみる

 実際にランタイムで試すために、「FileDragAndDrop.cs」を適当にアタッチして、UI-Text にドロップしたファイル名を表示するようにしてみよう。適当に Canvas を作って、Text にドロップしたときのログを出力すれば良いだけだ。コードは元のサンプルコードに少し手を加えて、の Debug.Log() 部分をまるっとコピーすれば良い。




●「FileDragAndDrop.cs」に UI-Text への出力を付け加える
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; //追加
using System.Linq;
using B83.Win32;

public class FileDragAndDrop : MonoBehaviour
{
public Text display; //インスペクタで出力するUI-Textを登録

UnityDragAndDropHook hook;

//ここでドラッグ&ドロップ機能を登録
void OnEnable ()
{
hook = new UnityDragAndDropHook();
hook.InstallHook();
hook.OnDroppedFiles += OnFiles;
}

//ここでドラッグ&ドロップ機能を解除
void OnDisable()
{
hook.UninstallHook();
}

//ここでドラッグ&ドロップされたファイル名とドロップ位置を取得
void OnFiles(List<string> aFiles, POINT aPos)
{
Debug.Log("Dropped "+aFiles.Count+" files at: " + aPos + "\n"+
aFiles.Aggregate((a, b) => a + "\n" + b));

//UI-Text に出力
if (display != null)
{
display.text = ("Dropped "+aFiles.Count+" files at: " + aPos + "\n"+
aFiles.Aggregate((a, b) => a + "\n" + b));
}
}
}




■実際にビルドしてランタイムで試してみる

 「File>Build Settings...」で「Standalone」に切り替えて、作ったサンプルシーンを追加し、「Build And Run」でビルドして起動してみよう。適当にファイルをウィンドウにドラッグ&ドロップすれば、ファイル名が表示されるハズだ。



 とても簡単で、既に「VRM Live Viewer」で実装していて、何の問題も無く利用できている。インポートファイルも少ないので管理も楽だ。

 また、日本語が入ったパス名でも大丈夫のようだ。パス名だけでなく、ドロップした座標も取得できるので、ドロップした UI によって処理を変えるなんてこともできるだろう。これは色々使えると思う。てゆかこの機能はぜひ標準で欲しいね(笑)。





(関連記事)
【Unity】VRM(VRoid)をライブステージで踊らせるアプリを作ってみた
【Unity】【C#】uGUI ドロップダウンの要素をコードで設定と取得、外観のカスタマイズなど


関連記事

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityオープンソースライブラリ  Unityライブラリ 
tb: 0   cm: --

【Unity】【C#】UniRx で「1フレームごと待機して処理」してみる  


 今まで「VRM Live Viewer」では非同期処理に「Await Extensions」というライブラリを使っていたのだが、「UniRx」の非同期処理関連の資料を見てたら、同じようなことができるとわかったので、移行してみようと考えた。


 ただ注意しなくてはならないのは、「UniRx」の非同期処理は Scripting Runtime を「.NET 4.x」にすることと、C# 7.0が必須のため、現時点(Unity2018.2.x)では「Incremental Compiler」を導入する必要があるとのことだ。

UniTask - Unity + async/awaitの完全でハイパフォーマンスな統合

 「Incremental Compiler」はまだ Preview 版のため、商用利用は控えたほうが良いともあるね。まぁ、「VRM Live Viewer」はフリーなのと、色々実験してみたが、安定性にも問題無いようなので(どちらかというと Stable[安定版] が出たら、メソッドの仕様(引数など)が変わって、書き換え必須となることの方が辛いね(笑))、導入を試みてみたら成功した。実際「UniRx」上で使える「UniTask」は「async/await/Task」の上位互換で、現在私が使っている機能もそのまま移行できたので、基本的な使い方ならば、バージョンアップ・正式版が出てもそれほど問題ないとも思う。また今後UI処理などを少し強化したいしね。そういったものは「UniRx」はとても強い(笑)。

 なので、現時点では導入する人は少ないかも知れないが、「.NET 4.x」の非同期処理「async/await/Task」が使えるようになると、コルーチンで書いていたものがスッキリする上に、別スレッドでバックグラウンド処理などもとても簡単になるので、いずれは誰しも使うようになるだろう(笑)。そしてはじめに使いたいのはやはり、今までコルーチンなどで書いていた「1フレーム待機して処理」かなと(笑)。ググったらなぜかあまりハッキリとした答えがなかったので、ちょっと実験してみた感じ。たぶん他の人も同じことを調べるだろうしね。

■「1フレームごとに待機して処理」っぽくなりそうなものを、色々やってみる
 ●コルーチンで1フレームごとに待機して処理(ログ出力のみ。動作の基準)
 ●Observable.NextFrame() で1フレームごとに待機して処理?
 ●Observable.TimerFrame() で1フレームごとに待機して処理(引数=1)?
 ●Observable.TimerFrame() で1フレームごとに待機して処理(引数=0)?
 ●Observable.ReturnUnit().DelayFrame() で1フレームごとに待機して処理(引数=1)?
 ●Observable.ReturnUnit().DelayFrame() で1フレームごとに待機して処理(引数=0)?
 ●UniTask.DelayFrame() で1フレームごとに待機して処理?
 ●UniTask.WaitUntil() で1フレームごとに待機して処理?
 ●UniTask.Yield() で1フレームごとに待機して処理?
■とりあえず「1フレームごとに待機して処理」を簡単に(実験してみた結果)

(※) Unity 2018.2.1f1 / UniRx 6.2.2 / Incremental Complier 0.0.42(Preview) / Windows10(x64) で確認



■「1フレームごとに待機して処理」っぽくなりそうなものを、色々やってみる

 まずは今まで通り、コルーチンで「1フレームごとに待機して処理」をしてみる。処理自体はただのログ出力なので、実際の処理の重さは考慮に入れてない。ちなみに「Await Extensions」では「yield return new WaitForEndOfFrame()」の代わりに「await new WaitForEndOfFrame()」が使える(そしてメソッドに async が使えるので非同期処理が簡潔に書ける。StartCoroutine() もいらない)。


●コルーチンで1フレームごとに待機して処理(ログ出力のみ。動作の基準)
using System.Collections;
using UnityEngine;

public class EachFrameTest : MonoBehaviour {

// Use this for initialization
void Start () {
Debug.Log("(Start) frame : " + Time.frameCount); //1

StartCoroutine(WaitForEndOfFrameCoroutineTest());
}

IEnumerator WaitForEndOfFrameCoroutineTest()
{
Debug.Log("frame : " + Time.frameCount); //1
yield return new WaitForEndOfFrame();
Debug.Log("frame : " + Time.frameCount); //2
yield return new WaitForEndOfFrame();
Debug.Log("frame : " + Time.frameCount); //3
yield return new WaitForEndOfFrame();
Debug.Log("frame : " + Time.frameCount); //4
yield return new WaitForEndOfFrame();
Debug.Log("frame : " + Time.frameCount); //5
}
}

(Start) frame : 1
frame : 1
frame : 2
frame : 3
frame : 4
frame : 5

 なんてことはないコルーチンで順次処理していくときのようなコード(本来は同じ処理ならループにするだろうが、これはあくまでサンプルなので、実際には別々の処理が入ると考えて欲しい)。これを基準として「UniRx」でオペレータなども使って色々試してみよう。なお、ここでは「yield return new WaitForEndOfFrame()」を使っているが、実行タイミングを気にしないなら「yield return null」でも良い。

イベント関数の実行順



●Observable.NextFrame() で1フレームごとに待機して処理?

using System.Collections;
using UnityEngine;
using UniRx;

public class EachFrameTest : MonoBehaviour {

// Use this for initialization
void Start () {
Debug.Log("(Start) frame : " + Time.frameCount); //1

ObservableNextFrameTest();
}

async void ObservableNextFrameTest()
{
Debug.Log("frame : " + Time.frameCount); //1
await Observable.NextFrame();
Debug.Log("frame : " + Time.frameCount); //3
await Observable.NextFrame();
Debug.Log("frame : " + Time.frameCount); //5
await Observable.NextFrame();
Debug.Log("frame : " + Time.frameCount); //7
await Observable.NextFrame();
Debug.Log("frame : " + Time.frameCount); //9
}
}

(Start) frame : 1
frame : 1
frame : 3
frame : 5
frame : 7
frame : 9

 UniRx で一番始めに目についたのは「Observable.NextFrame()」だったが、どうやら await で1フレーム、NextFrame() で1フレーム待機のようだ。フレームが1つ飛びになっていた。期待していた処理とは違う。



●Observable.TimerFrame() で1フレームごとに待機して処理(引数=1)?

using System.Collections;
using UnityEngine;
using UniRx;

public class EachFrameTest : MonoBehaviour {

// Use this for initialization
void Start () {
Debug.Log("(Start) frame : " + Time.frameCount); //1

ObservableTimerFrameTest();
}

async void ObservableTimerFrameTest()
{
Debug.Log("frame : " + Time.frameCount); //1
await Observable.TimerFrame(1);
Debug.Log("frame : " + Time.frameCount); //3
await Observable.TimerFrame(1);
Debug.Log("frame : " + Time.frameCount); //5
await Observable.TimerFrame(1);
Debug.Log("frame : " + Time.frameCount); //7
await Observable.TimerFrame(1);
Debug.Log("frame : " + Time.frameCount); //9
}
}

(Start) frame : 1
frame : 1
frame : 3
frame : 5
frame : 7
frame : 9

 Observable.NextFrame() と結果は同じになった。ではちょっと引数を0にしてみようと実験してみると…


●Observable.TimerFrame() で1フレームごとに待機して処理(引数=0)

using System.Collections;
using UnityEngine;
using UniRx;

public class EachFrameTest : MonoBehaviour {

// Use this for initialization
void Start () {
Debug.Log("(Start) frame : " + Time.frameCount); //1

ObservableTimerFrameTest();
}

async void ObservableTimerFrameTest()
{
Debug.Log("frame : " + Time.frameCount); //1
await Observable.TimerFrame(0);
Debug.Log("frame : " + Time.frameCount); //2
await Observable.TimerFrame(0);
Debug.Log("frame : " + Time.frameCount); //3
await Observable.TimerFrame(0);
Debug.Log("frame : " + Time.frameCount); //4
await Observable.TimerFrame(0);
Debug.Log("frame : " + Time.frameCount); //5
}
}

(Start) frame : 1
frame : 1
frame : 2
frame : 3
frame : 4
frame : 5

 いけた(笑)。これは期待していた処理と合致する。



●Observable.ReturnUnit().DelayFrame() で1フレームごとに待機して処理(引数=1)?

using System.Collections;
using UnityEngine;
using UniRx;

public class EachFrameTest : MonoBehaviour {

// Use this for initialization
void Start () {
Debug.Log("(Start) frame : " + Time.frameCount); //1

ObservableDelayFrameTest();
}

async void ObservableDelayFrameTest()
{
Debug.Log("frame : " + Time.frameCount); //1
await Observable.ReturnUnit().DelayFrame(1);
Debug.Log("frame : " + Time.frameCount); //3
await Observable.ReturnUnit().DelayFrame(1);
Debug.Log("frame : " + Time.frameCount); //5
await Observable.ReturnUnit().DelayFrame(1);
Debug.Log("frame : " + Time.frameCount); //7
await Observable.ReturnUnit().DelayFrame(1);
Debug.Log("frame : " + Time.frameCount); //9
}
}

(Start) frame : 1
frame : 1
frame : 3
frame : 5
frame : 7
frame : 9

 これも Observable.NextFrame() と結果は同じになった。では引数を0にしてみると…


●Observable.ReturnUnit().DelayFrame() で1フレームごとに待機して処理(引数=0)

using System.Collections;
using UnityEngine;
using UniRx;

public class EachFrameTest : MonoBehaviour {

// Use this for initialization
void Start () {
Debug.Log("(Start) frame : " + Time.frameCount); //1

ObservableDelayFrameTest();
}

async void ObservableDelayFrameTest()
{
Debug.Log("frame : " + Time.frameCount); //1
await Observable.ReturnUnit().DelayFrame(0);
Debug.Log("frame : " + Time.frameCount); //2
await Observable.ReturnUnit().DelayFrame(0);
Debug.Log("frame : " + Time.frameCount); //3
await Observable.ReturnUnit().DelayFrame(0);
Debug.Log("frame : " + Time.frameCount); //4
await Observable.ReturnUnit().DelayFrame(0);
Debug.Log("frame : " + Time.frameCount); //5
}
}

(Start) frame : 1
frame : 1
frame : 2
frame : 3
frame : 4
frame : 5

 これもいけた。これは期待していた処理と合致する。実装自体は Observable.TimerFrame() とは違うみたいだけどね。



●UniTask.DelayFrame() で1フレームごとに待機して処理?

using System.Collections;
using UnityEngine;
using UniRx;
using UniRx.Async;

public class EachFrameTest : MonoBehaviour {

// Use this for initialization
void Start () {
Debug.Log("(Start) frame : " + Time.frameCount); //1

UniTaskDelayFrameTest();
}

async void UniTaskDelayFrameTest()
{
Debug.Log("frame : " + Time.frameCount); //1
await UniTask.DelayFrame(0);
Debug.Log("frame : " + Time.frameCount); //1
await UniTask.DelayFrame(0);
Debug.Log("frame : " + Time.frameCount); //2
await UniTask.DelayFrame(0);
Debug.Log("frame : " + Time.frameCount); //3
await UniTask.DelayFrame(0);
Debug.Log("frame : " + Time.frameCount); //4
}
}

(Start) frame : 1
frame : 1
frame : 1
frame : 2
frame : 3
frame : 4

 せっかくのなで、UniTask も試してみた。するとあれ?なぜか初めの1回は待機されてない。なんか理由があるのだろうけど、今回は放おっておこう(←誰か調べて(笑))。こちらは「using UniRx.Async;」が必要。



●UniTask.WaitUntil() で1フレームごとに待機して処理?

using System.Collections;
using UnityEngine;
using UniRx;
using UniRx.Async;

public class EachFrameTest : MonoBehaviour {

// Use this for initialization
void Start () {
Debug.Log("(Start) frame : " + Time.frameCount); //1

UniTaskWaitUntilTest();
}

async void UniTaskWaitUntilTest()
{
Debug.Log("frame : " + Time.frameCount); //1
await UniTask.WaitUntil(() => true);
Debug.Log("frame : " + Time.frameCount); //1
await UniTask.WaitUntil(() => true);
Debug.Log("frame : " + Time.frameCount); //2
await UniTask.WaitUntil(() => true);
Debug.Log("frame : " + Time.frameCount); //3
await UniTask.WaitUntil(() => true);
Debug.Log("frame : " + Time.frameCount); //4
}
}

(Start) frame : 1
frame : 1
frame : 1
frame : 2
frame : 3
frame : 4

 UniTask.DelayFrame() と同じ結果になった。これもはじめの1回が待機されてない…?ま、まぁ、今回はコルーチンでの表記をそのまま代替できる書き方を探していただけなので(パフォーマンスなども考慮に入れてない)、これで勘弁してやろう(笑)。誰かそのうち調べてくれるだろうと期待してる(←投げっぱなし(笑))。



●UniTask.Yield() で1フレームごとに待機して処理?

using System.Collections;
using UnityEngine;
using UniRx;
using UniRx.Async;

public class EachFrameTest : MonoBehaviour {

// Use this for initialization
void Start () {
Debug.Log("(Start) frame : " + Time.frameCount); //1

UniTaskYieldTest();
}

async void UniTaskYieldTest()
{
Debug.Log("frame : " + Time.frameCount); //1
await UniTask.Yield();
Debug.Log("frame : " + Time.frameCount); //1
await UniTask.Yield();
Debug.Log("frame : " + Time.frameCount); //2
await UniTask.Yield();
Debug.Log("frame : " + Time.frameCount); //3
await UniTask.Yield();
Debug.Log("frame : " + Time.frameCount); //4
}
}

(Start) frame : 1
frame : 1
frame : 1
frame : 2
frame : 3
frame : 4

 これも UniTask.DelayFrame() と同じ結果になった。これもはじめの1回が待機されてない?
 本来はメインスレッドに切り替えたりPlayerLoopに同期したりするのに使うみたいだが、次のフレームになるので、近い動作になるっぽい。



■とりあえず「1フレームごとに待機して処理」を簡単に(実験してみた結果)

 他にも色々実験している記事もあったが、単純に面倒なので、とりあえず「Observable.TimerFrame(0)」または「Observable.ReturnUnit().DelayFrame(0)」を代替として使うことにしてみた。もしからしたら正しい使い方ではないかも知れないので、static な関数(WaitForFrame)にしておいて、後で書き換えられるようにしておけば、修正も楽かも知れない。「Observable.TimerFrame(0)」は UniRx 特有の「マイクロコルーチン」というものを使っているので(負荷が軽いらしい)、今回はこちらで書いておこう。まぁ、戻値の型の問題はあるが、あくまでコルーチンでの「yield return null」みたいな使い方を想定しているので、今回は気にしないとする(笑)。Observable のように拡張メソッドにしても良いと思うけど(「Observable_Joins.cs」に書くとか)、その辺はご自由に。

●とりあえず1フレームごとに待機して処理
using System.Collections;
using UnityEngine;
using UniRx;
using UniRx.Async;

public class EachFrameTest : MonoBehaviour {

// Use this for initialization
void Start () {
Debug.Log("(Start) frame : " + Time.frameCount); //1

WaitForFrameTest();
}

async void WaitForFrameTest()
{
Debug.Log("frame : " + Time.frameCount); //1
await WaitForFrame();
Debug.Log("frame : " + Time.frameCount); //2
await WaitForFrame();
Debug.Log("frame : " + Time.frameCount); //3
await WaitForFrame();
Debug.Log("frame : " + Time.frameCount); //4
await WaitForFrame();
Debug.Log("frame : " + Time.frameCount); //5
}

public static IObservable<long> WaitForFrame()
{
return Observable.TimerFrame(0);
}
}

(Start) frame : 1
frame : 1
frame : 2
frame : 3
frame : 4
frame : 5

 「Observable.TimerFrame()」だと戻値の型が long となっているので、Unit にしたいなら、以下のようにしても良いかも知れない(まぁ、今回の使い方のように、捨て値なら無駄な処理が増えるだけだが…)。

●戻値を Unit に変えた例
public static IObservable<Unit> WaitForFrame()
{
return Observable.TimerFrame(0).AsUnitObservable();
}


 こちらの記事にも書いてあるけど「コルーチンをほぼ駆逐」できると表記がすっきりし、しかもコルーチンと違って、別スレッド動作や非アクティブなオブジェクトでも動くので(というより、MonoBehaviour に依存しないで動作できるので)、いずれは「async/await」的な書き方の方が主流になるかもね。「VRM Live Viewer」は商用アプリにするつもりは無いし、実験的にやってみることに意義があると思ってるので(ファイルドロップ→非同期なファイル読み込みは既に実装されてる)、前のめりで新しい機能を導入していきたい(笑)。

(参考)
Unity UniRxとasync/awaitでフレーム管理
UniRx.Async機能紹介
UniTask - Unity + async/awaitの完全でハイパフォーマンスな統合
Unityにおけるコルーチンの省メモリと高速化について、或いはUniRx 5.3.0でのその反映





(関連記事)
【Unity】VRM(VRoid)をライブステージで踊らせるアプリを作ってみた


関連記事

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityオープンソースライブラリ  Unityライブラリ  実証実験 
tb: 0   cm: --

【Unity】【C#】Android で VRM(VRoid)を動的に読み込む  


 VRM Live Viewer にも利用しているが、元々は「プラグインを使って VRM を Android で読み込めるか?」という実験をしてみたら、スンナリと行けてしまったので次々とアイデアが浮かび、VRM Live Viewer をリリースするまでに至ってしまったという…(タイムスタンプを見ると、試しにライブステージ導入してから、アプリリリースまで4日しかかかってない←夢中になるといつの間にかアプリを完成させてしまうことも多い(笑))。


 まぁせっかくなので、VRMVRoid を Android でも読み込み、利用する方法を書いておこう。ちなみに VRM は VRChat やバーチャルキャストで使われるアバターフォーマットではあるが、リアルタイムで読み込むことができるので、あらかじめモデルをアプリに入れてビルドする必要もなく、読み込みもそれほど時間はかからないので、応用範囲は広いと思う。

 私は Unity4 の時代から MMD を Unity で動かしたり、一般公開されているモデルを実験で使ってたりしてたが、Unity ではいつもキャラのバリエーションが少ないな~と感じていたので、VRM で動的に読み込めるのは画期的だとさえ思う。例えば RPG でもアクションでも、好きなキャラで遊べるゲームとかも作れそうだしね(もちろん、大きさやコライダの判定などの問題もあるが、あくまで可能性として(笑))。アイデアは常に新しい発想から生まれるので、既成概念に捕らわれずに色々やってみると良いと思う。それがいつか新たな作品に繋がる。

 今回はあくまで Android で VRMVRoid を読み込む方法だけだが(どちらも "~.vrm" で扱うとして)、私が試したところ、一度 Unity 内に読み込んでしまえば、プラットフォームに関係なく扱えると思うので(見た目はシェーダなどのせいで多少変わることもあるが)、ひとつの方法として覚えておけば色々活用できるだろう。ちなみに VRM Live Viewer は Android版と Windows版を出しているが、ファイル読み込みやダイアログなどプラットフォーム固有のもの以外は全て同じだ。実際にシーン1つだけでビルドしている。つまり複数のプラットフォーム対応も簡単にできることがわかる。


(※) Unity 5.6.3p1 - 2018.2.1f1 / UniVRM 0.40 - 0.43 / VRoid Studio 0.1.1 - 0.2.8 / Windows10(x64) / Galaxy S7 Edge (Android 7.0) で確認



■UniVRM をインポートする

 Unity で VRM を読み込むには UniVRM というオープンソースが必要となる。ライセンスは「MIT License」となるので、その辺りは各自で確認して欲しい。ちなみにライセンス形態にも色々あるが、MIT License は比較的緩いライセンスだ。ついでに参考資料も載せておこう。

(参考)
GPL, LGPL, BSD などのOSSライセンスの違いと注意点まとめ
知らないと損をする6つのライセンスまとめ



 なお、新規プロジェクトで Android プラットフォームでビルドして試すなら、パッケージをインポートする前に「File>Build Settings...」であらかじめ「Switch Platform」で Android プラットフォームに切り替えておいた方が良いかも知れない。UniVRM に内包されているシェーダ(MToon 等)を再コンパイルしたりするのに結構時間がかかる(笑)。


 プロジェクトの準備ができたら、まずは UniVRM をダウンロードしよう。今回はアプリに動的に VRM を読み込むので UniVRM の本体「UniVRM-x.xx_xxx.unitypackage」(xxx はバージョンなど)の他に「UniVRM-RuntimeLoaderSample-x.xx_xx.unitypackage」のインポートも必要になる。本体「UniVRM-x.xx_xxx.unitypackage」を先にインポートしてから、ランタイムローダ「UniVRM-RuntimeLoaderSample-x.xx_xx.unitypackage」をインポートしよう。とりあえず VRM の動的読み込みに必要なものはこれだけで良い。






●API のアップデートが促されたら、「Go Ahead!」する




■VRM を動的に読み込んでみる

 UniVRM のインポートが終わったら、次にプロジェクトビューで「Assets/VRM.Samples/Scenes」で、シーン「VRMViewer」を開いてみよう。ビューワ自体は PC 用なのだが、これを改造することにより、Android 等他のプラットフォームの読み込み方法もわかると思う。



 ちなみに「VRM Live Viewer」はこのシーンを元ベースとしている(見た目もたいして変わってないのでわかると思うが(笑))。他の VRM 利用アプリを見てみると、たぶん同じようにこれを改造してるものが多い気がする。エクスポートできるアプリを作るなら、シーン「VRMRuntimeExporterSample」あたりを見てみると良いと思う。せっかくのオープンソースなのだから、遠慮なく使わせて頂こう(笑)。


 このシーンでは左上部にある「Open」ボタンを押すことにより、VRM を動的に読み込んで、シーン上にモデル(アバター)をロードすることができる。ただ、Windows 上なら 「PC, Mac & Linux Standalone」プラットフォームになってればそのまま使えるが、Android では無視される。この辺りから少し改造していこう。


1.スクリプトとしてはヒエラルキーで「Canvas」をクリックして、インスペクタで表示される「Viewer UI」にそのコードが書かれている。これを編集しよう。グレーアウトしてる「Script>ViewerUI」をダブルクリックすれば、Visual Studio で開かれる(シングルクリックなら、プロジェクトビューで移動できる)。



2.「ViewerUI.cs」を開いたら、検索で「OnOpenClicked」を探してみよう。これが前述した「Open」ボタンのイベントハンドラとなっている。ここのコードを見てみるとプリプロセッサディレクティブ(#if~文)でプラットフォームが分けられている。とりあえず Unity エディタ上でもテストできるようにディレクティブ(UNITY_EDITOR_WIN)を付け加えておこう。

void OnOpenClicked()
{
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
var path = FileDialogForWindows.FileDialog("open VRM", "vrm", "glb", "bvh");
#else
var path = Application.dataPath + "/default.vrm";
#endif
・・・(略)・・・
}

 ちなみに「UNITY_EDITOR_WIN」とは「Unityエディタ上でかつ Windows である場合の条件」である。プラットフォーム依存コンパイルを上手く使えば、複数のプラットフォームを分別することも可能だ。まぁしかし、コードは見づらくなるので、機能まるごとみたいな場合は、クラスごとに用意するという手もある。今回は一部を改造して使うので、この方法でやっていこう。

プラットフォーム依存コンパイル


3.「UNITY_EDITOR_WIN」を入れたら、グレーアウトしていた文字が見えるようになったと思う。しかし「FileDialogForWindows.FileDialog」の方にエラーが出たかも知れない。まぁ、これも同じプラットフォーム依存なので、「FileDialogForWindows」部分にカーソルを合わせ、「F12」を押せば、クラスがまるごとグレーアウトしてるのがわかる。手順2と同じように「UNITY_EDITOR_WIN」を #if~文に追加しよう。

#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
using System;
・・・(略)・・・
#endif

namespace VRM
{
public static class FileDialogForWindows
{
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
#region GetOpenFileName
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class OpenFileName
{
・・・(略)・・・
}
・・・(略)・・・
#endif
}
}


 これでコンパイルが通るようになったと思う。一旦、Unityエディタに戻ってプレイしてみよう。「Open」ボタンを押して適当な「~.vrm」を読み込んで見ると良い。VRMニコニ立体で多く配布されているので、いくつかダウンロードしておくと良いだろう。「ニコニ立体ちゃん」ことアリシア・ソリッドはとても軽いのでテストするにはもってこいだ。自分で作った VRoid でも可能だが、髪の毛などメッシュが多いものほど、生成に時間がかかるようだ(なので「VRM Live Viewer」では非同期読み込みの方を利用している。非同期読み込みを使うには「.NET4.x」にする必要があるので、ここでは割愛)。

ニコニ立体ちゃん (VRM)





■VRM の動的に読み込みを Android に対応させる

 VRM を動的に読み込みに成功したなら、後は Android に対応させるだけだ。ファイル選択などはプラットフォームに依存するので、先に出てきた「FileDialogForWindows」のようなものが必要になるが、Unity の標準機能には無いので、ここではプラグインを使うことにする(自分で作ったものがあれば、それでも良い)。



 ここで紹介するプラグインは元々私がブログで公開していたものだが、様々なアプリで利用して貰えてるようなのでアセットストアにも提出したというものだ(既に GooglePlay 等で公開されてるアプリなどにも利用されている。「〇〇というアプリを作ってるんですが、使わせて貰って良いですか?」と聞かれるようになったので、気兼ねなしに使えるようにアセットストアにも出したという経緯もある)。AssetStore版GoogleDrive版に機能的な違いはないので(AssetStore版 はアセットストアの規約に合わせただけ)、どちらを利用しても構わない(※ここでは AssetStore版を例にしている)。



 セットアップは以前の記事にあるので、そちらを参照して欲しい。AssetStore版GoogleDrive版では一部ファイル名やパス、素材が違うくらいで、内容的には同じだ。注意点は「Plugins」フォルダを「Assets」直下に移動し、「Plugins/Android」フォルダにあるサンプルのマニフェストファイル(AndroidManifest.xml)を用意しておくということだ(テストだけなら、"AndroidManifest_demo.xml"[AssetStore版]、または"AndroidManifest_test.xml"[GoogleDrive版]を複製してリネームすれば良い)。

AssetStore版のセットアップ
GoogleDrive版のセットアップ


1.プラグインのインポートとセットアップの準備が済んだら、プロジェクトビューの検索で「StorageOpenFileController」のプレファブを見つけよう。見つけたら、これをヒエラルキーに置き、後述のコードを書くことにより、Android でもファイルの情報を受け取れるようになる。本来なら Android でストレージの読み取りなどにはパーミッションなども必要になるが、前述のデモのマニフェスト("AndroidManifest_demo.xml"など)を使ってる分には既に含まれている(「READ_EXTERNAL_STORAGE」または「WRITE_EXTERNAL_STORAGE」が必要。デモにはそれ以外の権限も含まれているが、通常は不要な権限は削除した方が良い→ユーザーにインストを拒否られる確率が高くなるため)。

※Unity2018 以降、Android 8.0 以上を対象にしている場合は、「File>Build Settings...>Player Settings...>Other Settings>Configuration>Write Permission」を「Exernal (SD Card)」にするか、「Android アプリでパーミッション(権限)要求をする」でパーミッション要求をした方が良いかも知れない(Unity2017 のときと違い、自動で出なくなった(?))。

(パーミッション)
Android アプリでパーミッション(権限)要求をする
READ_EXTERNAL_STORAGE(ファイル読み取り権限)
WRITE_EXTERNAL_STORAGE(ファイル読み書き権限)



2.次に「StorageOpenFileController」で取得したファイル名を受け取るハンドラを、元のコード「ViewerUI.cs」の「OnOpenClicked」に追加しよう。書き方は前述のコードに追加する形となる。Android の場合ディレクティブは「UNITY_ANDROID」となるので、それを追加し、「StorageOpenFileController」でストレージを開くコードを Android プラットフォーム用に書いておこう。「using FantomLib;」を入れておくことを忘れずに。

プラットフォーム依存コンパイル

using FantomLib;

・・・(略)・・・

void OnOpenClicked()
{
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
var path = FileDialogForWindows.FileDialog("open VRM", "vrm", "glb", "bvh");
#elif UNITY_ANDROID
var path = "";
StorageOpenFileController storageOpenFileController = FindObjectOfType<StorageOpenFileController>(); //ここはインスペクタで登録できるようにしても良い
storageOpenFileController.Show(); //実機ではエクスプローラのようなもので、ファイル選択ができるようになる
#else
var path = Application.dataPath + "/default.vrm";
#endif
if (string.IsNullOrEmpty(path))
{
return;
}
・・・(略)・・・
}

※この例はやっつけ的なコードなので、「StorageOpenFileController」をインスペクタで登録できるようにしたり、任意にまとめたりして使って下さい(笑)。


3.ランタイム時では「StorageOpenFileController」は閉じられてから、コールバックで結果(選択されたファイルパス名)が返ってくるので、「UNITY_ANDROID」ディレクティブ内ではパスを空(path = "")にしていることに注意して欲しい。これはすぐ下にある「string.IsNullOrEmpty(path)」で一旦終了することを意味する。

 なので、取得したパスを受け取るハンドラを作成する必要がある。ここでは簡略のため、元の「OnOpenClicked()」内のコードを一部まるっとコピーして、もう1つ「OnStorageOpenFile()」というメソッドを定義した(メソッド名は任意)。

public void OnStorageOpenFile(string path)
{
if (string.IsNullOrEmpty(path))
{
return;
}

var ext = Path.GetExtension(path).ToLower();
switch (ext)
{
case ".gltf":
case ".glb":
case ".vrm":
LoadModel(path);
break;

case ".bvh":
LoadMotion(path);
break;
}
}

※UniVRM v0.40 以前は拡張子分岐は無いが、同じように「LoadModel(path)」を呼べば良い。

 実際には「StorageOpenFileController」をインスペクタで登録できるようにしたり、拡張子による分岐などは重複してるので「OnOpenClicked() → OnStorageOpenFile(path)」へ行くように書き換えても良いだろう。その辺りはお任せする(笑)。とりあえずはコード自体はこれで良い。


4.後はヒエラルキーに戻って「StorageOpenFileController」のコールバック「OnResult」に先程の「OnStorageOpenFile(String)」に登録しよう。これで一応完成である。ただし、実機でしか確認できないので、Android ビルドして動作確認してみよう。



5.「File>Build Settings...」を開いてシーン「VRMViewer」を追加してビルドしよう。ビルドに関してはいくつか注意点があるので、以下を参照して欲しい。

「要求 API Level」の設定
シーンを追加してビルドする
Unity 2018.1.0~1.6 での Gradle ビルドにおいて、「Cannot read packageName from~(パス)\AndroidManifest.xml」と出る。




 ここまでできれば、例えば以前の「VRoid(VRM)を動かす」のようにして、ゲームに使うことも可能だろう。1つ1つの技術は結構手間のかかるものだと思うが、プラグインも含め、全て無料でできるので、これを使わない手はない(笑)。今までにない新たな利用法を考えてみるのも良いだろう。

●実機(Android)で「ニコニ立体ちゃん (VRM)」を読み込んでみた所

ニコニ立体ちゃん (VRM)
(c) DWANGO Co.,Ltd. ニコニ立体ちゃんライセンス


 今回はただ VRM を読み込んで動的にアバターを召喚(笑)しただけだが、実際にスマートフォンで利用するには画面解像度・回転の対応やピンチなど、使い勝手を良くした方が良いだろう。プラグインにはそういったスマホらしい操作(ピンチ・スワイプ・ロングタップ等)の例も入っている。VRM Live Viewer の Android 版はまさにその使用例なので、動作確認にインストして動かしてみるのも良いだろう(またはプラグインのデモもQRコードからインストできるようにしてあるので参考に)。











(関連記事)
【Unity】VRM(VRoid)をライブステージで踊らせるアプリを作ってみた
【Unity】VRoid(VRM)をインポートして動かす
【Unity】Unity2018.3.2 にアップグレードすると見た目がおかしくなることがある
【Unity】AssetStore版 FantomPlugin のセットアップ
【Unity】Androidのトーストやダイアログ、通知、音声認識、ハード音量操作など基本的な機能を使えるプラグインを作ってみた


関連記事

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: VRM  VRoid  Unityオープンソースライブラリ  Unityプラグイン  C# 
tb: 0   cm: --

【Unity】VRoid(VRM)をインポートして動かす  


 VRoid Studio が 8/3 に一般公開されたのでさっそく触ってみた。


 VRM 形式は VRChat が流行った経緯もあり、3Dアバターファイルフォーマットとして新たに MMD とは別に VR 用として利用できるフォーマットだ(そのためか VRoid 上では A ポーズだね(笑))。Unity 向けの C# による標準実装(UniVRM)がオープンソースで提供されていて、簡単に扱えるということなので試してみた。

 実際にとても簡単で、ざっくり説明しておくと、UniVRM の Unity パッケージが配布されているので、それをプロジェクトにインポートし、VRoid Studio で作ったキャラをエクスポート(*.vrm ができる)。保存した VRM ファイルをプロジェクトにインポート(ドラッグ&ドロップでOK)すれば良い。あとは見た目が少しおかしくなったりするので、その辺りを適当に修正し、以前にやった方法で歩かせたりすれば動かせる。そんな感じだ。


(※) Unity 5.6.3p1 - 2018.2.1f1 / VRoid Studio 0.1.1 - 0.2.3 / UniVRM 0.40 / Windows10(x64) で確認



●VRoid Studio から VRM を作成する

1.まだ VRoid Studio をインスールしてないなら、公式サイトからダウンロードして、インストールしよう。ページの下の方へ行くと、Windows版 と Mac版 の両方がある。アーカイブを解答したら、そのフォルダ(ファイル)ごと移動すれば使えるようだ。

VRoid Studio

 ただ、私がバージョン 0.1.1 と 0.2.0 を試した所、保存したデータが完全互換では無いようだ(というか髪の位置がずれる)。またインストしたフォルダが別れていると(「VRoidStudio-v0.1.1-win」「VRoidStudio-v0.2.0-win」のように)起動時の「開く」メニューの一覧には出てこない(そして起動後には他のデータを読み込めない)。キャラを作り込むのは正式版が出てからの方が良いかも知れない(笑)。まぁ、現在はベータ版なので、今後改善されることを願おう。

●ver.0.1.1 で作ったもの


●ver.0.2.0 で読み込んだら髪の位置がずれた(笑)

※「髪型編集」で「手描きグループ1」を選択肢、「ガイドパラメータ>高さ」を調整すると直るようだ。


2.「新規作成」でキャラを作った場合は少なくとも髪だけは付けておこう。実際最初に髪を塗るのが面倒だったので(笑)、そのままデフォルトでエクスポートしてみたが、Unity で読み込んだら髪の部分だけ空の白いメッシュが重なってしまった。面倒だったらアホ毛一本でも良いかも知れない(笑)。


3.後はとにかくキャラができたらファイルのメニューからエクスポートするだけだ(ver.0.2.x 以降は「撮影・エクスポート」に移動した)。また、私が試したのは ver0.1.1 だったが、アプリが不安定なのか、閉じようとしたらフリーズしたりするので、なるべく途中経過は保存(Ctrl+S)しておいた方が良いかも知れない。

 エクスポートしたファイル(*.vrm)は「C:\Users\(ユーザー名)\Documents\vroid\avatars」(※Windows版)のように、個人用のドキュメント以下に作られるようだ。


※下のボタンが見えない場合は、ウィンドウを広げれば見えるようになる




●VRM を Unity にインポートする

1.Unity のプロジェクトを開いたら、まずは先に変換ツール「UniVRM」をプロジェクトにインポートしよう。

UniVRM

 パッケージは「UniVRM-x.xx.unitypackage」と「UniVRM-RuntimeLoaderSample-x.xx.unitypackage」(x.xx はバージョン)の2つがあるが(掲載時点:0.40)、「~RuntimeLoader~」となってる方は、実行時にリアルタイムに読み込む方法のようだ。ここでは「UniVRM-x.xx.unitypackage」の方をインポートして欲しい。


 「API Update Required」ダイアログが出たら「I Made a Backup. Go Ahead!」(自動でアップデート)で良い。



2.UniVRM のインポートが終わったら、VRoid Studio でエクスポートした VRM ファイルを適当なフォルダでも作って(ここでは「Model」としている)、エクスプローラーから(※Windowsのとき)ドラッグ&ドロップしよう。インポートにはしばらく時間かかるが、変換が完了したら、ドロップしたフォルダにプレファブができる


「NormalMap settings」が出たら「Ignore」の方が良いかも知れない。「Fix now」でも構わないが、インポート(変換)したマテリアルがギラギラとする(NormalMap を手動で直すしかない)。私はその辺りはあまり詳しくないのでお任せする(←とりあえず動けば良い人(笑))。
(※ver.0.2.x 以降では修正されてるようなのでどちらでも可。)



3.あとはプレファブをヒエラルキーに置いて、カメラやモデルの位置を調整すれば良い。ここではカメラの Z軸を -2 に、モデルの Y軸の回転を 180 度にしてカメラに写している。


※「NormalMap settings」は「Ignore」にしている




●VRoid(VRM)キャラを動かす

 VRMのインポートに成功したら、キャラを動かしてみよう。基本的には以前に書いた「SDプロ生ちゃんを動かす!」と同じ方法で良い。大まかに説明すると、歩行モーションなどのアニメータや、キー入力を判定するスクリプトをモデルにアタッチすれば良い。ただ、一から作るのは結構大変なので、とりあえず既存のアセットやスクリプトを利用して動かしてみよう。

1.歩行モーションなどはユニティちゃんのアセットを利用するので公式サイトからダウンロードしよう。サイトにアクセスして、画面右上の「DATA DOWNLOAD」を押し、規約を読んだら一番下の方にある「ユニティちゃんライセンスに同意しました。」をチェックし、「データをダウンロードする」でダウンロードページへ移動できる。ここでは「ユニティちゃん 3Dモデルデータ」を押してパッケージをダウンロードして欲しい。

 また、ここでは余談になるが、ユニティちゃんパッケージは Unity4 時代からリリースされているので、ユニティちゃん自体を使いたいときは、「ユニティちゃんシェーダー (Unity 5.4/5.5β 対応版)」や「ユニティちゃんスクリプト(Unity 5 修正パッチ)」もダウンロード&インポートした方が良い。

ユニティちゃん公式


2.パッケージをダウンロードしたら、プロジェクトにインポートしよう(掲載時点:UnityChan_1_2_1.unitypackage)。
インポートしたら、ヒエラルキーに置いた VRoid のモデルをクリックし、インスペクタで「Animator>Contoller」に「UnityChanLocomotions」をセットしよう。エディタでプレイしてみればわかるが、これだけで立ちアニメーションが再生される(わかりづらいかも知れないが、拡大してみると、ゆっくりと呼吸してるようにアニメしている)。



3.アニメーションするようになったら、次に操作できるようにスクリプトをアタッチする前に、ヒエラルキーで空のオブジェクトを作り(Creat Empty:ここでは「VRoid_Locomotion」としている)、その子要素になるように VRoid モデルをドロップしよう。また、親オブジェクト(VRoid_Locomotion)の Position や Rotation などは全て (0, 0, 0) にしておく(微調整はモデルの方の Transform でやる)

 これはそのモデルを変更したくなったとき、簡単に中身だけ変えられるようにしておく処置だ。VRoid Studio 本体もしばらくはアップデートされるだろうし、その互換性も微妙なようなので、このようにしておくと更新時に非常に楽になる。



4.VRoid モデルを空オブジェクトの子要素に置いたら、次に操作スクリプトを親オブジェクト(VRoid_Locomotion)にアタッチしよう。ここではユニティちゃんの操作スクリプト「UnityChanControlScriptWithRgidBody.cs」に少し修正を入れて、他のキャラでも使えるようにした「UnityChanControlScriptWithRgidBodyForAny.cs」スクリプトをアタッチする。そのスクリプトは以下からダウンロードして欲しい。

>>サンプルのスクリプトをダウンロード
(Google Drive を利用。画面右上にあるダウンロードアイコンを押す)


5.スクリプトをアタッチしたら、「Rigidbody」の「Constrains>Freeze Rotation」と「Capsule Collider」の「Center>Radius」「Height」だけは調整しておこう。シーンビューを平行投影モードにすると調整しやすい。真横からみると VRoid モデルは少し足が埋まってしまうようなので(※VRoid Studio 0.1.1 で作った場合(?))、ここでは子要素(モデル)の Y軸を 0.07 だけ上げている。値は任意で良い。



●モデルの Position.Y だけ 0.07 にして少し調整している(※VRoid Studio 0.1.1 で作った場合(?))


6.ここまでできたらプレイしても良いが、床が無いので奈落の底に落ちる(笑)。ヒエラルキーに Cube を置いて床にしても良いが、せっかくなので、モックに使えるアセットをインポートしてみよう。

 Unity2017 まではメニューから「Assets>Import Package>Prototyping」でアセットをインポートできたのだが、Unity2018 以降はどうやら「StandardAssets」は廃止されたようだ(たぶんインポートしたアセット同士でバージョンによるエラーや競合などのトラブルが発生しやすいため)。まぁ、オブジェクトだけなら Unity4 時代のものでも問題は無いので(スクリプトやシェーダーは古いバージョンをインポートするとエラーが出やすいので注意)、アセットストアから「Sample Assets (beta) for Unity 4.6」をダウンロードしよう。

Sample Assets (beta) for Unity 4.6


7.ダウンロードが完了したらインポートするときに、ダイアログで一度「None」を押し、全てをオフにしてから、「Prototyping」のフォルダのみをチェックしよう(Prototyping 以下は自動でチェックが入る)。全てをインポートすると時間がかかるのと、エラーが出る可能性があるので、気をつけよう(Unity4 時代のものは特に)。



8.インポートができたら、フォルダ「Standard Assets/Prototyping/Prefabs/」以下に色々なオブジェクトが入っている。床には「FloorPrototype64x01x64」辺りを置けば良いだろう。他にも階段「Step~」、坂「Ramp~」など色々あるので、好きに置いてみると良いだろう。

 ちなみに、Ctrl キーを押しながらオブジェクトをドラッグすると、一定幅で移動することができるので、グリッド状にキレイに配置することができる。この幅はメニュー「Edit>Snap Settings...」で設定できるので上手に使おう。



9.プレイしてみると上手く動いただろうか?動くには動いたが、カメラは追従してないかも知れない。カメラを追従させる方法は、一番簡単なやり方だと、「Main Camera」を作ったキャラの子要素にしてしまえば良い。ヒエラルキーで「Main Camera」を「VRoid_Locomotion」にドラッグ&ドロップしよう。子要素にしたら距離やアングルなどを調整して完了だ。




 カメラをスムーズに動かすには以前の記事「SmoothFollow3」辺りを使うと良い。ちなみにアセットストアで配布しているプラグインにはスワイプ、ドラッグ、ピンチ操作できるスクリプトなども一緒に入っているので、スマホなどで使ってみたいときには良いだろう。




※カメラスクリプト「SmoothFollow3」はプラグインにも同梱されています。





(関連記事)
【Unity】VRM(VRoid)をライブステージで踊らせるアプリを作ってみた
【Unity】【C#】Android で VRM(VRoid)を動的に読み込む
【Unity】Unity2018.3.2 にアップグレードすると見た目がおかしくなることがある
【Unity】SDプロ生ちゃんを動かす!
【Unity】SDユニティちゃんを動かす!(Unity4)
【Unity】【C#】ユニティちゃんをサクっと簡単に動かす!(Unity4)
【Unity】【C#】SmoothFollow3(SmoothFollow に回転・遠近・高さ操作とピンチ・スワイプとの連携機能を付けた拡張版)


関連記事

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: VR  VRoid  VRM  Unityオープンソースライブラリ  サンプル 
tb: 0   cm: --

【Unity】ARCore を使って現実世界にプロ生ちゃんを召喚してみる  


 やっと ARCore の正式版が 2/23 にリリースされたので、さっそくいじってみることにした。というのはベータ版段階では Galaxy S8 や Google Pixel 等の最新機種しか使えなかったんだよね。正式版(掲載時点:ver.1.0.0)の「Supported Devices」では Android 7.0(Nougat) and later となっている。Galaxy S7 Edge(2016/5/19発売)でも使えるみたいだ。

●SDプロ生ちゃんを ARCore で召喚してみた

 ドキュメントはうん、まぁ、英語だよね(笑)。数ヶ月したら日本語化されてたりするけど、はじめは大体こんなもんだ。GearVR作ってみたときもまだ英語だけだった(今は少し日本語化されている)。なのでとりあえず Google翻訳使いながら、機械的に作ってみた。

※バッテリー温度やコンディション等の取得プラグインはこちら(Android の色々な機能を使える Unity プラグイン)


(※) Unity 2017.3.0f3 / ARCore 1.0.0 / Windows10(x64) / Galaxy S7 Edge (Android 7.0) で確認



■開発環境の設定(Setting up your development environment)

※基本的にはここの翻訳である。

1.Android SDK のバージョン 7.0(API Level 24)以上をインストールするには以下のようにする。

Android Studio」をインストールする。

・Android Studio でメニューから「Tools>Android>SDK Manager」で「Android 7.0 (Nougat)」にチェックを入れてインストールする)。


●Android Stuidio の SDK Manager


2.Unity 2017.3.0f2 以上をインストールする(「Personal」(無料)でも良い)。インストールの際には「Android Build Support」にチェックを入れてコンポーネントをインストールする。



※ドキュメントには書かれてないが初回の場合は、インストールした「Android SDK」のパス(Android Studio の SDK Manager を開けばパスがわかる)を Unityエディタのメニュー「Edit>Preferences...」の設定ダイアログの「External Tools」でパスを設定する必要があるかも知れない)。



3.以下のいずれかの方法で「ARCore SDK for Unity」もダウンロードする。

・Unity パッケージ「SDK for Unity」(.unitypackage)をダウンロードする。

・リポジトリから(Gitなどで)Clone する。
git clone https://github.com/google-ar/arcore-unity-sdk.git

4.サポートされているデバイスが必要である。



■デバイスを用意する(Prepare your device)

※基本的にはここの翻訳である。

サポートされているデバイスを用意し、開発者向けオプション」を有効化し、「USBデバッグ」をオンにする


※「開発者向けオプション」を有効化する方法はここを参照



■新規プロジェクトを作成する(Create a new project)

※基本的にはここの翻訳である。

・Unity で「HelloAR」という名前でプロジェクトを作成し(※名前は任意で良い)、「3D」にする。そして「Create Project」ボタンを押す。

※Unity 2017.3.0f2 以上



■SDK をインポートする(Import the SDK)

※基本的にはここの翻訳である。

1.Unity のメニューから「Assets>Import package>Custom Package」でダウンロードした「arcore-unity-sdk-vX.X.X.unitypackage」(X.X.Xはバージョン番号が入る)を全てインポートする(プロジェクトエクスプローラでドラッグ&ドロップでも良い)。



2.Unity のプロジェクトエクスプローラでは SDK のファイルと「Assets/GoogleARCore/Examples/HelloAR」にサンプルシーンが見られる。







■ビルド設定を構成する(Configure the build settings)

※基本的にはここの翻訳である。

・Unity でメニューから「File>Build Settings...」を開く。

・次に以下のように設定する。

1.「Platform」のターゲットを「Android」にし、「Switch Platform」ボタンを押す。



2.「Player Settings」ボタンを押し、開いた「PlayerSettings」を以下のように設定する。

 ・「Other Settings>Rendering>Multithreaded Rendering」をオフにする。
 ・「Other Settings>Identification>Package Name」にアプリ固有のIDとなる Java のパッケージ名を入れる。例えば:"com.example.helloAR" など(※パッケージ名は任意で良い)。
 ・「Other Settings>Identification>Minimum API Level」で「Android 7.0 'Nougat'(API level 24)」以上に設定する。
 ・「Other Settings>Identification>Target API Level」で「Android 7.0 'Nougat'(API level 24)」または「Android 7.1 'Nougat'(API level 25)」に設定する。
 ・「XR Settings>XR Settings>ARCore Supported」をオンにする。





3.「Scenes In Build」にビルドするシーンを追加する。「HelloAR」の場合は、以下のようにして追加する。

 ・プロジェクトエクスプローラで「Assets/GoogleARCore/Examples/HelloAR」を探す。
 ・シーン「HelloAR」をクリックし、「Scenes In Build」にドラッグ&ドロップする(※既にシーンを開いている場合は、「Add open scenes」ボタンでも追加できる)。



■サンプルアプリケーションをビルドして実行する(Build and run the sample app)

※基本的にはここの翻訳である。

デバイスとPCがUSBで接続されていることを確認したら、「Build And Run」ボタンを押す。すると Unityはプロジェクトを Android APK にビルドし、それを自動的にデバイスにインストールして起動する。


●2回目以降は、メニューから「File>Build & Run」(Crtl+B) でダイアログを開かなくてもビルド→アプリ起動できる


※初回起動時にはデバイス(スマホ)側で ARCore のインストール、またはアップデートを促されることがある。



(※以下、ドキュメントをまるっと google翻訳→コピペ)

・あなたのデバイスを移動すると、アプリは自動的に平面を検出し、ダイヤモンドグリッドを描画します。 グリッドをタップすると、Androidロボットが地面に置かれます

Android Logcatを使用してログメッセージを表示するか、Android Device Monitor を使用してデバイスをより包括的に分析することができます。



■次のステップ(Next Steps)

※基本的にはここの翻訳である。

※ARCore を自分のアプリに組み込むには、以下を参照(ARCore の対応機種やインスト状態、アップデートの必要性などの事が書かれている)。

Enable ARCore
ARCore for Unity API Reference



■キャラを入れ替える(オマケ)

 これはただのオマケだが、ヒエラルキーの「Exsample Controller」を選択肢、インスペクタで「Andy Android Prefab」(海外ではドロイド君ではなくて、アンディ君と言うのか(?))のプレファブを入れ替えれば、AR でクリックしたとき出て来るキャラを他のキャラにすることもできる。サイズは原寸(SDプロ生ちゃんは約1m)みたいなので、特にスケールはいじる必要は無いようだ(元がオリジナルサイズの場合)。色々試してみよう。


●他のキャラのプレファブに置き換えるだけでOK



※プロ生ちゃんのインポート・動かす方法はこちら


● Andy君(?)をプロ生ちゃんに入れ替えて、現実世界に召喚してみた
 

●クエリちゃんを現実世界で飛ばしてみたよ!

●ARでけもみみ天国?!

●飛行ARユニティちゃんver ●ARでドラゴンとバトル!

●ARで野外ライブ!?

●フルバージョン

PronamaChan CRS with ARCore from Fantom on Vimeo.









(関連記事)
【Unity】GearVR アプリをビルドする
【Unity】SDプロ生ちゃんを動かす!
【Unity】【C#】クエリちゃんを飛行させる!
【Unity】【C#】ユニティちゃんを飛行させる!




"Query-Chan model" は Creative Commons Attribution 4.0 International License(CC-BY) に基づいて配布されています。

このコンテンツの一部には『ユニティちゃんライセンス』で許諾されたアセットが使用されています。
Portions of this work are licensed under Unity-Chan License


関連記事

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: AR  Unityオープンソースライブラリ  プロ生ちゃん 
tb: 0   cm: --


プロフィール

Social

検索フォーム

全記事一覧

カテゴリ

ユーザータグ

最新記事

リンク

PR