第3回UnityでARkit2アプリを作る!距離測定アプリを作る

こんにちはイマイです。

前回までの記事でARkitで開発する環境を構築することができたと思うので
これから本格的にアプリをつくっていきます!

今回の目標

動画のような距離を測定するアプリケーションをつくります!

動画でみると距離の誤差は1cm未満と実用性も十分であることがわかりますね!

プロジェクトの準備

この記事ではUnityの基本的な使い方などは省略して
実装メインについて書いていきますので悪しからず。

Unity内での準備は以下のようになります。
まずはARkitが正常に動作する環境を作るのですが,今回はサンプルにあるものを使いまわします。
・Assets/UnityARKitPlugin/ARKitRemote/EditorTestSceneをコピーしてこれをもとに機能を追加していきます。
・シーンにボタンと測定した距離を表示するTextとButtonを追加します。
・Rayが当たっている位置を表示するためのFoucusSquareFindinはUnityARkitPlugin内にあるものを使いまわしました。
(今回の実装方法ではあらかじめFoucusSquareFindingがシーン内に存在しないと正常に動作しません。)]
・スクリプトはHitPoinManagerのみをカメラにアタッチしています。

1.カメラの中心からRayを飛ばす

使う端末によって画面のサイズに応じてカメラの中心からRayを飛ばすようにします。

public GameObject FocusPointObj;
private RaycastHit Hit;
public float findingSquareDist = 0.5f;

void Update () {
		Vector3 center = new Vector3(Screen.width/2, Screen.height/2, findingSquareDist);
		Ray ray = Camera.main.ScreenPointToRay (center);
		
		// カメラ中心からRayを飛ばす (HitにはRayの当たった情報が入ります。)
		if (Physics.Raycast (ray, out Hit)) {
			//レイが当たった座標にFocusPointObjを移動させる
			FocusPointObj.transform.position = Hit.point;
			//レイが当たった平面を基準にFocusPointObjを回転させる
			FocusPointObj.transform.rotation = Hit.transform.rotation;
			return;
		}
	}

Rayが当たった座標にFocusPoinObjを表示することでRayの当たっているところをわかりやすくします。
Hit.pointで簡単にRayが当たっている情報を取得できますね。

2.当たったところにマーカーを設置する


今回はボタンを設置してボタンを押すとマーカーを設置するようにします。

	public Text DisplayText;
	private int Click = 1;
	List<GameObject> list_toggle_ = new List<GameObject>();

     //ボタンを押したときの処理
        //ボタンを押すたびに処理が変わります
	public void ClickPlaceButton(){
		switch (Click){
			case 1:
			PlaceMarker();
			break;

			case 2:
			PlaceMarker();
			CalculateDistance();
			break;

			case 3:
			PlaceMarker();
			CalculateArea();
			break;

			case 4:
			Reset();
			break;
		}
	}

        //マーカーを設置する(マーカーの座標はリストで管理)
	private void PlaceMarker(){
		if(Hit.point != new Vector3(0,0,0)){
             //マーカーを生成する
			GameObject toggle_instance = Instantiate(MakerObj, Hit.point, Quaternion.identity) as GameObject;
             //マーカーをリストに追加
			list_toggle_.Add(toggle_instance);
			Click++;
		}
	}

3.マーカーの距離を測定・表示


リストを使って座標を管理します。
1.2の処理と合わせたコードの全文は以下のようになります。

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

public class HitPointManager : MonoBehaviour {
        //Rayが当たっている所に表示するオブジェクト
	public GameObject FocusPointObj;
        //マーカーオブジェクト
	public GameObject MakerObj;
	private RaycastHit Hit;
        //測定した距離を表示するテキスト
	public Text DisplayText;
        //ボタンを押した時に処理を分ける変数
	private int Click = 1;
	public float findingSquareDist = 0.5f;
        //マーカーの座標を管理するリスト
	List<GameObject> list_toggle_ = new List<GameObject>();

        //ボタンを押したときの処理
        //	
	public void ClickPlaceButton(){
		switch (Click){
			case 1:
			PlaceMarker();
			break;

			case 2:
			PlaceMarker();
			CalculateDistance();
			break;

			case 3:
			Reset();
			break;
		}
	}

	//マーカーを設置する
	private void PlaceMarker(){
		if(Hit.point != new Vector3(0,0,0)){
			GameObject toggle_instance = Instantiate(MakerObj, Hit.point, Quaternion.identity) as GameObject;
			list_toggle_.Add(toggle_instance);
			Click++;
		}
	}

	//2点間の距離を求めて表示する
	public void CalculateDistance(){
		Vector3 pos1 = list_toggle_[0].transform.position;
		Vector3 pos2 = list_toggle_[1].transform.position;
		float DistanceMillimeter = Vector3.Distance(pos1, pos2);
		DisplayText.text = "2点間の距離"+(DistanceMillimeter * 100f).ToString("f2")+"cm";
	}

	//マーカーを削除する
	public void Reset(){
		for (int i = 0; i < list_toggle_.Count; i++)
		{
			Destroy(list_toggle_[i]);
        }
        //リスト自体をキレイにする
        list_toggle_.Clear();
		Click = 1;
	}
}

この実装方法だと床と壁など、測定する場所が平面ではなくても距離を測定することができます。
複雑な計算をしなくてもUnity内で距離を測定する関数が用意されているのでそれを使うことができるのがおすすめポイントですね

次回の記事でこのプロジェクト一式をGithubに上げるのでとりあえず動かしたいという方はそちらからダウンロードしてみてください!

とってもざっくりな説明となりましたが今回はここまで~
それではよいハッキングライフを~