ARCoreで地面(平面)を検出し、その上でユニティちゃんを歩かせてみました
※正確には、地面に配置した透明なPlaneの上を歩いています。また、Planeを外れるとユニティちゃんが落下するため、移動できる範囲は5mくらいです
~ 目次 ~
- 環境
- 手順1. Unity-Chan!を導入して、PC上でユニティちゃんを動かす
- 手順2. ARCoreを導入し、Android上でユニティちゃんを表示
- 手順3. ARCoreを設定し、平面を検出できるようにする
- 手順4. ARCoreで検出した平面に、ユニティちゃんを配置
- 手順5. GUIを追加して、ユニティちゃんを動かす
- 参考にした情報
環境
- Galaxy S8 SCV36(au) ※Android 8.0.0, ARCore V1.5.180910096 をインストール済み
- Windows10(64bit)
- Unity 2018.1.1f1(64-bit)
- ARCore SDK for Unity v1.5.0
- "Unity-chan!" Model(V1.1)
手順1. Unity-Chan!を導入して、PC上でユニティちゃんを動かす
※この作業はPC単体で行います
Asset Store より
"Unity-Chan!" Model
をインポート
Assets/UnityChan/Prefabs/unitychan
をHierarchyに追加
unitychan のInspectorで下記を実施
メニューからGameObject > 3D Object > Plane を選択して、
Plane
を生成。Transform 設定で、Poisiton を (0, 0, 0) に
PC上で実行(Play)。カーソルキーでユニティちゃんの前後移動と旋回操作ができればOK
手順2. ARCoreを導入し、Android上でユニティちゃんを表示
※この作業はPCとAndroid端末を接続して行います
下記より ARCore SDK for Unity
arcore-unity-sdk-v1.5.0.unitypackage
をダウンロードし、インポート
Releases · google-ar/arcore-unity-sdk · GitHub
Assets/GoogleARCore/Prefabs/ARCore Device
をHierarchyに追加し、Main Cameraを削除
下記を参考に、Android および ARCore用のビルド設定をする
ARCore 取扱説明書 - QiitaBuild&Runする。アプリが起動したら後ろに移動して、Planeに乗ったユニティちゃんが見えればOK
手順3. ARCoreを設定し、平面を検出できるようにする
※この作業はPCとAndroid端末を接続して行います
Aseetsで右クリック。Create>GoogleARCore>SessionConfig を選択
生成された
ARCoreSessionConfig
を選択。Plane Finding Mode をHorizontal に設定
※今回は地面を検出したいので、水平面のみ検出するよう設定
Hierarchy からARCore Device を選択。AR Core Session 設定のSession Config に
ARCoreSessionConfig
をセット
メニューより、GameObject>Create Empty を選択。生成された
GameObject
に、スクリプトAssets/GoogleARCore/Examples/Common/Scripts/DetectedPlaneGenerator
を追加
DetectedPlaneGenerator 設定のDetected Plane Prefab に、
Assets/GoogleARCore/Examples/Common/Prefabs/DetectedPlaneVisualizer
をセット
Hierarchy からPlane を選択。Mesh Renderer横のチェックを外して、Plane を透明にする
※最後に透明にする予定でしたが、実行時に邪魔になるので、ここで透明にしておきますBuild&Runする。アプリが起動したら床を見渡して、メッシュが表示されたらOK
※動画では赤いメッシュになってますが、通常は最初に白いメッシュが表示されます
手順4. ARCoreで検出した平面に、ユニティちゃんを配置
※この作業はPCとAndroid端末を接続して行います
GameObject に新規スクリプト
PutUnityChan.cs
を追加
スクリプトを記述。大まかに下記を行っています
- 画面タッチを検出
- タッチ位置を、ARCore が検出した平面上での位置に変換
- 平面上に、ユニティちゃんとPlane を配置
- Anchorを設置し、ユニティちゃんとPlane をその子にする
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using GoogleARCore; public class PutUnityChan : MonoBehaviour { // 平面上に配置する ユニティちゃん と Plane を指定する public GameObject UnityChan; public GameObject Plane; // Use this for initialization void Start () { } // Update is called once per frame void Update () { // タッチしていないなら、何もしない if (Input.touchCount < 1) return; // GUIに対するタッチであれば無視する // ※この条件は、後で追加するGUI操作を意識した物。GUIを追加しない場合は不要。 if (EventSystem.current != null && EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)) return; // タッチ点の取得 Touch touch = Input.GetTouch(0); // タッチの開始以外は、無視する if (touch.phase != TouchPhase.Began) return; // タッチした先に、ARCoreが検出した平面があるかチェック // PlaneWithinPolygon:延長線上の点が「平面を構成するポリゴン境界内」に交差する点を探す TrackableHit hit; if (Frame.Raycast(touch.position.x, touch.position.y, TrackableHitFlags.PlaneWithinPolygon, out hit)) { // 平面上にオブジェクトを配置 if (hit.Trackable is DetectedPlane) { // UnityChan の位置・姿勢を指定 // ※hit.Pose.rotationは、Z+方向がカメラの向きになる // そのままだと後ろを向いてしまうので、Y軸回りに180度回転 UnityChan.transform.position = hit.Pose.position; UnityChan.transform.rotation = hit.Pose.rotation; UnityChan.transform.Rotate(0, 180, 0, Space.Self); // Plane の位置・姿勢を指定 Plane.transform.position = hit.Pose.position; Plane.transform.rotation = hit.Pose.rotation; // Anchorを生成し、各オブジェクトをAnchorの子にする // ※ARCoreで位置関係を維持するには、Anchorを生成し、その子に入れる必要がある Anchor anchor = hit.Trackable.CreateAnchor(hit.Pose); UnityChan.transform.parent = anchor.transform; Plane.transform.parent = anchor.transform; } } } }
PutUnityChan 設定の Unity Chan と Plane に、
unitychan
とPlane
をセット
unitychan にアタッチされているスクリプト
UnityChanControlScriptWithRgidBody.cs
を修正(2か所)
////// 1. キャラクターを移動させる(100行付近)を、ローカル座標からワールド座標に変更 // 上下のキー入力でキャラクターを移動させる #if false transform.localPosition += velocity * Time.fixedDeltaTime; #else // ワールド座標系で移動するように変更 // ※オブジェクトをAnchorの子オブジェクトとしている関係で // ローカル座標系で移動させると、おかしな方向に移動してしまう。 transform.position += velocity * Time.fixedDeltaTime; #endif
////// 2. GUI表示(190行付近)を、コメントアウト void OnGUI() { #if false // GUI表示は無効にする GUI.Box(new Rect(Screen.width -260, 10 ,250 ,150), "Interaction"); GUI.Label(new Rect(Screen.width -245,30,250,30),"Up/Down Arrow : Go Forwald/Go Back"); GUI.Label(new Rect(Screen.width -245,50,250,30),"Left/Right Arrow : Turn Left/Turn Right"); GUI.Label(new Rect(Screen.width -245,70,250,30),"Hit Space key while Running : Jump"); GUI.Label(new Rect(Screen.width -245,90,250,30),"Hit Spase key while Stopping : Rest"); GUI.Label(new Rect(Screen.width -245,110,250,30),"Left Control : Front Camera"); GUI.Label(new Rect(Screen.width -245,130,250,30),"Alt : LookAt Camera"); #endif }
- Build&Runする
- アプリが起動したら床を見渡して、メッシュを表示させる
- メッシュ内をタップし、ユニティちゃんが表示されればOK
- もし、ゲームパッドやキーボードが使える状態なら、ユニティちゃんを操作できます
※DualShock4なら左スティック(環境依存かも)、キーボードならカーソルキーで操作
手順5. GUIを追加して、ユニティちゃんを動かす
※この作業はPCとAndroid端末を接続して行います
メニューより、Assets > Import Package > CrossPlatformInput を選択、
CrossPlatformInput
をインポート
Assets/Standard Assets/CrossPlatformInput/Prefabs/MobileAircraftControls
をHierarchyに追加
MobileAircraftControls
以下を修正Throttle
,TiltSteerInputV
,TiltSteerInputH
を削除
※ 最初の削除時に、Brake Prefab instance のメッセージが出るがContinue を押す- メニューより、GameObject>UI>Panel を選択し、
Panel
を追加。MobileAircraftControlsの一番上に配置 Brake
を右クリックしてDuplicate(複製)を選択し、Brake(1)
を作成Brake
の名称をWalk
に変更。Brake(1)
の名称をStop
に変更
~ 修正内容の補足 ~
- Left, Rightボタン: 左右旋回用のボタン
- Walk, Stopボタン: 歩く、停止用のボタン
- Panel: ボタン周辺を触ったときに画面タッチが誤動作するのを防ぐために設置
各オブジェクトのInspector を修正
- 各オブジェクトのRect Transfom 設定で、Anchorsを変更して、配置を修正
Walk
とStop
のEvent Trigger 設定にてButtonHandler.SetAxisPositiveState
をButtonHandler.SetDownState
に変更ButtonHandler.SetAxisNegativeState
をButtonHandler.SetUpState
に変更
Walk
とStop
のButton Handler 設定にて、Name を"Walk"と"Stop"に変更Walk
とStop
の子に入っているText
の設定にて、Textを"Walk"と"Stop"に変更
~ 修正内容の補足 ~
- Left, Rightボタンは、Name: "Horizontal"と設定。CrossPlatformInputManager.GetAxis("Horizontal") で、2つのボタン押下に応じた値(-1, 0, +1)を取得できる
- Walk, Stopボタンは、Name: "Walk","Stop"と設定。それぞれのボタン押下を CrossPlatformInputManager.GetButtonDown("Walk" or "Stop")で取得できる
unitychan にアタッチされているスクリプト
UnityChanControlScriptWithRgidBody.cs
を修正(3か所)
////// 1. CrossPlatformInputを使うための using ディレクティブ 追加(10行付近) using UnityEngine; using System.Collections; #if true using UnityStandardAssets.CrossPlatformInput; #endif
////// 2. 前後移動を記憶するためのメンバ変数を追加(40行付近) private GameObject cameraObject; // メインカメラへの参照 #if true private float vertical_ = 0.0f; // 前後移動を記憶 #endif // アニメーター各ステートへの参照 static int idleState = Animator.StringToHash("Base Layer.Idle");
////// 3. 移動操作(70行付近)で、CrossPlatformInputを使うように修正 void FixedUpdate () { #if false float h = Input.GetAxis("Horizontal"); // 入力デバイスの水平軸をhで定義 float v = Input.GetAxis("Vertical"); // 入力デバイスの垂直軸をvで定義 #else // CrossPlatformInputによる操作 // 左右移動は、バーチャルパッドの水平軸([Left],[Right]ボタン操作)をそのまま反映 float h = CrossPlatformInputManager.GetAxis("Horizontal"); // 前後移動は、[Walk],[Stop]ボタン押下に応じて、前方移動・停止を切り替え if (CrossPlatformInputManager.GetButtonDown("Walk")) { vertical_ = 0.15f; } else if (CrossPlatformInputManager.GetButtonDown("Stop")) { vertical_ = 0.0f; } float v = vertical_; #endif
UnityChanControlScriptWithRgidBody の設定で、移動速度を遅くする
※デフォルトの速度だと、操作しにくいため- Anim Speed: 1
- Foward Speed: 3.5
- Rotate Speed: 1.5
Build&Runする
- アプリが起動したら床を見渡して、メッシュを表示させる
- メッシュ内をタップすると、ユニティちゃんが表示される
Leftボタン
,Rightボタン
で、ユニティちゃんが旋回するWalkボタン
,Stopボタン
で、ユニティちゃんの歩く・止まるを操作できればOK
参考にした情報
ヽ|∵|ゝ(Fantom) の 開発blog? - 【Unity】ARCore を使って現実世界にプロ生ちゃんを召喚してみる
⇒ こちらを見たのがきっかけで、自分でも試してみましたtks_yoshinagaの日記 - ARCore対応コンテンツ開発入門
ARコンテンツ作成勉強会資料 - はじめようArcore (修正版)
⇒ ARCoreの導入、検出した平面へのオブジェクト配置は、こちらの資料に従って進めましたQiita @taptappun さん - ARCore 取扱説明書
⇒ ARCoreの情報は、よくこちらを参照しますおもちゃラボ - 【Unity】ボタンを押したときに画面クリックは無視する
この作品はユニティちゃんライセンス条項の元に提供されています