のしメモ アプリ開発ブログ

Unityアプリとかロボットとか作ってるときに困ったこととかメモ

【2017年】作ったもの総まとめ

今年(2017年)に作ったものをTwitterを追いながらまとめてみる

1月

Makebox

VR Oculus Rift CV1 リリース


2016年秋ごろからコツコツ作ってたのをリリース

続きを読む

VR用のPCを組んでみた

Fallout4 VRをちゃんとやりたいのと、サイバーマンデーが来たのでPCを組むことに。

予算は「20万ぐらい」で「GTX 1080を搭載したVR ReadyなPC」を目指す。
また、開発でも使うので多少オーバースペックになってもOKという感じ。

買ったパーツをまとめました。

マザーボード

サイバーマンデーで安くなっていたのでこれをベースに。
好きな色で一部を光らせることができます。

ASRock Intel Z270チップセット搭載 ATXマザーボード Z270 Extreme4

ASRock Intel Z270チップセット搭載 ATXマザーボード Z270 Extreme4

CPU

7700は欲しいけど8000番台は予算オーバーかなと思いこれを購入

CPUクーラー

売れてるやつに

サイズ オリジナルCPUクーラー 虎徹 Mark II

サイズ オリジナルCPUクーラー 虎徹 Mark II

メモリ

DDR4で人気のものに。黒色も同じ値段だったので、せっかくなので赤を選びました

GPU

1080!

ASUS NVIDIA GeForce GTX1080搭載ビデオカード メモリ8GB TURBO-GTX1080-8G

ASUS NVIDIA GeForce GTX1080搭載ビデオカード メモリ8GB TURBO-GTX1080-8G

SSD

サイバーマンデーで20%オフになっていたので、M.2にしてみました

SSD用ヒートシンク

熱くなりやすいみたいなので念のため

アイネックス M.2 SSD用ヒートシンク HM-21

アイネックス M.2 SSD用ヒートシンク HM-21

HDD

とりあえず安くて売れてるやつに

電源

750Wで十分かなぁと。あとは80PLUSでゴールドのやつで絞って買いました。

PCケース

サイバーマンデーで安くなっていたのと、マザボが光るのでそれが見えるのでないとダメかなと。
光るファンの色は変えられます。裏に配線回せて結構すっきりな感じになります。

Corsair Crystal 460X RGB ミドルタワー型PCケース CS6657 CC-9011101-WW

Corsair Crystal 460X RGB ミドルタワー型PCケース CS6657 CC-9011101-WW

合計の購入金額

購入時の価格で計算してみました。

マザーボード 14,532
CPU 35,244
CPUクーラー 3,635
メモリ 22,335
GPU 61,636
SSD 25440
ヒートシンク 575
HDD 8,580
電源 10,794
PCケース 12,796
合計 195,567円

これにOS等のソフトウェアの料金が入りますが、BTOパソコンで同じスペックのものだと、24万ぐらいはするので若干お買い得という感じでしょうか。
組み立ての手間と初期不良だったりのコストやリスク等も考えるとBTOで買ったほうがよさそう。

パフォーマンステスト

f:id:noshipu:20171214195142p:plain

これでしばらくは快適なVR生活を過ごせそうです。

Unity ARKit PluginのFace Trackingを使ってみる

Oculus Rift Advent Calendar 2017の1日目の記事です!

ARKitでiPhoneXのFace Trackingを利用することができます。
Face Tracking with ARKit

Live2D Euclidと組み合わせると、こんなことが可能になります。

また、UnityのARKit Pluginから呼び出せるようになっていたので簡易的な解説をします。

設定

  1. iOSにプラットフォーム切り替え
  2. Unity ARKit Pluginをインポート
  3. 設定ファイルを下記に変更

Assets/UnityARKitPlugin/Resources/UnityARKitPlugin/ARKitSettings.asset
f:id:noshipu:20171130063756p:plain

シーンのセットアップ

Camera

ClearFlagをDepthOnlyに設定

UnityARVideo

YUV形式のカメラのテクスチャを取得、描画
ClearMaterialにYUVMaterialを設定する

UnityARCameraNearFar

Unityで設定しているClipping PlanesのNear/FarをNative側に伝える役割

ARCameraTracker

TrackedCameraにトラッキングさせたいカメラを指定

UnityARFaceMeshManager

MeshFilterに顔のMeshを反映させたいMeshを指定
また、このゲームオブジェクト自体が顔の位置をトラッキングする


これで下記のようなマスクマン的なことはできるようになります。

その他のクラスについて

UnityARFaceAnchorManager

任意のオブジェクトをトラッキングさせる。顔の位置、回転がわかればいいならこちらでOK

BlendshapePrinter

Blendshape(表情のパラメータ)の値をOnGUIで出力するデバッグ用スクリプト
これを使用するとフレームレートが落ちるので注意

UnityARKitLightManager

Meshにリアル空間の環境光を反映できるスクリプト
サンプルシーンのFaceDirectionalLightEstimateで確認可能

顔検出のScriptを簡易解説

顔を検出する

1. usingする
using UnityEngine.XR.iOS;
2. FaceTracking開始、検出イベント登録

configの設定を行い、サポートしていればSessionを開始

その後、顔の検出時のイベントを登録
・顔の検出をされるとFaceAddedが呼ばれる
・検出した顔の情報が更新されるとFaceUpdatedが呼ばれる
・顔の検出がはずれるとFaceRemovedが呼ばれる

void Start()
{
	UnityARSessionNativeInterface session = UnityARSessionNativeInterface.GetARSessionNativeInterface();

	Application.targetFrameRate = 60;
	ARKitFaceTrackingConfiguration config = new ARKitFaceTrackingConfiguration();
	config.alignment = UnityARAlignment.UnityARAlignmentGravity;
	config.enableLightEstimation = true;

	if (!config.IsSupported)
	{
		// 利用できない場合の処理はここで行う
		return;
	}

	session.RunWithConfig(config);

	// 顔の検出イベント登録
	UnityARSessionNativeInterface.ARFaceAnchorAddedEvent += FaceAdded;
	UnityARSessionNativeInterface.ARFaceAnchorUpdatedEvent += FaceUpdated;
	UnityARSessionNativeInterface.ARFaceAnchorRemovedEvent += FaceRemoved;
}

※ ちなみに検出可能な顔は1つで、体感ですが手前にある顔が優先されている感じです。

3. コールバック側で処理する
void FaceAdded (ARFaceAnchor anchorData)
{
	// 検出された時の処理
}

void FaceUpdated (ARFaceAnchor anchorData)
{
	// 検出中の処理
}

void FaceRemoved (ARFaceAnchor anchorData)
{
	// 検出から外れた時の処理
}

基本的には、ARFaceAnchorで渡ってくるパラメータを使って、FaceMeshを作成したり、顔の位置やBlendshapeの値を取得することが可能です。

ARFaceAnchorを使ったサンプルコード

顔の位置、回転を取得する
void FaceUpdated (ARFaceAnchor anchorData)
{
	gameObject.transform.localPosition = UnityARMatrixOps.GetPosition (anchorData.transform);
	gameObject.transform.localRotation = UnityARMatrixOps.GetRotation (anchorData.transform);
}
顔のMeshを作成、更新する
void FaceAdded (ARFaceAnchor anchorData)
{
	faceMesh = new Mesh ();
	faceMesh.vertices = anchorData.faceGeometry.vertices;
	faceMesh.uv = anchorData.faceGeometry.textureCoordinates;
	faceMesh.triangles = anchorData.faceGeometry.triangleIndices;

	faceMesh.RecalculateBounds();
	faceMesh.RecalculateNormals();
	meshFilter.mesh = faceMesh;
}

void FaceUpdated (ARFaceAnchor anchorData)
{
	faceMesh.vertices = anchorData.faceGeometry.vertices;
	faceMesh.uv = anchorData.faceGeometry.textureCoordinates;
	faceMesh.triangles = anchorData.faceGeometry.triangleIndices;
	faceMesh.RecalculateBounds();
	faceMesh.RecalculateNormals();
}
Blendshapeを取得する

取得可能な値の一覧は下記から画像付きで解説してくれています。
ARFaceAnchor.BlendShapeLocation - ARFaceAnchor | Apple Developer Documentation

ARBlendShapeLocationにパラメータKeyが格納されています。

パラメータを取得してモデルに反映させるコードはこんな感じになります。

void FaceUpdated (ARFaceAnchor anchorData)
{
	blendShapes = anchorData.blendShapes;

	// 口の開閉値を取得
	jawOpen = blendShapes[ARBlendShapeLocation.JawOpen];

	// 左目の開閉値を取得
	eyeBlink_L = blendShapes[ARBlendShapeLocation.EyeBlinkLeft];

	// Blendshapeの値をモデルに反映するなど
	m_MeshRenderer.SetBlendShapeWeight(0, jawOpen * 100f);
}

iPhoneX限定という制約はありますが、かなりコードがシンプルなので、お手軽にフェイシャルモーションを作ることができるのではないでしょうか。


明日の記事はnryotaさんになります!
qiita.com

円卓状にオブジェクトを配置する

Unityで任意の場所から円卓のように、任意の数のオブジェクトを配置したくなったときに使う処理をメモ

f:id:noshipu:20171128065040p:plain


スクリプト

/// <summary>
/// 円卓状にPrefabを生成する
/// </summary>
/// <param name="prefab">生成するPrefab</param>
/// <param name="count">生成数</param>
/// <param name="center">中心点のオブジェクト</param>
/// <param name="distance">距離</param>
/// <param name="isLookAtCenter">中心点の方向に向けるか</param>
private void SpawnObjectsOnRoundTable(GameObject prefab, int count, GameObject center, float distance, bool isLookAtCenter = true)
{
    for (int i = 0; i < count; i++)
    {
        var position = center.transform.position + (Quaternion.Euler(0f, 360f / count * i, 0f) * center.transform.forward * distance);
        var obj = Instantiate(prefab, position, Quaternion.identity);

        if (isLookAtCenter)
        {
            obj.transform.LookAt(center.transform);
        }
    }
}