ソースに絡まるエスカルゴ

貧弱プログラマの外部記憶装置です。

【Unity】Unityでスカイボックスのやり方

 相も変わらずUnityをいじってます。
 Blenderでもやりましたが、今回はUnityでのスカイボックスのやり方です。


1:スカイボックスの素材を準備する
 まずはスカイボックスの素材を準備します。
 自作でも良いですが、Unityのアセットストアにも無料のものがあるので今回はそれを使用します。

 Unityのプロジェクトを立ち上げ、メニューの「Window」→「Asset Store」を選択します。
f:id:rikoubou:20180614131153p:plain

 検索欄に「worldskies」と入力して検索して一番上に出てくる「WorldSkies Free」を選択します。
f:id:rikoubou:20180614132747p:plain

 アセットの「Import」ボタンを押してインポートします。
f:id:rikoubou:20180614132916p:plain
f:id:rikoubou:20180614133049p:plain

「WorldSkies」というフォルダが追加されていればインポート完了です。
f:id:rikoubou:20180614133202p:plain

 これで素材の準備ができました。


2:スカイボックスを作る
 素材の準備ができたら、メニューの「Window」→「Lighting」→「Settings」を選択します。
f:id:rikoubou:20180614133659p:plain

 出て来たウインドウの「Scene」タブを選択します。
「Skybox Material」という項目がありますが、このMaterialを変更することで空の部分を変更できます。
f:id:rikoubou:20180614133852p:plain

  • デフォルトの状態

f:id:rikoubou:20180614134336p:plain

  • 別のマテリアルに変更した状態

f:id:rikoubou:20180614134424p:plain


 以上がUnityでスカイボックスをするやり方です。

 ただマテリアルを変更するだけ、という非常に簡単な方法でできることがわかりました。
 できれば素材を自作してみたいです。
 

・参考資料

【Unity】オブジェクトの移動方法(絶対座標・相対座標)

 OculusGoでアプリが作りたくてUnityを勉強中です。

 今回はオブジェクトの移動方法の備忘録です。用途としては「OculusGo用のカメラをコントローラーなどで移動させる」際に使うことになると思います。


1:絶対座標での移動方法
 Unityのオブジェクトには「Transform」という項目があります。この「Position」の座標が絶対座標(どこから見てもその座標)になります。
f:id:rikoubou:20180612173857p:plain

 この値を変更することでオブジェクトを移動させることができます。

 以下のようなスクリプトを記述することにより、Positionの値を変更することができます。

/* 例えばOculus Goのカメラである「OVRCameraRig」の場合 */

// 「OVRCameraRig」という名前のオブジェクトのTransformを取得
Transform cameraTrans = GameObject.Find("OVRCameraRig").transform;

// positionを取得して各座標を+1する
Vector3 pos = cameraTrans.position;
pos.x = pos.x + 1f;
pos.y = pos.y + 1f;
pos.z = pos.z + 1f;

// 新しい座標をセットする
cameraTrans.position = pos;

 これで絶対的な座標での移動ができます。

 しかしFPSなどでは「カメラが向いている方向に動きたい場合」があります。その場合、この方法では絶対座標通りにしか動けないので、次に紹介する相対座標での移動方法を採用することになります。


2:相対座標での移動方法
 オブジェクトにおけるZ軸のプラス方向が正面として、前、後への移動などを設定する便利なVector3の値が用意されています。
 その一覧が以下の通りで「それぞれ値が+1」されます。

方向
前方向 Vector3.forward
後方向 Vector3.back
左方向 Vector3.left
右方向 Vector3.right
上方向 Vector3.up
下方向 Vector3.down

 使い方の例は以下の通りです。

GameObject.Find("GameObject").transform.Translate(Vector3.forward);

 そのオブジェクトから見て前方向に0.5だけ移動させたい場合は、以下のようなスクリプトで実現できます。

/* 例えばOculus Goのカメラである「OVRCameraRig」の場合 */

// 「OVRCameraRig」という名前のオブジェクトのTransformを取得
Transform cameraTrans = GameObject.Find("OVRCameraRig").transform;

// そのオブジェクトから見て前方向に0.5だけ移動
cameraTrans.Translate( Vector3.forward * 0.5f);

 FPSのような視点を左右に回転させたりする場合は、絶対座標での移動ではなく相対的な移動であるこちらを使用した方が楽だと思います。


 以上がオブジェクトの2通りの移動方法です。Unityを使っている人には基本的なことだとは思いますが、操作性のあるゲームなどを作る場合は必要になるので記事にした次第です。

 とりあえずこれでUnityでのオブジェクトの動かし方はわかったので、OculusGoのアプリを色々作っていきたいです。


・参考資料

【Oculus Go】MacOSでUSB接続してもOculusGoが認識されない場合

 Oculus Goを使っていたら突然MacOSのPCがOculus Goを認識しなくなりました。
 PCを再起動してもダメ、Oculus Goを再起動してもダメという状態でした。

 ですが以下の方法で認識できるようになりました。

MacOSでOculus Goを認識させる方法
 結論から言うとMacのターミナルを開いて、以下のコマンドを入力すればOKです。

$ adb kill-server
$ adb start-server

要はTCPのコネクションがおかしくなっていたようなので、再起動させて復帰させるようです。

 この方法をツイートしていた方に感謝です。

【Unity / Oculus Go】Oculus Goコントローラーについて

rikoubou.hatenablog.com

 以前書いた記事の続きです。ある程度のボタンやタッチパッドの取得方法はわかりましたが、Oculus Goコントローラーについてもうちょっとわかったのでそれをまとめておきます。


1:Oculus Goコントローラーのボタン
 前の記事でも載せましたが、Oculus Goのコントローラーの各ボタンは以下のページから確認できます。
developer.oculus.com

 ボタン部分の画像だけ抜き出すと、Oculus Goのコントローラーは以下のようになっています。
f:id:rikoubou:20180611154338p:plain


2:タッチパッド上の二次元座標について
 これについても前の記事で載せましたが、タッチパッド上の二次元座標は以下の方法で取得できます。

Vector2 vector =  OVRInput.Get(OVRInput.Axis2D.PrimaryTouchpad, OVRInput.Controller.RTrackedRemote);
float x = vector.x;
float y = vector.y;

 そしてこのX座標、Y座標の範囲はそれぞれ-1〜+1の範囲のfloat型になっています。また物理ボタンと座標の対応は以下のようになっています。
f:id:rikoubou:20180611154627p:plain

 またタッチパッド指が触れていない状態ではX座標、Y座標共に0の値になります。


3:OVRInput.Get関数について
 どのボタンでも「OVRInput.Get({ボタン変数名})」という書き方でボタンが押されている間ずっとTrueを返すと思っていたのですが、実際は少し違いました。

  • 押されている間Trueが返るもの
// コントローラーのトリガー
bool trigger = OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger);

// タッチバッドのボタン
bool touchButton = OVRInput.Get(OVRInput.Button.PrimaryTouchpad);
  • 押された瞬間のみTrueが返るもの
bool backButton = OVRInput.Get(OVRInput.Button.Back);

 要はBackボタンのみがOVRInput.Get関数を使っても、ずっと押され続けているということを検知できない仕様のようです。これは実装して確認してみた結果なのですが、Backボタンだけ特別にする必要があったのか?というのは謎ですね……。


 以上がざっとOculus Goコントローラーの値を取ってみた結果です。コントローラーの角度やHMDの角度とかもおそらく取れると思うのでそのあたりも調べていきたいです。
 追加でわかればこの記事を更新していこうと思います。


・参考資料

【Unity】Prefabsにあるオブジェクトをスクリプトから生成する方法

 Oculus Goのアプリを作りたくてUnityをいじっています。
 数年前に一度やってはいたのですが、やり方を思い出すので時間がかかったので備忘録として記録しておきます。

1:Resourcesフォルダ内にPrefabsフォルダを作成する
 前提条件としてAssetsフォルダ配下に「Resources」フォルダを作成し「Prefabs」フォルダを作成します。
f:id:rikoubou:20180607225325p:plain

 この「Resources」フォルダは「Resources.Load({パス})」という記述で配下にあるファイルを読むことができます。
 それを利用してその中に「Prefabs」フォルダを作成することにより、Prefabsに登録されたオブジェクトを生成します。


2:Prefabsにあるオブジェクトを生成するプログラム
 結論からいうと以下の関数でできます。

/// <summary>
/// プレハブを作成する(pos, Quaternion有)
/// </summary>
/// <returns>GameObject</returns>
/// <param name="path">プレハブのパス</param>
/// <param name="pos">Position.</param>
/// <param name="q">Quaternion.</param>
public GameObject createPrefab(string path, Vector3 pos, Quaternion q) {
	GameObject prefabObj = (GameObject)Resources.Load (path);
	GameObject prefab = (GameObject)Instantiate (prefabObj, pos, q);
	return prefab;
}

 上記の関数は以下のように使います。

// 対象のプレハブのパス
string prefabsPath= "Prefabs/PrefabsObj";

// 表示座標
Vector3 pos = new Vector3(1f, 1f, 1f); 

// スケール
Vector3 scale = new Vector3 (0.5f, 0.5f, 0.5f);

// プレハブオブジェクトを作成
GameObject obj = createPrefab(prefabsPath, pos, this.gameObject.transform.rotation);
obj.transform.localScale = scale;

 このような記述をEmptyのオブジェクトなどにアタッチさせておくことで生成することができます。


3:使い方例
 例として以下のように角度をつけて大きさをデフォルトの2倍にした「CubeA」を「Resource」配下の「Prefabs」に登録しました。
f:id:rikoubou:20180607225919p:plain
 
 「Scripts」フォルダを作成してその中に「CreatePrefabs」スクリプトを作成します。スクリプトの中身は以下のようにします。

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

public class CreatePrefabs : MonoBehaviour {

	// Use this for initialization
	void Start () {
		string prefabsPath = "Prefabs/CubeA";
		Vector3 pos = new Vector3 (6f, 0f, 0f);
		Vector3 scale = new Vector3 (0.5f, 0.5f, 0.5f);
		GameObject obj = createPrefab(prefabsPath, pos, this.gameObject.transform.rotation);
		obj.transform.localScale = scale;
	}

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

	}

	/// <summary>
	/// プレハブを作成する(pos, Quaternion有)
	/// </summary>
	/// <returns>GameObject</returns>
	/// <param name="path">プレハブのパス</param>
	/// <param name="pos">Position.</param>
	/// <param name="q">Quaternion.</param>
	public GameObject createPrefab(string path, Vector3 pos, Quaternion q) {
		GameObject prefabObj = (GameObject)Resources.Load (path);
		GameObject prefab = (GameObject)Instantiate (prefabObj, pos, q);
		return prefab;
	}
}

 次に空のGameObjectを作成して名前を「CreatePrefabs」に変更したものに「CreatePrefabs」スクリプトをドラッグ&ドロップでアタッチします。この時の空のGameObjectの座標は「全て0」にしておくと色々楽です。
f:id:rikoubou:20180607230731p:plain
f:id:rikoubou:20180607230911p:plain

 この状態で実行すると、スクリプトで指定した位置と大きさでCubeAが作成されます。
f:id:rikoubou:20180607231336p:plain


・参考資料

【Unity / Oculus Go】Oculus Goコントローラー表示方法とボタン取得方法

rikoubou.hatenablog.com

 前回の記事でOculus Go向けのビルドはできるようになりました。
 今回は前回のプロジェクト(と言ってもCubeやSphereを置いただけですが)にOculus Goコントローラーを追加していきます。


1:必要なアセットのインポート
 プロジェクトを開いたらメニューの「Window」→「Asset Store」を選択します。
f:id:rikoubou:20180603202718p:plain

 するとAsset Storeの画面が出てくるので「Oculus Integration」と入力して検索ボタンを押します。
f:id:rikoubou:20180603203507p:plain

 Oculus Integrationのアセットをダウンロードしてない場合はダウンロードします。

 ダウンロードが終わったら「Import」ボタンを押してアセットをインポートします。
f:id:rikoubou:20180603203553p:plain

 インポートの途中で以下のダイアログが出てきた場合は「Yes」ボタンを押します。
f:id:rikoubou:20180603203748p:plain

 そのあとUnityを再起動するかを尋ねるダイアログが出てくるので、それもYesボタンをクリックしてUnityを再起動させます。

 Unityの再起動が終わって開いていたプロジェクトが再び立ち上がると、Assets配下に「Oculus」というフォルダが追加されています。この中にOculus向けアプリ開発に必要なものが入っています。
f:id:rikoubou:20180603204253p:plain

 これでアセットのインポートは完了です。


2:OVRCameraRigの追加しMain Cameraを削除する
 初めにOVRCameraRigというVR用のカメラを追加します。

「Oculus」→「VR」→「Prefabs」の中にある「OVRCameraRig」をドラッグ&ドロップでSceneに追加します。
f:id:rikoubou:20180604004355p:plain

 これで元のカメラがいらなくなるので「Main Camera」を選択した状態で右クリックし、「Delete」を選択して削除します。
f:id:rikoubou:20180604005054p:plain


3:Oculus Goコントローラーの追加
 次はOculus Go用のコントローラーを追加します。

「Oculus」→「VR」→「Prefabs」の中にある「TrackedRemote」を「OVRCameraRig」の中にある「LeftHandAnchor」と「RightHandAnchor」にドラッグ&ドロップします。
f:id:rikoubou:20180604005504p:plain

「LeftHandAnchor」と「RightHandAnchor」の両方に配置しておくことで、右手・左手の設定から自動的にどちらを表示するかを決めてくれます。

 追加した「TrackedRemote」の子として「OculusGoControllerModel」というのがあります。これがOculus Goのコントローラーになります。
f:id:rikoubou:20180604010707p:plain

 単にコントローラーを追加するだけならこれで終わりです。


4:Oculus Goコントローラーからレーザーポインターを出す
 追加したコントローラーがどこを指しているかがわかるように、コントローラーの先からレーザーポインターを出すようにします。

 最初に「Assets」フォルダを選択した状態で右クリックをし「Create」→「Folder」を選択し、「Scripts」という名前のフォルダを作成します。ここにスクリプトを追加していきます。
f:id:rikoubou:20180603235333p:plain

 次に「Scripts」フォルダを選択した状態で右クリックをし「Create」→「C# Script」を選択し、「LaserPointer」という名前で.csファイルを作成します。
f:id:rikoubou:20180603235659p:plain

 作成した「LaserPointer」ファイルをダブルクリックしてエディタを開き、以下のようにソースコードを記述します。

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

/**
 * レーザーポインターを出すクラス
 */
public class LaserPointer : MonoBehaviour {

	[SerializeField]
	private Transform _RightHandAnchor; // 右手

	[SerializeField]
	private Transform _LeftHandAnchor;  // 左手

	[SerializeField]
	private Transform _CenterEyeAnchor; // 目の中心

	[SerializeField]
	private float _MaxDistance = 100.0f; // 距離

	[SerializeField]
	private LineRenderer _LaserPointerRenderer; // LineRenderer

	// コントローラー
	private Transform Pointer {
		get {
			// 現在アクティブなコントローラーを取得
			var controller = OVRInput.GetActiveController();
			if (controller == OVRInput.Controller.RTrackedRemote) {
				return _RightHandAnchor;
			} else if (controller == OVRInput.Controller.LTrackedRemote) {
				return _LeftHandAnchor;
			}
			// どちらも取れなければ目の間からビームが出る
			return _CenterEyeAnchor;
		}
	}

	void Update () {
		var pointer = Pointer; // コントローラーを取得
		// コントローラーがない or LineRendererがなければ何もしない
		if (pointer == null || _LaserPointerRenderer == null) {
			return;
		}
		// コントローラー位置からRayを飛ばす
		Ray pointerRay = new Ray(pointer.position, pointer.forward);

		// レーザーの起点
		_LaserPointerRenderer.SetPosition(0, pointerRay.origin);

		RaycastHit hitInfo;
		if (Physics.Raycast(pointerRay, out hitInfo, _MaxDistance)) {
			// Rayがヒットしたらそこまで
			_LaserPointerRenderer.SetPosition(1, hitInfo.point);
		} else {
			// Rayがヒットしなかったら向いている方向にMaxDistance伸ばす
			_LaserPointerRenderer.SetPosition(1, pointerRay.origin + pointerRay.direction * _MaxDistance);
		}
	}
}

 ソースコードの記述が終わったら、Sceneの何も選択していない状態で右クリックをし「Create Empty」を選択します。
f:id:rikoubou:20180604174152p:plain

 すると空のGame Objectが作成されるので、名前を「LaserPointer」に変更します。
f:id:rikoubou:20180604174438p:plain

 名前を変更した「LaserPointer」のGame ObjectにScriptsフォルダの中にある「LaserPointer」をドラッグ&ドロップします。
f:id:rikoubou:20180604174740p:plain

 するとソースコードが追加され、以下のように「SerializeField」でクラス変数としたものを設定する項目が出てきます。
f:id:rikoubou:20180604175042p:plain

 以下のように「○○Anchor」となっているところに、それぞれ該当する「Anchor」をドラッグ&ドロップします。
f:id:rikoubou:20180604175611p:plain

 次にレーザーを描写するLine Renderderを作成します。

 LaserPointerのGame Objectを選択した状態で、「Add Component」ボタンを押してlineを入力して出てきた「Line Renderer」を選択します。
f:id:rikoubou:20180604175901p:plain

 Line Rendererが追加されます。
f:id:rikoubou:20180604180108p:plain

 以下の赤枠で囲った部分を設定します。
f:id:rikoubou:20180604181011p:plain

 Materialの選択は右側にある「○」のようなマークをクリックし、出てきたウインドウで「sp」と入力し「Sprites-Default」を選択します。
f:id:rikoubou:20180604181342p:plain

 レーザーの距離による太さは、以下のようにグラフ上で「ダブルクリック」することで頂点を追加できるので、追加した頂点をドラッグで移動させます。その後その頂点から伸びている薄い線の先にある点をドラッグして曲線を調節します。
f:id:rikoubou:20180604181527p:plain
f:id:rikoubou:20180604182011g:plain

 レーザーの色や不透明度は、以下のように上下の両端にあるスライダーのチェック部分をクリックで選択し、下側は色、上側はアルファ値を設定します。色やアルファ値は適当でよいです。
f:id:rikoubou:20180604182439p:plain
f:id:rikoubou:20180604182932p:plain

 必要な設定が済んだら、Line Rendererを「Laser Pointer Renderer」にドラッグ&ドロップします。
f:id:rikoubou:20180604183205p:plain

 これでコントローラーの先からレーザーポインターが出ます。

 ちなみにこの状態でビルドしてOculus Goで実行すると以下のようになります。


5:Oculus Goコントローラーのボタン取得方法
 Oculus Goのコントローラーの各ボタンは以下のページから確認できます。
developer.oculus.com

 ボタンの解説画像のみは以下の通り。
f:id:rikoubou:20180604191436p:plain

 画像の通り各ボタンの名前は以下のようになっています。(間違っている可能性あり)

取得ボタン 変数名
トリガー OVRInput.Button.PrimaryIndexTrigger
タッチパッドのクリック OVRInput.Button.PrimaryTouchpad
タッチパッドの上方向スクロール OVRInput.Button.Up
タッチパッドの下方向スクロール OVRInput.Button.down
タッチパッドの左方向スクロール OVRInput.Button.left
タッチパッドの右方向スクロール OVRInput.Button.right
バックボタン OVRInput.Button.Back

 右手・左手のどちらの設定になっているかは以下で取得できます。

var controller = OVRInput.GetActiveController();

if (controller == OVRInput.Controller.RTrackedRemote) {
	// 右手の場合
} else if (controller == OVRInput.Controller.LTrackedRemote) {
	// 左手の場合
}


 各種ボタンの基本的な取得方法は以下のようになります。(間違っている可能性あり)

bool result = OVRInput.Get({ボタン変数名});     // ボタンが押されている間ずっとTrueを返す
bool result = OVRInput.GetDown({ボタン変数名}); // ボタンが押された時の1回のみTrueを返す
bool result = OVRInput.GetUp({ボタン変数名});   // ボタンが離された時の1回のみTrueを返す

 タッチパッド上の2次元座標は以下のように取得します。

Vector2 vector =  OVRInput.Get(OVRInput.Axis2D.PrimaryTouchpad, OVRInput.Controller.RTrackedRemote);
float x = vector.x;
float y = vector.y;


6:Oculus Goコントローラーのボタンでレーザーポインター先のオブジェクトを操作する
 4まででコントローラーからレーザーポインターが出るようになりました。
 5の内容を踏まえて、レーザーポインターの先にあるオブジェクトをボタンで操作できるようにしてみます。

 今回は単純にレーザーポインターが当たっている先のオブジェクトの大きさをボタンで変更できるようにしてみます。

 方法は簡単でScriptsフォルダの中にある「LaserPointer」を開いて以下のように書き換えます。

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

/**
 * レーザーポインターを出すクラス
 */
public class LaserPointer : MonoBehaviour {

	[SerializeField]
	private Transform _RightHandAnchor; // 右手

	[SerializeField]
	private Transform _LeftHandAnchor;  // 左手

	[SerializeField]
	private Transform _CenterEyeAnchor; // 目の中心

	[SerializeField]
	private float _MaxDistance = 100.0f; // 距離

	[SerializeField]
	private LineRenderer _LaserPointerRenderer; // LineRenderer

	// コントローラー
	private Transform Pointer {
		get {
			// 現在アクティブなコントローラーを取得
			var controller = OVRInput.GetActiveController();
			if (controller == OVRInput.Controller.RTrackedRemote) {
				return _RightHandAnchor;
			} else if (controller == OVRInput.Controller.LTrackedRemote) {
				return _LeftHandAnchor;
			}
			// どちらも取れなければ目の間からビームが出る
			return _CenterEyeAnchor;
		}
	}

	void Update () {
		var pointer = Pointer; // コントローラーを取得
		// コントローラーがない or LineRendererがなければ何もしない
		if (pointer == null || _LaserPointerRenderer == null) {
			return;
		}
		// コントローラー位置からRayを飛ばす
		Ray pointerRay = new Ray(pointer.position, pointer.forward);

		// レーザーの起点
		_LaserPointerRenderer.SetPosition(0, pointerRay.origin);

		RaycastHit hitInfo;
		if (Physics.Raycast(pointerRay, out hitInfo, _MaxDistance)) {
			// Rayがヒットしたらそこまで
			_LaserPointerRenderer.SetPosition(1, hitInfo.point);

			/* ---以下追加した部分--- */
			// ヒットしたオブジェクトを取得
			GameObject obj = hitInfo.collider.gameObject;
			// ヒットしたオブジェクトのScaleを取得
			Vector3 scale = obj.transform.localScale;
			
			if (OVRInput.GetDown(OVRInput.Button.PrimaryIndexTrigger)) {
				// トリガーボタンを押した時
				Vector3 maxScale = new Vector3(5f,5f,5f);
				// スケールの各値が5より小さい場合は0.1大きくする
				if (scale.sqrMagnitude < maxScale.sqrMagnitude) {
					obj.transform.localScale = new Vector3 (scale.x + 0.1f, scale.y + 0.1f, scale.z + 0.1f);
				}
			} else if (OVRInput.GetDown(OVRInput.Button.PrimaryTouchpad)) {
				// タッチパッドボタンを押した時
				Vector3 minScale = new Vector3(0.5f,0.5f,0.5f);
				// スケールの各値が0.5より大きい場合は0.1小さくする
				if (scale.sqrMagnitude > minScale.sqrMagnitude) {
					obj.transform.localScale = new Vector3 (scale.x - 0.1f, scale.y - 0.1f, scale.z - 0.1f);
				}
			}
			/* ---追加した部分ここまで--- */
		} else {
			// Rayがヒットしなかったら向いている方向にMaxDistance伸ばす
			_LaserPointerRenderer.SetPosition(1, pointerRay.origin + pointerRay.direction * _MaxDistance);
		}
	}
}

 このように書き換えると、以下のようにオブジェクトにレーザーポインターに当たった状態でトリガーボタン or タッチパッドボタンを押すとオブジェクトを大きくしたり、小さくしたりできます。レーザーポインターの先にオブジェクトが存在しない場合は、ボタンを押しても何も起こりません。


 以上、長々となってしまいましたが、Oculus Goコントローラーの表示方法とボタン取得方法でした。

 これでOculus Goコントローラーのボタンなどを取得できるようになったので、色々アプリでボタン操作を実装することができます。
 楽しみが広がりますね。


・参考資料

【Oculus Go / unity】unityでOculus Go向けアプリのビルド方法

 購入したOculus Go向けアプリをunityで開発できるらしいということを知り、やってみたのでその備忘録です。
 アプリ自体の開発ではなく「unityでのOculus Go向けのビルド方法」の説明なので、今回の内容にゲーム要素はないので注意してください。


1:開発環境
 環境は以下の通りです。

  • OS:MacOS Sierra 10.12.6
  • unity:2018.1.0f2 Personal

 unityがすでにインストールされている前提で進めていきます。(Windowsの場合は以下の記事の手順を参照するようにしてください)
syuuki-k.hatenablog.com


2:Oculus Goを開発者モードにする
 最初にアプリを公開する際に必要になる団体名を作成します。
 以下のページで団体名を作成します。

 団体名を作成したらスマホの「OculusGoアプリ」を起動させてOculus Goと接続させます。

 右下にある「設定」をタップして設定画面を表示させ、接続したOculus Goを選択したのち、「その他の設定」をタップします。
f:id:rikoubou:20180602230649p:plain

 その他の設定画面で「開発者モード」をタップします。
f:id:rikoubou:20180602230731p:plain

 開発者モードを一度タップしてONにします。
f:id:rikoubou:20180602230815p:plain

 以上の手順でOculus GoをAndroid端末と同じようにビルドしたアプリを書き込めるようになります。


3:Java Development Kitをインストールする
 以下のサイトからOSにあったJava Development Kitをダウンロードしてインストールします。

 サンプルやデモなどは必要ないので、一番上にあるものの中から選べばよいです。
 自分の場合は「Java SE Development Kit 8u172」を選択しました。


4:Android StudioSDKをインストールする
 以下のページからAndroid Studioをダウンロードしてインストールします。

 インストールが完了したらAndroid Studioを起動させます。

 Android Studioを起動させたら、右下にある「Configure」をクリックします。
f:id:rikoubou:20180602232423p:plain

 出てきた中の「SDK Manager」を選択します。
f:id:rikoubou:20180602232503p:plain

 すると以下のようにインストールするAndroid SDKの一覧が表示されるので、APIレベルが21以降のものにチェックを入れて「Apply」ボタンを押してSDKをインストールします。
f:id:rikoubou:20180602232902p:plain

(※Oculus GoのAndroidバージョン以上のSDKをインストールすれば良いのですが、バージョンがよくわからないのでとりあえずAPIレベルが21以上のものをインストールしています)

・追記:Oculus GoはAndroid 7.1.1らしいので、そのSDKのみのインストールで良いです。
f:id:rikoubou:20180603005714p:plain

 インストールが完了したらAndroid Studioはもう必要ないので終了させます。


5:unityのAndroidビルド環境設定を行う
 unityを起動させ、適当なプロジェクトを開きます。
 適当なプロジェクトを開いたらメニューの「Unity」→「Preferences」を選択します。
f:id:rikoubou:20180602233829p:plain

「External Tools」を選択し、Androidの項目の「SDK」と「JDK」のところのパスを設定します。
f:id:rikoubou:20180602234212p:plain

 MacOSの自分の場合は以下のように設定しました。MacOSの場合は大体これで大丈夫だと思います。

  • SDK:/Users/{ユーザ名}/Library/Android/sdk
  • JDK:/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home

 これでunityでのAndroidビルドができるようになります。エラーが出た場合は以下の記事を参考にしてください。
syuuki-k.hatenablog.com


6:unityでプロジェクトを作成しビルドする
 なんでもよいですが、今回は以下のようにCubeとSphereを置いただけのプロジェクトを作成しました。これをビルドしていきます。
f:id:rikoubou:20180602235039p:plain

 プロジェクトができたらメニューの「File」→「Build Settings」を選択します。
f:id:rikoubou:20180602235219p:plain

「Build Settings」のウインドウが出てきたら「Android」を選択し、「Switch Platform」ボタンを押します。
f:id:rikoubou:20180602235400p:plain

 プラットフォームをAndroidに切り替えたらBuild Systemを「Gradle」に変更し、「Development Build」にチェックを入れます。そして「Player Settings」ボタンを押します。
f:id:rikoubou:20180603010457p:plain

・追記:Build Systemは標準の「Gradle」にしてください。「Internal」は今後サポートが期待できないので「Gradle」でビルドに失敗した時のみの応急処置として「Internal」を使うようにしてください。


 すると「Inspector」が表示されるので「Company Name」と「Product Name」を変更します。
f:id:rikoubou:20180602235948p:plain

 なんでも良いですが今回は以下のように入力しました。(配布するアプリは1で登録した団体名をCompany Nameにした方が良いかも)

  • Company Name:hoge
  • Product Name:TestApp

「Inspector」の中にある「Other Settings」を開いて「Package Name」を入力します。
「Package Name」は「com.{Company Name}.{Product Name}」の形式で入力します。
 また「Minimum API Level」を「Android 5.0 "Lollipop"(API Level 21)」に変更します。
f:id:rikoubou:20180603000303p:plain

・追記:Oculus GoはAndroid 7.1.1らしいので「Minimum API Level」もAndroid 7.1.1にすればよいです。

 次に「Inspector」の中にある「XR Settings」を開いて「Virtual Reality Supported」にチェックを入れます。
 チェックを入れたら「+」ボタンをクリックし、「Oculus」を選択して追加します。
f:id:rikoubou:20180603000831p:plain

 これでビルド設定は終了です。


7:ビルドしてOculus Goにアプリを送る
 6まで準備できたらOculus Goの電源が入った状態で、付属のUSBケーブルでPCとOculus Goを接続します。
 その状態で「Build And Run」ボタンを押すとビルドが始まり、Oculus Goにビルドされたアプリが送られます。
f:id:rikoubou:20180603001451p:plain

 Oculus Goにビルドしたアプリが転送されると、自動的にアプリが立ち上がります。
 立ち上がらない場合はOculus Goの「ライブラリ」を開き「提供元不明」となっている中から該当のアプリ名(Product Nameで設定した名前)を選択すると起動できます。何度か選択しないと起動できない場合もあります。
f:id:rikoubou:20180611151042p:plain

 ちなみに上記のプロジェクトをOculus Goで実行するとこのようになります。


 以上がunityでOculus Go向けのビルド方法です。結構手順が多くて大変ですが、一度設定してしまえば6以降の手順だけで済みます。

 割と簡単にVRアプリが作成できることがわかったので、何か面白いものを作ってみたいです。


・参考資料