VirtualExperience 解説

背景

2016年のVR元年から4年が経過した2020年、VRの普及率はまだ高くない。

HMDの価格やセットアップの難解さが、未経験者がVRに接するハードルを上げていると思われる。

2019年にOculus Questが発売され VRの敷居がさらに下がったが、それは主にVR経験者にとってであり、

VR未経験者はOculus Questの名前すら聞いたことのない人が多い。このような背景があるVRを、より気軽に体験できるコンテンツを目指す。

コンセプト

VRを通して、家にいながら、綺麗な森、マグマ、海底、街、蝶の飛ぶ幻想的な風景などを体験できる

 

ターゲットユーザー

体が弱く外出するのが難しい人々 や VR未経験者でも気軽にVRを体験でき、安らぐことができるコンテンツ

 制作期間:平日1時間、休日:3〜4時間で2ヶ月

体験人数: 1人

対象:一般 、企業

使用機材:Oculus Quest

Unity Version:2019.2.9f1

※イメージ

制作予定

各ワールドを作成し、プレイヤーの操作によって別のシーンに遷移することで

色々な世界、風景を体験できるようにする。

 

必要な要素は以下

・各ワールド(3Dモデル、テクスチャ、BGMなど)

・UI操作

UI操作

誰にでも気軽に体験できるコンテンツとして、2019年12月にOculus Questで実装されたHand Trackingを使用する。Hand Trackingはコントローラーの代わりにプレイヤー自身の手を使用し操作することができるシステムだ。

Oculusが配信しているAsset Oculus Integration Ver 12.0

を使用することでHandTrackingが簡単に実装することができるので使っていく。※Oculus Questのバージョンを更新しておく必要あり。

①新規プロジェクトを作成しOVRCameraRig Prefabを配置、元からあったCameraは削除する。

②OVRCameraRig Prefabの中にRight/Left Anchorがあるのでその中にOVRHandPrefabを配置 (右手/左手を選択する項目があるので各手に合わせる)

③OVRCameraRig OVR Managerスクリプトがついているので

Hand Tracking Supportを Hands Onlyに設定

これでHand Trackingを使用することが可能となる。

その他設定をすることでHand Trackingでは以下のようなことが行える

  • Objectを押す(手にColliderが付いている)
  • 指でつまむ動作(物を掴むことはできない為、手からUI操作用のレーザーなどを出して、つまむ動作で選択等が主な使用方法のようだ)

コントローラーに比べ、Hand Trackingの操作性はあまり高くない。

Hand TrackingOculus Questの機体前面に付いている4つのカメラから手の位置をトラッキングしている為、カメラに手が映らなくなると手のトラッキングができなくなるからだ。

日常生活において指でつまむといった動作は若齢、高齢にはわかりづらく、上記の理由からハンドトラッキングの認識精度は高くない為、

誰でも簡単にできる手のグー、パーの動作を基本操作とすることにした。


OVR Hand PrefabにはOVRHandスクリプトがついている。

上述したつまむ動作はこのスクリプト内の

GetFingerIsPinching()GetFingerPinchStrength() 関数を使用することで検知可能だ。調べたところ、この関数は各指の伸ばしや曲げ具合を取得できるようなので、グーやパーも実装できる。値を調整することで微調整も可能。


public bool Grab
{
get
{
//人差し指と中指の曲げ検知
return (GetFingerPinchStrength(OVRHand.HandFinger.Middle) >= 0.5f && GetFingerPinchStrength(OVRHand.HandFinger.Index) >= 0.1f);
}
}

public bool TwoFinger
{
get
{
return ((GetFingerPinchStrength(OVRHand.HandFinger.Pinky) >= 0.05f) && (GetFingerPinchStrength(OVRHand.HandFinger.Ring) >= 0.2f));
}
}

public bool Release
{
get
{
return (GetFingerPinchStrength(OVRHand.HandFinger.Thumb) <= 0.01f);
}
}


上記の3つの関数を主に使用する。加えて以下の設定を行う。

  • OVRHand Prefabの配下にSphere(名前をHandに設定)を配置。
  • Mesh Rendererのチェックを外す。
  • Hand Tagを付ける。
  • Sphere Collider isTriggerにチェック

Grabを検知した際にHand ObjectをActiveにすることでUIとHandが接触し操作する。

UI自体は簡単に操作できるようにSphere Objectを使用する。

Sphere Objectに以下のスクリプトをつけることで別のシーンに遷移する


void OnTriggerEnter(Collider other)
{
//接触したオブジェクトのタグが”Player”のとき
if (other.CompareTag(“Hand”))
{
//シーン遷移処理

}
}


メニューの呼び出し

OVRHand PrefabにはOVRSkeletonスクリプトがついており、OVRHandの各指のボーン情報が入っている。これを使用し、指先の位置にSphereを配置する。各Sphereには対応する指のTagを付ける。

以下のSphere5つはSpheresというからオブジェクトで括り、上記記載のTwoFinger関数(手がチョキになったら)が呼ばれたらActiveにする。

左手にもHandPrefab配下にSphereを配置し、Activeになった指先の中指(Middle)と触れたらメニューを呼び出す。


public class handobj : MonoBehaviour
{
// Start is called before the first frame update
public GameObject HandR;
OVRSkeleton script;
public GameObject Sphere;
public GameObject Sphere2;
public GameObject Sphere3;
public GameObject Sphere4;
public GameObject Sphere5;

void Start()
{
script = HandR.GetComponent<OVRSkeleton>();

}

// Update is called once per frame

void Update()
{
Sphere.transform.position = script.Bones[(int)OVRSkeleton.BoneId.Hand_ThumbTip].Transform.position;
Sphere2.transform.position = script.Bones[(int)OVRSkeleton.BoneId.Hand_IndexTip].Transform.position;
Sphere3.transform.position = script.Bones[(int)OVRSkeleton.BoneId.Hand_MiddleTip].Transform.position;
Sphere4.transform.position = script.Bones[(int)OVRSkeleton.BoneId.Hand_RingTip].Transform.position;
Sphere5.transform.position = script.Bones[(int)OVRSkeleton.BoneId.Hand_PinkyTip].Transform.position;

}
}


 

World①紅葉舞う日本庭園

まず、紅葉の木を作成していく。

紅葉の木のモデリングにはフリーの3Dソフト、Blenderを使用する。

Blenderのアドオン、Sapling Tree Genを使用することで簡単に木を作成することができる。

木のモデルは初め以下のようになっているが、設定を行うことで紅葉の木となる。

Photoshop Elementsでテクスチャを作成

 

上記テクスチャを葉として使用すると以下のようになる

 

Oculus Questは中身がAndroidで出来ている為、描画処理能力があまり高くない。現時点で約8万ポリゴンとなっている紅葉の木を大量に配置するとカクツキの原因になる。

そこで以下の紅葉の木は4本までとし、周りの景色は竹柵や360度写真を配置することで描画を軽減することに成功した。

石や石灯篭、鯉なども配置したことでより日本庭園感を増すことができた。

以下画像だと少しみづらいが餌を投げ入れると鯉が寄ってくるようになっている。

配置したものが以下となる。

World②宇宙ステーション

このワールドでは仮想空間でしか味わえない、無重力を体験できるコンテンツとした。ハンドトラッキング と合わせることでより無重力感を味わえる。

宇宙にすることで、物が浮いていても不自然にならず、ハンドトラッキング での操作も自然に行うことができた。今回は基本的なオブジェクトは自作してみた。

基本的には空中のオブジェクトを指先で押したり手で掴んだりといった無重力体験をした後、赤いスイッチを押すことで地球に向かってミサイルが飛び出し破壊する事でオチとしている。

 

自作したオブジェクト

・宇宙ステーション

・ヘルメット

・ペットボトル

・発射スイッチ

など

World③コムローイ祭り

Blenderでモデルを作成し、Standard Assetの火のエフェクトを組み合わせて灯篭を作成、イチョウ同様多数を配置できないので多数の灯篭はテクスチャを貼ったパーティクルで代用しました。

指先で灯篭を押すか掴むかしてうまい具合に灯篭を飛ばす体験が可能となっている。周りの景色は360度写真を使用した。

Nightmare(笑)

VRアカデミーにて行われた「VRハッカソン」チーム制作コンテンツ

ハッカソンテーマ:360度でVRならではの体験ができるもの

テーマが360度ということなので「」と「視線」に重点を置き作成しました。

概要
目の前に現れた3つのドア。
ドアの中では不思議で奇妙な悪夢が待っていた。

コンテンツ解説
プレイヤーは3つのドアから好きなものを選択し中に入ります。
基本的には3つのシーンがあり、ドアを選択することでそのうち2つを体験できます。

シーン内容

スタートシーン
3つのドアから選択する

チキンシーン
鳥のおもちゃが迫ってくる部屋

パンツマンシーン
パンツ男があらゆる方向から襲い来るシーン

お母さんシーン
巨大なお母さんが迫りくるシーン

エンドシーン
ベッドの上で目が覚める
本当に夢だったのか!?

担当範囲
私はパンツマンシーンと各シーンの遷移方法を担当しました。

パンツマンシーン解説

シーンが始まるとパンツマンが目の前に登場します。

しばらくすると視線の方向に設定されたオブジェクト「eyesight」(meshオフで透明)が有効になり
自分の向いた方向のパンツマンが倒れていきます。

eyesightには以下のスクリプトがついており、パンツマンに設定されたEnemy tagを検知すると数をカウントし、数によって次のパンツマン集団を出現させるようにしています。


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class manactive : MonoBehaviour
{
// Start is called before the first frame update

public GameObject Enemypoint2;
public GameObject Enemypoint3;
public GameObject Enemypoint4;
public GameObject Enemypoint5;
public GameObject Enemypoint6;
public GameObject Enemypoint7;
public GameObject Door;
public GameObject field;
public GameObject text;

public int count = 0;

void Start()
{
text.SetActive(false);
}

// Update is called once per frame
void Update()
{

if (count >= 15)
{

Invoke(“appear2”, 3f);

}
if(count >= 25)
{
Invoke(“appear3”, 3f);

}

if (count >= 50)
{
Invoke(“appear4”, 3f);

}
if (count >= 80)
{
Invoke(“appear5”, 3f);

}

if (count >= 90)
{
Invoke(“appear5”, 3f);

}

if (count >= 100)
{
count = 0;
Invoke(“Doorappear”, 5f);
Invoke(“fielddelete”, 5f);
Invoke(“appear7”, 5f);
Invoke(“delete”, 7f);
field.SetActive(false);

}

}

public void appear2()
{
Enemypoint2.SetActive(true);
}

public void appear3()
{
Enemypoint3.SetActive(true);
}

public void appear4()
{
Enemypoint4.SetActive(true);
}

public void appear5()
{
Enemypoint5.SetActive(true);
}

public void appear6()
{
Enemypoint6.SetActive(true);
}
public void appear7()
{
Enemypoint7.SetActive(true);
}

public void delete()
{
Enemypoint2.SetActive(false);
Enemypoint3.SetActive(false);
Enemypoint4.SetActive(false);
Enemypoint5.SetActive(false);
Enemypoint6.SetActive(false);
}

public void Doorappear()
{
Door.SetActive(true);
}

public void fielddelete()
{
field.SetActive(false);

}

void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == “Enemy”)
{

count++;
}

}

}


パンツマンにはRagdollとAudioSource、Animator(走るアニメーション)、プレイヤーに向かって移動するスクリプトがついています。視線を向けられるとパンツマンに付けられた以下のスクリプトによりAnimatorと移動スクリプトが無効化され落下します。プレイヤー側で数を何度もカウントされないようにtagを変更します。

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Businessman : MonoBehaviour
{
// Start is called before the first frame update
public GameObject man;
private Animator animator;

public AudioClip sound1;
AudioSource audioSource;

void Start()
{
//Componentを取得
audioSource = man.GetComponent<AudioSource>();
}

// Update is called once per frame
void Update()
{

}

public void Audiooff()
{
man.GetComponent<AudioSource>().enabled = false;
}

void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == “Tarai”)
{

man.GetComponent<Animator>().enabled = false;

}

else if (other.gameObject.tag == “eyesight”)
{
//音(sound1)を鳴らす
audioSource.PlayOneShot(sound1);
man.GetComponent<Animator>().enabled = false;
man.GetComponent<move_lookat>().enabled = false;
this.tag = “Down”;
Invoke(“Audiooff”, 2f);
}
}

}


 

基本的にはパンツマン登場→視線を向けて倒す

を繰り返し、一定数倒すと次のシーンへの扉が現れる仕組みとなっています。

パンツマンの登場時に効果音(3D音源)をつけることで背後や上下の方向から音がするので、自然とパンツマンの方向を向き、最終的に360度の体験ができるよう工夫しました。

シーン遷移

Scene Controllerを用意し、static変数を設定。

シーン始めにcountをプラス1していき、カウントが2になった状態で遷移するとエンドシーンに遷移するようにしました。

スタートシーン

countを0にリセット

シーン1開始

countに+1

シーン2開始

countにさらに+1で2になる

エンドシーンに遷移

スタートシーンに戻る


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Scenecontroller : MonoBehaviour
{
// Start is called before the first frame update

public static int count = 0;

void Start()
{
count++;
}

// Update is called once per frame
void Update()
{
Debug.Log(count);

}

 

}


各シーンのドアには以下のスクリプトを設定し、上記で設定したcount変数を読み取り、値によって各シーンにランダム遷移(ランダム変数使用)します。

シーン遷移は手にHand タグをつけてドアに入った段階で遷移します。

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using UnityEngine;

public class SceneChange : MonoBehaviour
{
// Start is called before the first frame update
public GameObject gameobject;

// Scenecontroller script;
private int count2;
private int ramValue;

OVRScreenFade fade;
GameObject CenterEyeAnchor;
void Start()
{
CenterEyeAnchor = GameObject.Find(“CenterEyeAnchor”);
fade = CenterEyeAnchor.GetComponent<OVRScreenFade>();
//script = gameobject.GetComponent<Scenecontroller>();
}

// Update is called once per frame
void Update()
{
count2 = Scenecontroller.count;
//count2 = script.count;

}

void OnTriggerEnter(Collider other)
{

if (other.gameObject.tag == “hand”)
{

ramValue = Random.Range(1, 4);
Debug.Log(ramValue);

if (count2 == 2)
{
fade.FadeOut(0.0f, 1.0f);
Invoke(“Scenemove3”, 5f);
}
else if(count2 == 1)
{
fade.FadeOut(0.0f, 1.0f);
switch (ramValue){
case 1:
fade.FadeOut(0.0f, 1.0f);
Invoke(“Scenemove”, 5f);

break;
case 2:
fade.FadeOut(0.0f, 1.0f);
Invoke(“Scenemove”, 5f);
break;
case 3:
fade.FadeOut(0.0f, 1.0f);
Invoke(“Scenemove2”, 5f);
break;
case 4:
fade.FadeOut(0.0f, 1.0f);
Invoke(“Scenemove2”, 5f);
break;

}

}

}

}

 

Unity Asset Storeブラックフライデーセール買ってみた!!

こんにちは、こんばんは!Misagonです!!

今回は、Unity Asset Storeブラックフライデーセールがあったので奮発して色々と買ってみました!!買ったものの一覧はこちら↓↓↓↓

Final IK

Obi Fluid

Mesh Baker

Dynamic Bone

思い切って買い過ぎてしまいました泣

まあいつか買うなら安い時に買うのがいいよね!!

各Assetについてかるーく説明していきます!!(本当に軽くね笑)


Dynamic Bone

髪や尻尾、胸などの揺れものを再現するアセットです。3Dモデルの髪の毛とか

尻尾とかを揺らしたいなーという時に使用します!

・使い方

①揺らしたい3Dモデルを用意(Boneがついているものだと超楽、その場合②は飛ばして良い)

②3DモデルにBoneをつける(Blenderを使用してね)

③DynamicBoneScriptをアタッチ

④インスペクタービューから揺らしたいBoneを設定する

⑤完成!!


Obi Fluid

液体を表現できるアセットです。水や細かい石など流体を実現できます!!

・使い方(模索中のため更新を待たれよ)


Final IK

Oculus等の動きをアバターに反映できるAssetです!

使い方

①Boneの入ったモデルを用意

②Oculus Integrationをインポート

③OVRCamerarigをSceneに追加

④モデルをOVRCamerarigの子要素にする

⑤モデルにFinalIKのVRIKスクリプトをアタッチ

⑥OVRCamerarigの配下の

・CenterEyeAnchor

・LeftHandAnchor

・RightHandAnchor

の下に以下のように各Targetの子要素を追加

⑦モデルにつけたVRIKに上記で追加したTargetを設定

・Head Target

・LeftArm

・RightArm

の項目のTargetを設定

⑧実行してみて手の角度などを調整して完成!!


 

Mesh Baker

MeshBakerはシーン上のオブジェクトのメッシュやテクスチャを結合することで描画を軽くするAssetです。

SetPass callsに注目してください。

Mesh Baker使用前のSetPass calls:11

Mesh Baker使用後のSetPass calls:7

もう少しうまく使えればもっと減らせると思います。

 

使い方

①3Dモデルを追加

複数のモデルをまとめる空要素Buildingも作成しその中に3Dモデルを入れます。

②GameObject→MeshBaker→TextureBaker and MultiMeshBaker

③ヒエラルキーにTexrureBaker0が追加されるので選択します。

④Open Tools For Adding Objectsを選択

⑤Editorが表示されるのでExclude mesh with out-of-bounds UVsのチェックを外します。

⑥Buildingを選択した状態で、「Add Selected Meshes To Target」押します。

するとマテリアルが選択されます。

⑦Create Empty Assets For Combined Materialを選択

⑧「Bake Materials Into Combined Material」を選択しTextureを結合します。

⑨ヒエラルキー上の 「TextureBaker」の子要素に「MultiMeshBaker」を選択し

Bakeを押します。

以下のように結合されたオブジェクトが生成されたら完成!!

 

SNOWのフェイスフィルターのスパイダーマンバージョンを作りたいpart2

皆さんこんにちは🌞こんばんは🌇

Misagonです‼️

フェイスフィルタースパイダーマンバージョンを考えてから随分と日が開いてしまいましたが、忘れていたわけではありません😑

試行錯誤の結果、スパイダーマンのフェイスフィルターを作ることに成功しました‼️

まずは見てましょう‼️ジャカジャン🎊

なかなかのクオリティですね‼️

合成してるわけじゃないですからね💦

それでは早速手順を記載していきます。

①ARKit2.0 for Unityをダウンロード

ダウンロード後、解凍してUnityにドラッグアンドドロップしてください。

iosのバージョン確認もしてね

②Spidermanの3Dモデルを入手 (Sketcfhabに登録必要※無料です)

③Spidermanの3Dモデルを編集して頭だけにする

ダウンロードしたものはモデルがカクカクしているのでBlenderで重複頂点を削除したり、表面を滑らかにしたりと編集します。(Blenderのサイトなどで調べてね)

④Unityに編集したSpidermanのモデルをインポート

⑤各種設定

ARKit2.0とSpidermanのモデルをインポートしたらあと少しです。

まず、UnityARKitPlugin>Examples>FaceTrackingの階層を開いてその中にある

FaceAnchorSceneを開きます。

するとヒエラルキービューに

CameraParent

ARFaceAnchorManager

ARCameraTracker

AxesPrefab

Directional light

が表示されます。(上画像参照)

AxesPrefabは削除か非表示にして構いません。

ARFaceAnchorManagerを選択すると、右側のインスペクタービューに

このように表示されます。このAnchor Prefabと書いているところに

インポートしたSpidermanのモデルを指定します。(以下参照)

れで顔を認識した時に表示されるオブジェクトの準備ができました。

次にFaceTrackingの使用を許可する必要があるので

UnityARKitPlugin>Resources>UnityARKitPlugin>ARKitSettingを選択し

AR Kit Uses Facetracking

App Requires AR Kit

の有効にチェックを入れます。

これでシーンを保存してビルドします。(プラットフォームをiosに切り替えてね)

⑥シャッターボタンの追加

スクリーンショットをカメラロールに保存するための設定をします。

Assetフォルダの下にPluginフォルダを作成しその中にiOSフォルダを作成します。

iOSフォルダの中にScreenShot.mmというファイルを作成します。(Xcodeで.mmファイルを作成できます。)

作成したファイルに次のプログラムを上書きします。

———————————————————————————

#import <Foundation/Foundation.h>
#import <AssetsLibrary/AssetsLibrary.h>
#import <AVFoundation/AVFoundation.h>

extern “C” void SaveToAlbum (const char* path)
{
UIImage *image = [UIImage imageWithContentsOfFile:[NSString stringWithUTF8String:path]];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];
[library writeImageToSavedPhotosAlbum:image.CGImage metadata:metadata completionBlock:^(NSURL *assetURL, NSError *error) {}];
}

————————————————————————–

ボタンを押したらスクリーンショットを撮るスクリプトはこちら※.cs

using System.Collections;
using UnityEngine;
using System.IO;
using System.Runtime.InteropServices;

public class ScreenShot : MonoBehaviour
{
[DllImport(“__Internal”)]
private static extern void SaveToAlbum(string path);

IEnumerator SaveToCameraroll(string path)
{
// ファイルが生成されるまで待つ
while(true)
{
if(File.Exists(path))
break;
yield return null;
}

SaveToAlbum(path);
}

void Update()
{
if(Input.GetMouseButtonDown(0))
{
#if UNITY_EDITOR
#else
string filename = “test.png“;
string path = Application.persistentDataPath + “/” + filename;

// 以前のスクリーンショットを削除する
File.Delete(path);

// スクリーンショットを撮影する
ScreenCapture.CaptureScreenshot(filename);

// カメラロールに保存する
StartCoroutine(SaveToCameraroll(path));
#endif
}
}

Xcodeでアプリをインストールします。

シャッターボタンを追加した場合

info.plistを選択し

右クリックでAdd Rowで以下を追加します。(追加しないとカメラで写真を取った時にアプリがクラッシュします。)

Privacy – Photo Library Additions Usage Description

⑧完成

という流れでした!これでみんなもスパイダーマン!!

SNOWのフェイスフィルターのスパイダーマンバージョンを作りたい!

どーも!Misagonです!!
今回から取り組んでいくのは、名付けて「Spider-man Filter Project」です!

SNOWのフェイスフィルターを自分で自作しようという試みなのですが、
アプリ制作超超初心者なので、いろいろなサイトや参考書を駆使して作成していきたいと思います。忘備録的な意味も込めてね笑

まず使用機材、ソフトはこちら
Macbook Air 10.5インチ(メモリ増設有り)
・iPhoneX1(主にこれにアプリを入れて動かす予定)
・Unity Version 2018.1.6f1 Personal
Photoshop Elements
Blender
などなど、都度使用していきたいと思います!

イメージとしては、自分の顔をスマホで写したら、スマホが顔を認識してスパイダーマンの顔を自分の顔に貼り付けてくれるという感じです。最終目標はこのスパイダーマンの画像のように目が大きくなったり小さくなったりを調整できるようにしたいと考えています。

今回一番重要な技術は「フェイストラッキング

カメラや赤外線センサーなどが顔を読み取り、表情などを認識する技術です。

制作の流れは、

①Unityでフェイストラッキングを実装したアプリを作成

PhotoshopBlenderスパイダーマンのマスクフィルターを作成

③上記を合体して実装

という流れです。

①が一番難しいところだと思うのですが、少しずつやっていきます!!

とりあえずUnityをインストールしたので、今回使用するアセット(いろいろな機能のパッケージプログラムと認識)をアセットストアからダウンロードしてインポートします!

ダウンロードするアセットはUnity-ARKit-Plugin です!Unityはインストールするとアセットストアを開けるのでそこで検索するのですが、検索しても出てこなかったのでGoogle先生に頼んだら載せてるサイトがあったのでここからダウンロード

https://bitbucket.org/Unity-Technologies/unity-arkit-plugin/downloads/

これをうまく使用したいところ、、、続く