HEXA BLOG

プログラム

HEXA BLOGプログラム2016.8.5

ちょっとだけARに触れてみる

こんにちはプログラマーのチャラメガネです

 

最近ますます暑くなってきましたね

気温ももちろんですが、

今、チャラメガネの中で特に熱いコンテンツは

ポケモンGO 」です

 

このゲーム、一般的にはAR表現で有名ですね。

プログラマーとしては、ARへの好奇心が疼きます

 

というわけで、ARのデモを作成してみました。

 

テーマとしては、

「部屋に女の子を召喚し、観察したり撮影したりできるスマホアプリ」

です

 

今回はお馴染みのゲームエンジン「Unity」を使い

ユニティちゃんを召喚してみます

 


 

1.まずはイメージを考える

 

女の子を部屋に召喚して写真を撮るシチュエーション。

理想としてはこんな感じ。

 

00

 

 

しかし、ARのない現実は…

 

 

 

01

 

当然ですが、こんな感じですね。

この理想を叶えるためAR表現でユニティちゃんを召喚するわけです。

 


 

2.とりあえず原理から

 

まず、必要な物は

 

・ジャイロセンサー

・カメラ

 

最近のスマホには概ね付いています

 

まずゲーム空間上にカメラとユニティちゃんを配置します。

この時、カメラにレンダーテクスチャをターゲット指定しておきます。

 

02

 

次に、ジャイロセンサーを使い

端末の傾きをゲーム空間上のカメラに伝えます。

 

03

04

 

これで、ゲーム空間に関する処理は終わりです。

 

次は背景テクスチャですが、

端末搭載カメラからテクスチャを取得するだけです。

 

05

 

最後に、

ゲーム空間のカメラのレンダーテクスチャと

端末搭載カメラから取得したテクスチャを重ねます。

 

06

 

 

原理は以上です!

これなら簡単に実装できそうですね。

背景からの平面抽出などはしていないので

端末の移動には対応していませんが、見た目は問題ないと思われます。 


 

3.実装すると

以上を踏まえて、今回実装したコンポーネントです。

 

まずはゲーム空間上のカメラと

端末の傾きを同期するコンポーネントです。

 

CameraDeviceSync.cs

using UnityEngine;

//===========================================================================
//!	@class		CameraDeviceSync
//!	@brief		カメラと端末の同期
//!				Cameraとの組み合わせで動作する。
//===========================================================================
[RequireComponent(typeof(Camera))]
public class CameraDeviceSync : MonoBehaviour
{
	//-----------------------------------------------------------
	//!	@name 内部メソッド
	//-----------------------------------------------------------
	//@{

	//-----------------------------------------------------------
	//!	@brief	初回処理
	//!	@return	なし
	//-----------------------------------------------------------
	private void Start()
	{
		// ジャイロセンサーの有効化
		Input.gyro.enabled = true;
	}

	//-----------------------------------------------------------
	//!	@brief	更新
	//!	@return	なし
	//-----------------------------------------------------------
	private void Update()
	{
		// 端末の傾きを取得
		Quaternion attitude = Input.gyro.attitude;
		// attitudeは端末の画面を上に向けている状態が基準となっている。
		// 今回、端末を縦持ちしている想定なので、90度回しておく。
		transform.localRotation = Quaternion.Euler(90, 0, 0) * new Quaternion(-attitude.x, -attitude.y, attitude.z, attitude.w);
	}

	//-----------------------------------------------------------
	//!	@brief	GUI更新
	//!	@return	なし
	//-----------------------------------------------------------
	private void OnGUI()
	{
#if DEBUG
		// ジャイロセンサーとCameraの回転情報を表示
		GUI.Label(new Rect(0, 0, 480, 20), "gyro:" + Input.gyro.attitude);
		GUI.Label(new Rect(0, 20, 480, 20), "rotation:" + transform.localRotation);
#endif
	}

	//@}
} 

 

 

次に、端末搭載カメラのテクスチャを表示するコンポーネントです。

 

WebCameraImage.cs

using UnityEngine;
using UnityEngine.UI;

//===========================================================================
//!	@class		WebCameraImage
//!	@brief		Webカメラの取得
//!				RawImageとの組み合わせで動作する。
//===========================================================================
[RequireComponent(typeof(RawImage))]
public class WebCameraImage : MonoBehaviour
{
	//-----------------------------------------------------------
	//!	@name 内部メソッド
	//-----------------------------------------------------------
	//@{

	//-----------------------------------------------------------
	//!	@brief	初期化
	//!	@return	なし
	//-----------------------------------------------------------
	private void Start()
	{
		// テクスチャを貼り付けるターゲットとしてRawImageを取得。
		RawImage targetImage = GetComponent();
		if( targetImage == null ) {
			Debug.LogWarning("invalid target.");
			return;
		}

		// カメラ情報は横向きで取得される。
		// _targetImageはエディタ上で事前に回転させておき、widthとheightは逆に入れる。
		targetImage.rectTransform.sizeDelta = new Vector2(Screen.height, Screen.width);

		// カメラ情報はWebCamTexture型で取得可能。
		WebCamDevice[] devices = WebCamTexture.devices;
		if( devices == null ||
			devices.Length <= 0 ) {
			Debug.LogWarning("there is not device.");
			return;
		}

		// 0番目のデバイスを使用
		// 端末によっては、0番がセルフィー用カメラの可能性もあり。
		WebCamDevice device = devices[0];
		WebCamTexture webcamTexture = new WebCamTexture(device.name, Screen.width, Screen.height, _webCamFPS);
		if( webcamTexture == null ) {
			Debug.LogWarning("invalid WebCamTexture.");
			return;
		}

		// ターゲットにテクスチャを指定し、カメラを起動
		targetImage.texture = webcamTexture;
		webcamTexture.Play();
	}

	//@}

	//-----------------------------------------------------------
	//!	@name メンバ変数
	//-----------------------------------------------------------
	//@{
	
	[SerializeField] private int		_webCamFPS		= 30;       //!< カメラのFPS

	//@}

}

 

 他にもレンダーテクスチャをUIに送る処理など書いていますが

特筆するべきところは特にないので端折ります。

 


 

 

4.実行結果

 

こんな感じになりました!

 

  IMG_0944 IMG_0945 

 

 

ちょっと足元が浮いてるとか

なんかデカイとか

調整すべき項目はありますがそれっぽい見た目になっています!

 


 

 

さて、今後の調整項目ですが、

 

・影がないので接地感がない

・現実の光源とゲーム空間の光源を一致させる仕組みがほしい

・画角が狭すぎてモデルがでかく見える

・ユーザーの腕の動きが考慮されていないので回転に違和感がある

・前後移動がないので近づけない

 

こういったものが挙げられます。

今後も進捗あれば報告していきます

それではまた次回

IMG_0946

RECRUIT

大阪・東京共にスタッフを募集しています。
特にキャリア採用のプログラマー・アーティストに興味がある方は下のボタンをクリックしてください

RECRUIT SITE 

NEWS