ゲーム開発
Unity
UnrealEngine
C++
Blender
ゲーム数学
ゲームAI
グラフィックス
サウンド
アニメーション
GBDK
制作日記
IT関連
ツール開発
フロントエンド関連
サーバサイド関連
WordPress関連
ソフトウェア設計
おすすめ技術書
音楽
DTM
楽器・機材
ピアノ
ラーメン日記
四コマ漫画
その他
おすすめアイテム
おもしろコラム
  • ゲーム開発
    • Unity
    • UnrealEngine
    • C++
    • Blender
    • ゲーム数学
    • ゲームAI
    • グラフィックス
    • サウンド
    • アニメーション
    • GBDK
    • 制作日記
  • IT関連
    • ツール開発
    • フロントエンド関連
    • サーバサイド関連
    • WordPress関連
    • ソフトウェア設計
    • おすすめ技術書
  • 音楽
    • DTM
    • 楽器・機材
    • ピアノ
  • ラーメン日記
    • 四コマ漫画
      • その他
        • おすすめアイテム
        • おもしろコラム
      1. ホーム
      2. 20201004_01

      【Unity】AR空間のランダム位置にオブジェクトを生成する【ARFoundation】

      Unityアセット関連もぐら叩きARARARFoundation
      2020-10-05

      マイケル
      マイケル
      みてくれよエレキベア!
      エレキベア
      エレキベア
      なにクマか
      もぐら叩きAR

      もぐら叩きAR

      MOLEGORO無料posted withアプリーチ

      マイケル
      マイケル
      今度はもぐら叩きのARゲームを開発したんだ!
      エレキベア
      エレキベア
      おーARクマか
      最近の流行クマね〜〜〜
      マイケル
      マイケル
      今回はこのARゲームの肝になる、
      「AR空間のランダム位置にオブジェクトを生成する」
      テクニックについて紹介するぜ!
      エレキベア
      エレキベア
      それは楽しみクマ
      でもなんだかARって難しそうクマね〜〜〜〜
      マイケル
      マイケル
      今回はUnityが提供している、
      ARFoundationというAR開発パッケージを使用したんだけど、
      思ってたより簡単に使うことができたよ!
      マイケル
      マイケル
      まずはARFoundationがどんなものかについて見ていこう!
      エレキベア
      エレキベア
      クマ〜〜〜〜〜〜〜

      ARFoundationとは

      マイケル
      マイケル
      先ほど話した通り、ARFoundationはUnityが提供している
      AR開発のパッケージになります。


      About AR Foundation

      エレキベア
      エレキベア
      Unity提供のパッケージがあるのクマね
      マイケル
      マイケル
      iOSではARKitAndroidではARCoreという
      ARのフレームワークが用意されているんだけど、
      ARFoundationを使えば同じコードで両方の機能を動作させることができるんだ!

      ↑イメージ図
      エレキベア
      エレキベア
      マルチプラットフォームというわけクマか・・・。
      マイケル
      マイケル
      そのとおり!
      さすがITクマだね

      スクリプトの実装

      マイケル
      マイケル
      インポート方法や基本的な使い方については今回は割愛します。
      パッケージにはサンプルが用意されているので、いろいろ試してみてください!
      マイケル
      マイケル
      ちなみに僕は下記サイト等を参考にさせてもらいました!


      参考サイト:
      【Unity】AR Foundation(ARKitとARCoreのマルチプラットフォームAR環境)の超入門
      UnityでARKit3を動かすためにAR Foundationを使ってみる

      エレキベア
      エレキベア
      どちらもわかりやすいサイトクマね
      マイケル
      マイケル
      それじゃさっそく、ランダム位置の生成処理を実装していこう!
      エレキベア
      エレキベア
      やったるクマ〜〜〜〜〜〜!!
      マイケル
      マイケル
      ざっくりとした処理としては

      1.ARで検出した面を取得・保持する
      2.保持した面の大きさから、ランダム位置を決定する

      といった流れで実装するよ!

      ARPlaneの取得

      マイケル
      マイケル
      ARPlane(ARで検出した面)の取得処理は以下になります!
      [RequireComponent(typeof(ARRaycastManager))]
      public class GameSceneManager : MonoBehaviour
      {
          ARPlaneManager aRPlaneManager;
          AssetsManager assetsManager;
          
          private TrackableCollection<ARPlane> playTrackableCollection;
          private List<ARPlane> playArPlaneList;
      
      ・・・略・・・
      
          private void Awake()
          {
              aRPlaneManager = FindObjectOfType<ARPlaneManager>();
              assetsManager = FindObjectOfType<AssetsManager>();
          }
      
          // --------------- 初期状態 ---------------
          void InitStart()
          {
          }
      
          void InitUpdate()
          {
              // プレーンを取得
              ARPlaneManager aRPlaneManager = FindObjectOfType<ARPlaneManager>();
              TrackableCollection<ARPlane> trackableCollection = aRPlaneManager.trackables;
              // プレーンを取得できた場合
              if (trackableCollection.count > 0)
              {
                  playTrackableCollection = trackableCollection;
              }
          }
      
      ・・・略・・・
      
          // --------------- UIイベントトリガー ---------------
          // スタートボタン押下時
          public void PushGameStartButton()
          {
              // プレーンをリストに変換
              playArPlaneList = new List<ARPlane>();
              foreach (ARPlane aRPlane in playTrackableCollection)
              {
                  playArPlaneList.Add(aRPlane);
              }
              // ARPlaneの色を透明にする
              foreach (ARPlane aRPlane in playArPlaneList)
              {
                  Color color = aRPlane.gameObject.GetComponent<Renderer>().material.color;
                  color.a = 0;
                  aRPlane.gameObject.GetComponent<Renderer>().material.color = color;
              }
              // PlaneManagerを無効化
              aRPlaneManager.detectionMode = PlaneDetectionMode.None;
          }
          
      ・・・略・・・
      
      }
      エレキベア
      エレキベア
      長くて分からないクマ〜〜
      マイケル
      マイケル
      少し細かく見ていこう!


      ・ARPlaneび取得処理

      マイケル
      マイケル
      下記部分でARPlaneの取得処理を行っています。
      「aRPlaneManager.trackables」に検知された面が設定されているので、変数に格納します!
      
          void InitUpdate()
          {
              // プレーンを取得
              ARPlaneManager aRPlaneManager = FindObjectOfType<ARPlaneManager>();
              TrackableCollection<ARPlane> trackableCollection = aRPlaneManager.trackables;
              // プレーンを取得できた場合
              if (trackableCollection.count > 0)
              {
                  playTrackableCollection = trackableCollection;
              }
          }
      


      ・ARPlaneの保持及び検知終了処理

      マイケル
      マイケル
      そして下記部分で、スタートボタンが押された際に
      ARPlaneのリストとして変数に保持し、ARPlaneManagerを無効化することで
      ボタン押下時のARPlaneオブジェクトを保持することができます。
      
          // スタートボタン押下時
          public void PushGameStartButton()
          {
              // プレーンをリストに変換
              playArPlaneList = new List<ARPlane>();
              foreach (ARPlane aRPlane in playTrackableCollection)
              {
                  playArPlaneList.Add(aRPlane);
              }
              // ARPlaneの色を透明にする
              foreach (ARPlane aRPlane in playArPlaneList)
              {
                  Color color = aRPlane.gameObject.GetComponent<Renderer>().material.color;
                  color.a = 0;
                  aRPlane.gameObject.GetComponent<Renderer>().material.color = color;
              }
              // PlaneManagerを無効化
              aRPlaneManager.detectionMode = PlaneDetectionMode.None;
          }
      
      エレキベア
      エレキベア
      色を変えてる部分はなにクマ?
      マイケル
      マイケル
      よく気づいたね!
      スタートボタン押下後はARPlaneを透明にするために
      「color.a=0」を設定しているんだ。
      エレキベア
      エレキベア
      なるほどクマ
      実体は残して色だけ透明にするクマね

      ランダム位置に生成

      マイケル
      マイケル
      ARPlaneのリストが保持できたら、
      あとはランダムで位置を決めて生成するのみ!
      スクリプトは以下になります。
      [RequireComponent(typeof(ARRaycastManager))]
      public class GameSceneManager : MonoBehaviour
      {
      
      ・・・略・・・
          
          void GameStart()
          {
          }
      
          void GameUpdate()
          {
              // モグラ生成処理
              GenerateMoleObj(mole_PlacedPrefab);
          }
      
          // モグラオブジェクト生成処理
          private GameObject GenerateMoleObj(GameObject placedPrefab)
          {
              // モグラをプレーンの上に生成
              ARPlane alPlane = playArPlaneList[Random.Range(0, playArPlaneList.Count)];
              Transform planeTransform = alPlane.gameObject.transform;
              // ランダム位置に生成
              float width = alPlane.gameObject.GetComponent<Renderer>().bounds.size.x;
              float height = alPlane.gameObject.GetComponent<Renderer>().bounds.size.z;
              float randomWidth = Random.Range(-width / 2, width / 2);
              float randomHeight = Random.Range(-height / 2, height / 2);
              if (planeTransform.rotation.eulerAngles.x >= 45)
              {
                  // オブジェクトの角度が45度以上(垂直)
                  // 位置 x: 平面 + ランダム, y: 平面 + ランダム, z: 平面
                  // 回転 x: 平面 * -1,     y: 平面 + 180,      z:平面
                  return Instantiate(placedPrefab,
                      new Vector3(planeTransform.position.x + randomWidth, planeTransform.position.y + randomHeight, planeTransform.position.z),
                      Quaternion.Euler(planeTransform.rotation.eulerAngles.x * -1, planeTransform.rotation.eulerAngles.y + 180.0f, planeTransform.rotation.eulerAngles.z));
              }
              else
              {
                  // オブジェクトの角度が0度(水平)
                  // 位置 x: 平面 + ランダム, y: 平面, z: 平面 + ランダム
                  // 回転 x: 平面 * -1,     y: 平面 + 180,      z:平面
                  return Instantiate(placedPrefab,
                      new Vector3(planeTransform.position.x + randomWidth, planeTransform.position.y, planeTransform.position.z + randomHeight),
                      Quaternion.Euler(planeTransform.rotation.eulerAngles.x * -1, planeTransform.rotation.eulerAngles.y + 180.0f, planeTransform.rotation.eulerAngles.z));
              }
          }
      }
      エレキベア
      エレキベア
      全然分からないクマ
      マイケル
      マイケル
      これもポイントだけ見ていこう!


      ・ランダムにARPlaneを選定

      マイケル
      マイケル
      まず下記の部分でリストからランダムでARPlaneを一つ取得するよ。
      
              // モグラをプレーンの上に生成
              ARPlane alPlane = playArPlaneList[Random.Range(0, playArPlaneList.Count)];
      
      エレキベア
      エレキベア
      検知した面からランダムに選ぶクマね


      ・オブジェクト生成の位置を選定

      マイケル
      マイケル
      生成するARPlaneを決めたら、大きさを取得してランダムに位置を設定するんだ!
      
              // ランダム位置に生成
              float width = alPlane.gameObject.GetComponent<Renderer>().bounds.size.x;
              float height = alPlane.gameObject.GetComponent<Renderer>().bounds.size.z;
              float randomWidth = Random.Range(-width / 2, width / 2);
              float randomHeight = Random.Range(-height / 2, height / 2);
      
      エレキベア
      エレキベア
      面の縦幅・横幅から位置を出すということクマね
      マイケル
      マイケル
      その通り!
      こうすることで下の画像みたいにランダムにオブジェクトを出現させることができるようになるよ!

      IMG 7385

      エレキベア
      エレキベア
      うじゃうじゃ出てきたクマ・・・。

      ARPlane再読込

      マイケル
      マイケル
      ついでだけど、AR検知結果をクリアして再読込させる方法についても紹介するよ!
      [RequireComponent(typeof(ARRaycastManager))]
      public class GameSceneManager : MonoBehaviour
      {
      
      ・・・略・・・
      
          public ARSession session;
          public GameObject sessionPrefab;
      
          // ARリロードボタン押下時
          public void PushArReloadButton()
          {
              // ARセッションの再読込
              if (session != null)
              {
                  StartCoroutine(DoReload());
              }
          }
      
          // ARセッションの再読込
          IEnumerator DoReload()
          {
              Destroy(session.gameObject);
              yield return null;
      
              if (sessionPrefab != null)
              {
                  session = Instantiate(sessionPrefab).GetComponent<ARSession>();
              }
          }
          
      ・・・略・・・
      
      }
      マイケル
      マイケル
      上記のようにARSessionを再度Instantiateさせることで
      再度読込処理を行うことができるよ!
      エレキベア
      エレキベア
      簡単クマ〜〜〜〜〜

      おわりに

      マイケル
      マイケル
      というわけで今回は
      「AR空間のランダム位置にオブジェクトを生成する」方法についての紹介でした!
      どうだったかな?
      エレキベア
      エレキベア
      本当に現実世界に現れたようで楽しかったクマ
      他の機能も使ってみたいクマね〜〜〜〜
      マイケル
      マイケル
      AR機能は他にもいろいろあるし
      今後も進化し続けるだろうね。
      また積極的に使っていこう!
      マイケル
      マイケル
      それでは今日はこの辺で!
      アデュー!!
      エレキベア
      エレキベア
      クマ〜〜〜〜〜〜〜〜

      【Unity】AR空間のランダム位置にオブジェクトを生成する【ARFoundation】 〜完〜

      もぐら叩きAR

      もぐら叩きAR

      MOLEGORO無料posted withアプリーチ


      Unityアセット関連もぐら叩きARARARFoundation
      2020-10-05

      関連記事
      【Unity】Timeline × Excelでスライドショーを効率よく制作する
      2024-10-31
      【Unity】Boidsアルゴリズムを用いて魚の群集シミュレーションを実装する
      2024-05-28
      【Unity】GoでのランキングAPI実装とVPSへのデプロイ方法についてまとめる【Go言語】
      2024-04-14
      【Unity】第二回 Wwiseを使用したサウンド制御 〜インタラクティブミュージック編〜
      2024-03-30
      【Unity】第一回 Wwiseを使用したサウンド制御 〜基本動作編〜
      2024-03-30
      【Unity】第二回 CRI ADXを使用したサウンド制御 〜インタラクティブミュージック編〜
      2024-03-28
      【Unity】第一回 CRI ADXを使用したサウンド制御 〜基本動作、周波数解析編〜
      2024-03-28
      【Unity】サウンドミドルウェアに依存しない設計を考える【CRI ADX・Wwise】
      2024-03-27