CrossRoad

Unity、VR、MR、ARを中心とした技術ブログ

Oculus RiftでPSEye越しに現実風景を見て、VRに切り替える方法

続きです。OculusGameJamで作ったゲームの主な作り方を説明します。

ゲームの流れはこんな感じです。
(1)oculusRiftでPSeye越しに現実風景を見る(AR)
(2)マーカを認識して現実風景をふわっと削除(AR->VR)
(3)フォロワーアイコンを頭上に掲げたクマさん登場(VR)
(4)逃げてくクマさんを追いかけてフォロワーを再び!

今回は(2)を説明します。

1. NRARToolKitのunityPackageをインポートする

マーカの認識にはNRARToolKitを使わせていただきました。ここからNRARToolkitUnity-4.1.1.zipをダウンロードします。

NyARToolKit プロジェクト日本語トップページ - OSDN

zipを解凍すると出てくる、NyARToolkitCS-4.1.1.unitypackageをUnityにインポートします。Unityを開いた状態でダブルクリックするか、UnityのAssets->Import Package->CustomPackage で選んでもよいです。

2. NRARToolKitのスクリプトを書き換える

NRARToolKitにはいくつかのサンプルがあります。今回は最もシンプルなSampleLiteを使いました。この中のARCameraBehavior.csを開き、いくつか変更します。

以下をご確認ください。元ソースのコメントは省略してます。

using UnityEngine;
using System;
using System.Collections;
using jp.nyatla.nyartoolkit.cs.markersystem;
using jp.nyatla.nyartoolkit.cs.core;
using NyARUnityUtils;
using System.IO;

public class ARCameraBehaviour : MonoBehaviour
{
 private NyARUnityMarkerSystem _ms;
 private NyARUnityWebCam _ss;
 private int mid;//marker id
 private GameObject _bg_panel;
	
 //addedd from
  public GameObject PseyeCameraImageObject;
  float scaleDegree = 1.0f;
  float scaleSec = 1.0f;
  private bool PseyeCameraImageFlag = true;
  // added to

  //ここは(3),(4)に関係するため今は不要
  //added from  
  public GameObject countDownTimeObject;
  CountDownTime countDownTime;
  public GameObject remainedBearObject;
  RemainedBear remainedBear;
  // added to
	
 void Awake(){
    WebCamDevice[] devices= WebCamTexture.devices;
    WebCamTexture w;
    if (devices.Length > 0){
    //w=new WebCamTexture(320, 240, 15);//original
    // changed from
      w=new WebCamTexture(devices[1].name,640, 480, 60);
    // changed to
      this._ss=new NyARUnityWebCam(w);
      NyARMarkerSystemConfig config = new NyARMarkerSystemConfig(w.requestedWidth,w.requestedHeight);
      this._ms=new NyARUnityMarkerSystem(config);
    //mid=this._ms.addARMarker("./Assets/Data/patt.hiro",16,25,80); //original
			
      mid=this._ms.addARMarker((Texture2D)(Resources.Load("MarkerHiro", typeof(Texture2D))),16,25,80);
    //this._bg_panel=GameObject.Find("Plane"); //original
    // changed from
      this._bg_panel=PseyeCameraImageObject;
    // changed to
			
      this._bg_panel.renderer.material.mainTexture=w;
    //this._ms.setARBackgroundTransform(this._bg_panel.transform);//ogirinal
	
      this._ms.setARCameraProjection(this.camera);
			
      }else{
	Debug.LogError("No Webcam.");
      }
  }

   void Start (){
      this._ss.start();
      countDownTime = countDownTimeObject.GetComponent<CountDownTime>();
      remainedBear = remainedBearObject.GetComponent<RemainedBear>();
   }
	
   void Update (){
     // added from
      if(PseyeCameraImageFlag == true){	
    // added to 
    this._ss.update();
	this._ms.update(this._ss);
	if(this._ms.isExistMarker(mid)){
	  this._ms.setMarkerTransform(mid,GameObject.Find("MarkerObject").transform);
     // added from
	    scaleDegree -= scaleSec * Time.deltaTime;
	    PseyeCameraImage.transform.localScale = new Vector3(scaleDegree*5,scaleDegree*5,0);
	    if(scaleDegree <0.0f){
		PseyeCameraImageFlag = false;	
		Destroy(PseyeCameraImage);
                //ここは(3),(4)に関係するため今は不要
		countDownTime.timeOnFlag = true;
		remainedBear.scoreOnFlag = true;
	    }	
	}else{
	  scaleDegree += scaleSec * Time.deltaTime;
	  PseyeCameraImage.transform.localScale = new Vector3(scaleDegree*5,scaleDegree*5,0);
        }
	  if(scaleDegree > 1.0f) scaleDegree = 1.0f;
	}
    // added to
   }
}

この中で、現実風景からVRに変化させる処理を書いています。ここを少し説明します。

2.1 認識対象を決定する処理

     NyARMarkerSystemConfig config = new NyARMarkerSystemConfig(w.requestedWidth,w.requestedHeight);
      this._ms=new NyARUnityMarkerSystem(config);
    //mid=this._ms.addARMarker("./Assets/Data/patt.hiro",16,25,80); //original
			
      mid=this._ms.addARMarker((Texture2D)(Resources.Load("MarkerHiro", typeof(Texture2D))),16,25,80);

  ・・・
     this._ms.setARCameraProjection(this.camera);
     

ここで、何を認識対象とするかを決めます。今回はNRARToolKitに付属のマーカを指定しています。ここではResource.Loadを使っているので、Resourcesフォルダ内の"MarkerHiro"というファイルを認識対象に設定しています。

if(this._ms.isExistMarker(mid)){


これで、"hiro"というマーカが認識されたらif文が真となり次の処理に進みます。

2.2 VRに切り替える処理

   scaleDegree -= scaleSec * Time.deltaTime;
   PseyeCameraImage.transform.localScale = new Vector3(scaleDegree*5,scaleDegree*5,0); 
    if(scaleDegree <0.0f){
	PseyeCameraImageFlag = false;	
	Destroy(PseyeCameraImage);
	countDownTime.timeOnFlag = true;
	remainedBear.scoreOnFlag = true;
   }	

マーカを認識すると、scaleDegreeをscaleSec*Time.deltaTimeだけ小さくします。Time*DeltaTimeは1フレームの時間です。scaleSecと掛けることで、1秒かけて変化させます。

また、scaleDegreeが0以下になると、PSeyeCameraImageのオブジェクトをDestoryで破棄し、VR世界用のフラグをtrueにします。

  }else{
   scaleDegree += scaleSec * Time.deltaTime;
   PseyeCameraImage.transform.localScale = new Vector3(scaleDegree*5,scaleDegree*5,0);
  }
    if(scaleDegree > 1.0f) scaleDegree = 1.0f;
   }

もし1秒以内にマーカを見失った場合、scaleDegreeをカウントアップさせます。scaleDegreeが1.0fを超えると、1.0fに固定されるので、マーカを見失うと、PSeyeCameraImageが元の大きさに戻る、という仕掛けです

3. ARCameraBehaviour.csをRightCameraにアタッチする

ARCameraBehaviour.csをOVRPlayerController/OVRCameraController/RightCameraにアタッチします。

また、

>|cs| public GameObject PseyeCameraImageObject; |

で宣言したので、PSeyeCameraImageをInspectorにアタッチします。

4. 動作確認

下記の動画のように、「hiro」と書かれたマーカを認識したときにPSEyeImageオブジェクトが小さくなります。