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

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

もぐら叩きAR

MOLEGORO無料posted withアプリーチ

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

ARFoundationとは

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


About AR Foundation

エレキベア
エレキベア
Unity提供のパッケージがあるのクマね
マイケル
マイケル
iOSではARKitAndroidではARCoreという
ARのフレームワークが用意されているんだけど、
ARFoundationを使えば同じコードで両方の機能を動作させることができるんだ!
Screenshot 2020 10 04 23 54 44
↑イメージ図
エレキベア
エレキベア
マルチプラットフォームというわけクマか・・・。
マイケル
マイケル
そのとおり!
さすが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アプリーチ

コメント