20190711のUnityに関する記事は7件です。

Unity内のファイルやHierarchyの名前を一括で変更してくれるEz Rename.の紹介

はじめに

VCI(Virtual Cast Interactive)の作成時に、各GameObjectの名前やMaterial、Audioの名前の付け方を統一したりインクリメント形式で付けると、luaスクリプトで操作する際に取り回しがしやすい事が多いです。
ということで、今回はファイル名やHierarchyの名前を一括で変更することのできるEz Rename.というアセットの使い方を解説していきたいと思います。
こんなアセットです。
EzReNameRename.gif

1. Ez Rename.のダウンロード・インポート

まず、Ez Rename.をダウンロード・インポートする必要があります。
UnityのAsset Store内でダウンロード・インポートを行ってください。
Unityのアセットストアの使い方については下記サイトを参考にしてください。
Unityのアセットストア(AssetStore)を使う方法【初心者向け】
下記動画Gifのように検索をかけると出てきますので、それのダウンロード・インポートボタンを押してImportしてください。
EzReNameInstall.gif

2. Ez Rename.のウィンドウの表示

WindowメニューからEz Renameを選択して、Openから、Ez Rename.のウィンドウを表示することができます。
こちらを使って名前の変更を行います。
EzReNameOpenWindow.gif

3. Ez Rename.でできること。

使い方についてはこちらに載っています。英語ですが。
Ez Rename Guide
英語を読みたくない方向けに、ざっくりとした解説を記載します。

Rename

・複数の名前の変更が一括でできます。
・赤い場所をクリックすると、現在選択しているGameObjectAssetの名前をコピーできます。
image.png
Hierarchyボタンを押せば、選択しているHierarchyGameObjectの名前を変更します。
Poject Folderボタンを押せば、選択しているProjectのファイルの名前を変更します。
・CMD + Z もしくは CTRL + Zで変更を取り消すことができます。
EzReNameRename.gif

Replace

・複数の選択しているGameObjectかファイルの名前を置換できます。
・CMD + Z もしくは CTRL + Zで変更を取り消すことができます。

Insert

・複数の選択しているGameObjectかファイルの名前に文字列を追加できます。
・先頭、最後尾、指定文字列目 を指定できます。
・CMD + Z もしくは CTRL + Zで変更を取り消すことができます。

Remove

・複数の選択しているGameObjectかファイルの名前を指定文字列分削除できます。
・先頭、最後尾、指定文字列目 を指定できます。
・CMD + Z もしくは CTRL + Zで変更を取り消すことができます。

Case Change

・複数の選択しているGameObjectかファイルの名前の英語の大文字・小文字を整形できます。
・全て大文字・先頭のみ大文字・全て小文字 のいずれかを指定できます。
・CMD + Z もしくは CTRL + Zで変更を取り消すことができます。

Sort

・複数の選択しているGameObjectかファイルの順番を入れ替える事ができます。
・昇順・降順 のいずれかを指定できます。
・CMD + Z もしくは CTRL + Zで変更を取り消すことができます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

javascript

test

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【VFX Graph】連番アニメーションを使ってみた

はじめに

Visual Effect Graphでスプライトシートを使った連番アニメーションを使ってみました。

1.gif

環境

【Unityバージョン】
Unity2018.3.14f1

【パッケージ】
Hight Definition RP - Version 4.1.0(Preview)
Visual Effect Graph - Version 4.10.0(Preview)

【OS】
Windows 10

Visual Effect Graph 完成図

今回作成したVisual Effect Graphは以下になります。

STEP0. スプライトシートの用意

今回のエフェクトでは、以下のテクスチャを使用しました。
Photoshopを使って手描きで作成しました。

スプライトシート(透過png)

STEP1. UV Mode = Flipbook に設定

Output系ノードのUv ModeFlipbookに設定し、スプライトシートのテクスチャとスプライトシート分割数を設定します。

image.png

ただし、これだけではまだテクスチャは動きません。

STEP2. Flipbook Playerを追加

UpdateノードにFlipbook Playerブロックを追加することで、アニメーションが動くようになります
frameRateの部分にフレームレートを指定します。 今回は24を指定しました。
image.png

以上でエフェクトは完成です。

完成したエフェクト

1.gif

炎が光っている感じはPost Processing StackのBloomを使って作っています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Unity] Destory処理中のOnDisableとOnDestroyの呼び出され方と、その最中にGameObjectの親子関係を解除したときの挙動

結論から

OnDisableやOnDestroyで親子関係を変えると意図しない挙動を引き起こしやすいので
Destroyする前に親子関係を解除した方が良い

検証用GameObjectの構造とコード

コメント 2019-07-09 153613.png

DestroyTest
DestroyTest : MonoBehaviour
    {
        public bool detachChildrenOnDisable;
        public bool detachParentOnDisable;
        public bool detachChildrenOnDestroy;
        public bool detachParentOnDestroy;

        private void OnDisable()
        {
            if (detachChildrenOnDisable) { transform.DetachChildren(); }
            if (detachParentOnDisable) { transform.parent = null; }
            Debug.Log(gameObject.name + "OnDisable");
        }

        private void OnDestroy()
        {
            if (detachChildrenOnDestroy) { transform.DetachChildren(); }
            if (detachParentOnDestroy) { transform.parent = null; }
            Debug.Log(gameObject.name + "OnDestroy");

        }
    }

コードから親をDestroyした場合

親→子→孫という順番でOnDisableが呼ばれ、その後同じ順序でOnDestroyも呼ばれる
コメント 2019-07-09 134746.png

Editorの操作から削除した場合

コメント 2019-07-09 154128.png
Disableは孫→子→親の逆順で呼ばれ、Destroyはコード側の操作と同じ順序で呼ばれる
コメント 2019-07-09 134916.png

親のOnDestroyで親子関係を解除した場合

すべてのOnDisableが呼び出された後、親子関係が解除され親のOnDestroyのみ呼ばれる
1213213.JPG

この場合DestroyしたGameObjectの直下にある子のみdisableのままになり孫はEnableが呼ばれコンポーネントが起動する
1010.JPG
コードにOnEnableを書き加え確認するとしっかり呼ばれているのを確認できる
1111.JPG
Destroy処理の途中で親子関係を外す場合に期待する挙動としては確かに子はDisableされずEnableのままにしてほしいと思うので
中断できた場合は改めてEnableにするのだろうが
構造的に子か否かでその処理が走るかどうか決めていて親になった「子」には適用されないのだろう

親のOnDisableで親子関係を解除した場合

特筆することもなく親だけで処理が完結する
212212.JPG

子のOnDestroyで親を外した時

親を外す処理はDestory中には不可能で、エラーになりそのままDestroyされる
22222222.JPG

子のOnDisableで親を外した時

子でOnDisableの伝播が止まり孫はDisableされていないのでOnEnableも呼ばれない
1515654.JPG
子はDisableのままになる
654566.JPG

Unityが用意しているコンポーネントは?

子がRootへ変化する状況では同じくDisableされる
16548163.JPG
Particle Systemなどは出てるパーティクルが一度すべて消える

感想

あんまり無い状況かもしれませんが、Destory中に親子関係を解除するとコンポーネントがDisableのままというのは
結構罠だと思うので、事前に解除しておきましょう

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AzurePlayFabのランキング機能を使ってみた&ついでにランキング報酬も配ってみた

まえがき

オンラインゲームにかかせないランキング機能、自分で作るのは少し面倒ですよね。
PlayFab にはユーザーのランキングを管理したり、ランキングに応じて報酬を配ったりできる機能があります。

今回は以前作ったユニティちゃんの縄跳びゲームに PlayFab のランキング機能を組み込んでみましたが、簡単便利で素敵だったので記事に残しておこうと思います。

成果物

※ゲームプレイ後に超簡易的なランキング画面が表示されます。
JumpRope.gif

使用する PlayFab の API

1. 事前準備

1.1. クライアントから PlayFab への統計情報のポストを許可しておく

PlayFab は統計情報(スコアなど)をクライアントから送信することをデフォルトでは禁止しています。

チート対策のために基本的にはサーバー側で処理してね、とのことですが今回は個人制作の趣味のゲームですし、クライアントからサクッと値を送信したいと思います。

そのために GameManager の設定画面で クライアントにプレイヤー統計情報のポストを許可する を有効にします。
image.png

これを忘れるとクライアントから統計情報を送信したときに下記のエラーがでるので注意してください。
image.png

1.2. ランキングの定義を作成しておく

GameManager で新しいランキングを作成します。
image.png

続いてどのようなランキングを作成するか決めます。
image.png

  • 統計情報名
    わかりやすい名前ならなんでも大丈夫です。
    一度決めると変更できないので慎重に。

  • リセット頻度
    今回は手動にしますが、毎時/毎日/毎週/毎月なども選べます。
    ランキングリセットの際は自動で報酬を配布したりすることもできます。(後述)

  • 集計方法
    今回はプレイヤーごとの最多ジャンプ成功数をランキング表示したいので 最大 にしておきます。

1.3. ユーザーの DisplayName を登録しておく

ランキングにユーザー名を表示するためにはユーザーの DisplayName を登録しておく必要があります。
ゲーム内でユーザー名を設定する画面を作り、以下のようなコードで PlayFab へ登録しておきましょう。

    private void SetUserName(string userName)
    {
        var request = new UpdateUserTitleDisplayNameRequest
        {
            DisplayName = userName
        };

        PlayFabClientAPI.UpdateUserTitleDisplayName(request, OnSuccess, OnError);

        void OnSuccess(UpdateUserTitleDisplayNameResult result)
        {
            Debug.Log("success!");
        }

        void OnError(PlayFabError error)
        {
            Debug.Log($"{error.Error}");
        }
    }

ちなみに登録した DisplayName は GameManager のプレイヤー一覧などにも自動的に表示されます。
地味に嬉しいですね!
image.png

2. ランキングの実装

2.1. 統計情報(スコア)の送信

以下のようなコードで統計情報を送信することができます。

    private void SendPlayScore(int score)
    {
        var statisticUpdate = new StatisticUpdate
        {
            // 統計情報名を指定します。
            StatisticName = "JumpCount",
            Value = score,
        };

        var request = new UpdatePlayerStatisticsRequest
        {
            Statistics = new List<StatisticUpdate>
            {
                statisticUpdate
            }
        };

        PlayFabClientAPI.UpdatePlayerStatistics(request, OnSuccess, OnError);

        void OnSuccess(UpdatePlayerStatisticsResult result)
        {
            Debug.Log("success!");
        }

        void OnError(PlayFabError error)
        {
            Debug.Log($"{error.Error}");
        }
    }

※送信した統計情報がランキングに反映されるまで1~2秒かかる場合があります。
※ですので送信後すぐにランキングを取得するような設計は控えましょう。
こちらの記事で詳しく解説されています。

2.2. ランキングの取得

以下のようなコードでランキングを取得することができます。

    private void GetRanking()
    {
        var request = new GetLeaderboardRequest
        {
            StatisticName = "JumpCount", // 統計情報名を指定します。
            StartPosition = 0, // 何位以降のランキングを取得するか指定します。
            MaxResultsCount = 100 // ランキングデータを何件取得するか指定します。最大が100です。
        };

        PlayFabClientAPI.GetLeaderboard(request, OnSuccess, OnError);

        void OnSuccess(GetLeaderboardResult leaderboardResult)
        {
            // 実際は良い感じのランキングを表示するコードにします。
            foreach (var item in leaderboardResult.Leaderboard)
            {
                // Positionは順位です。0から始まるので+1して表示しています。
                Debug.Log($"{item.Position + 1}位: {item.DisplayName} - {item.StatValue}回");
            }
        }

        void OnError(PlayFabError error)
        {
            Debug.Log($"{error.Error}");
        }
    }

実行すると以下のような結果が得られます。
これを良い感じに UI に組み込むだけでランキングの完成です!
image.png

ちなみにランキングのデータは GameManager で確認することが可能です。便利ですね。
image.png

そういえば今回は1位からのランキングを取得/表示しましたが、実際は自分の+-5位のランキングを表示したかったりすると思います。

その場合は GetLeaderboard の代わりに GetLeaderboardAroundPlayer を使います。
コードは殆ど同じです。

    private void GetRanking()
    {
        var request = new GetLeaderboardAroundPlayerRequest
        {
            StatisticName = "JumpCount", // 統計情報名を指定します。
            MaxResultsCount = 11 // 自分と+-5位をあわせて合計11件を取得します。
        };

        PlayFabClientAPI.GetLeaderboardAroundPlayer(request, OnSuccess, OnError);

        void OnSuccess(GetLeaderboardAroundPlayerResult leaderboardResult)
        {
            // 実際は良い感じのランキングを表示するコードにします。
            foreach (var item in leaderboardResult.Leaderboard)
            {
                // Positionは順位です。0から始まるので+1して表示しています。
                Debug.Log($"{item.Position + 1}位: {item.DisplayName} - {item.StatValue}回");
            }
        }

        void OnError(PlayFabError error)
        {
            Debug.Log($"{error.Error}");
        }
    }

ゲーム内の実装の話はここまでです。
最後にランキング報酬を配ってみましょう。

3. ランキング報酬の配布

GameManager でランキングを開きます。
image.png

プライズテーブルを開いて、新しいプライズテーブルを作成します。
image.png

ランキング1~5位には魔法石10個、6~10位には魔法石5個を配る設定を作ってみました。
画面が直感的に操作できて素敵です。(スクショが長くてごめんなさい)
image.png
※アイテムは複数種類を一度に配布することも可能です。
※無料プランではランキング10位までしか報酬を配れないので注意してください。
※$99.99課金すると1000位まで配れるようになります。
※報酬を配る以外にも、ランキングに応じてメールを送信する、プッシュ通知を送る、自分で書いたスクリプトを実行するなどの処理が可能です。

JumpCount のランキング表示に戻って、今すぐリセットを押します。
イベントが終わったらポチッとリセットする感じの運用ですね。
image.png

確認画面が表示されるのでリセットしてください。
これでランキングがリセットされて、同時に報酬が配布されます。
image.png

先程1位だったNishiさんのインベントリを覗いてみると、ちゃんと魔法石が配布されていますね。
image.png

あとがき

ゲームにランキングを簡単に実装できると聞いて試してみましたが、想像以上に簡単で驚きました。
報酬の配布もとても便利で最高ではないでしょうか。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AzurePlayFabのとても便利なランキング機能を使ってみた&ついでにランキング報酬も配ってみた

まえがき

オンラインゲームにかかせないランキング機能、自分で作るのは少し面倒ですよね。
PlayFab にはユーザーのランキングを管理したり、ランキングに応じて報酬を配ったりできる機能があります。

試しに使ってみたところ、とても便利な機能だったので記事に残しておこうと思います。

成果物

※ゲームプレイ後に超簡易的なランキング画面が表示されます。
JumpRope.gif

使用する PlayFab の API

1. 事前準備

1.1. クライアントから PlayFab への統計情報のポストを許可しておく

PlayFab は統計情報(スコアなど)をクライアントから送信することをデフォルトでは禁止しています。

チート対策のために基本的にはサーバー側で処理してね、とのことですが今回は個人制作の趣味のゲームですし、クライアントからサクッと値を送信したいと思います。

そのために GameManager の設定画面で クライアントにプレイヤー統計情報のポストを許可する を有効にします。
image.png

これを忘れるとクライアントから統計情報を送信したときに下記のエラーがでるので注意してください。
image.png

1.2. ランキングの定義を作成しておく

GameManager で新しいランキングを作成します。
image.png

続いてどのようなランキングを作成するか決めます。
image.png

  • 統計情報名
    わかりやすい名前ならなんでも大丈夫です。
    一度決めると変更できないので慎重に。

  • リセット頻度
    今回は手動にしますが、毎時/毎日/毎週/毎月なども選べます。
    ランキングリセットの際は自動で報酬を配布したりすることもできます。(後述)

  • 集計方法
    今回はプレイヤーごとの最多ジャンプ成功数をランキング表示したいので 最大 にしておきます。

1.3. ユーザーの DisplayName を登録しておく

ランキングにユーザー名を表示するためにはユーザーの DisplayName を登録しておく必要があります。
ゲーム内でユーザー名を設定する画面を作り、以下のようなコードで PlayFab へ登録しておきましょう。

    private void SetUserName(string userName)
    {
        var request = new UpdateUserTitleDisplayNameRequest
        {
            DisplayName = userName
        };

        PlayFabClientAPI.UpdateUserTitleDisplayName(request, OnSuccess, OnError);

        void OnSuccess(UpdateUserTitleDisplayNameResult result)
        {
            Debug.Log("success!");
        }

        void OnError(PlayFabError error)
        {
            Debug.Log($"{error.Error}");
        }
    }

ちなみに登録した DisplayName は GameManager のプレイヤー一覧などにも自動的に表示されます。
地味に嬉しいですね!
image.png

2. ランキングの実装

2.1. 統計情報(スコア)の送信

以下のようなコードで統計情報を送信することができます。

    private void SendPlayScore(int score)
    {
        var statisticUpdate = new StatisticUpdate
        {
            // 統計情報名を指定します。
            StatisticName = "JumpCount",
            Value = score,
        };

        var request = new UpdatePlayerStatisticsRequest
        {
            Statistics = new List<StatisticUpdate>
            {
                statisticUpdate
            }
        };

        PlayFabClientAPI.UpdatePlayerStatistics(request, OnSuccess, OnError);

        void OnSuccess(UpdatePlayerStatisticsResult result)
        {
            Debug.Log("success!");
        }

        void OnError(PlayFabError error)
        {
            Debug.Log($"{error.Error}");
        }
    }

※送信した統計情報がランキングに反映されるまで1~2秒かかる場合があります。
※ですので送信後すぐにランキングを取得するような設計は控えましょう。
こちらの記事で詳しく解説されています。

2.2. ランキングの取得

以下のようなコードでランキングを取得することができます。

    private void GetRanking()
    {
        var request = new GetLeaderboardRequest
        {
            StatisticName = "JumpCount", // 統計情報名を指定します。
            StartPosition = 0, // 何位以降のランキングを取得するか指定します。
            MaxResultsCount = 100 // ランキングデータを何件取得するか指定します。最大が100です。
        };

        PlayFabClientAPI.GetLeaderboard(request, OnSuccess, OnError);

        void OnSuccess(GetLeaderboardResult leaderboardResult)
        {
            // 実際は良い感じのランキングを表示するコードにします。
            foreach (var item in leaderboardResult.Leaderboard)
            {
                // Positionは順位です。0から始まるので+1して表示しています。
                Debug.Log($"{item.Position + 1}位: {item.DisplayName} - {item.StatValue}回");
            }
        }

        void OnError(PlayFabError error)
        {
            Debug.Log($"{error.Error}");
        }
    }

実行すると以下のような結果が得られます。
これを良い感じに UI に組み込むだけでランキングの完成です!
image.png

ちなみにランキングのデータは GameManager で確認することが可能です。便利ですね。
image.png

そういえば今回は1位からのランキングを取得/表示しましたが、実際は自分の+-5位のランキングを表示したかったりすると思います。

その場合は GetLeaderboard の代わりに GetLeaderboardAroundPlayer を使います。
コードは殆ど同じです。

    private void GetRanking()
    {
        var request = new GetLeaderboardAroundPlayerRequest
        {
            StatisticName = "JumpCount", // 統計情報名を指定します。
            MaxResultsCount = 11 // 自分と+-5位をあわせて合計11件を取得します。
        };

        PlayFabClientAPI.GetLeaderboardAroundPlayer(request, OnSuccess, OnError);

        void OnSuccess(GetLeaderboardAroundPlayerResult leaderboardResult)
        {
            // 実際は良い感じのランキングを表示するコードにします。
            foreach (var item in leaderboardResult.Leaderboard)
            {
                // Positionは順位です。0から始まるので+1して表示しています。
                Debug.Log($"{item.Position + 1}位: {item.DisplayName} - {item.StatValue}回");
            }
        }

        void OnError(PlayFabError error)
        {
            Debug.Log($"{error.Error}");
        }
    }

ゲーム内の実装の話はここまでです。
最後にランキング報酬を配ってみましょう。

3. ランキング報酬の配布

GameManager でランキングを開きます。
image.png

プライズテーブルを開いて、新しいプライズテーブルを作成します。
image.png

ランキング1~5位には魔法石10個、6~10位には魔法石5個を配る設定を作ってみました。
画面が直感的に操作できて素敵です。(スクショが長くてごめんなさい)
image.png
※アイテムは複数種類を一度に配布することも可能です。
※無料プランではランキング10位までしか報酬を配れないので注意してください。
※$99.99課金すると1000位まで配れるようになります。
※報酬を配る以外にも、ランキングに応じてメールを送信する、プッシュ通知を送る、自分で書いたスクリプトを実行するなどの処理が可能です。

JumpCount のランキング表示に戻って、今すぐリセットを押します。
イベントが終わったらポチッとリセットする感じの運用ですね。
image.png

確認画面が表示されるのでリセットしてください。
これでランキングがリセットされて、同時に報酬が配布されます。
image.png

先程1位だったNishiさんのインベントリを覗いてみると、ちゃんと魔法石が配布されていますね。
image.png

あとがき

ゲームにランキングを簡単に実装できると聞いて試してみましたが、想像以上に簡単で驚きました。
報酬の配布もとても便利で最高ではないでしょうか。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

UnityでARKit2 - 第四回 -

UnityでARアプリ開発をやってみたい 第四回

1. この記事でやること

BitBucketから拝借してきたunity-arkit-pluginのExampleにあるUnityARWorldMapをちゃんと読もうの回です。

2. UnityARWorldMapを理解したい

UnityARWorldMapはUnityARKitPluginに用意されているExampleのUnityプロジェクトです。
ここではUnityARWorldMapがどういうことをやっているのかを理解することを目的としています。
まずは構成要素からチェックしていきます。

Hierarchy

UniryARWorldMapのHierarchyは以下のようになっています。

Hierarchy

  • Directional Light
    • 通常の光源です
  • Random Cube
    • AR空間においておくCubeです
    • このCubeにはX,Y,Z方向がわかるようにコンポーネントがぶら下がっています
  • Camera Parent
    • Main Camera
      • GameView用のメインカメラです
      • なんで階層化しているのかわからない...
  • Hit Cube Parent
    • Hit Cube
      • AR空間に配置するCubeです
      • UnityARTestHitExample.csがあてられています
      • なんで階層化しているのかわからない...
  • Generate Planes
    • AR空間上で平面を認識するものです
    • UnityARGeneratePlane.csがあてられています
  • PointCloudParticleExample
    • AR空間で特徴点を表すために追加されているParticleです
    • ParticleのPrefabをつかっています
    • PointCloudParticleExample.csがあてられています
  • Canvas
    • Layout
      • Save button
      • Load button
        • 画面上に表示される補助ボタンです
        • OnClickイベントを割り当てたりすることができます
  • EventSystem
    • イベントドリブンでゲームを構成するためのコンポーネント、なにか画面に見えるわけではないです
  • WorldMapManager
    • WorldMapManager.csがあてられています
    • ARCameraManagerと連携してWorldMapを管理します
  • ARKitControl
    • ARセッションをコントロールしています
  • ARCameraManager
    • カメラマネージャーです、ARアプリの基盤的役割を果たします

Unity Scriptの読み方

Inspectorの設定値

ARCameraManagerを例に取ります

Componentとして追加されているスクリプトはUnityARCameraManager.csです。
UnityARCameraManager.csのようにファイル名を指定し、このファイル名と同じ名前のクラスを内部に定義するのがルールです。

Unityのinspectorビューで設定できる項目がいくつかありますが、これはこのクラスのPubilcなメンバが自動的にUIに反映されるようになっており、これらの設定値はUnity UIで与えるようになっています。

public class UnityARCameraManager : MonoBehaviour {

    public Camera m_camera;
    private UnityARSessionNativeInterface m_session;
    private Material savedClearMaterial;

    [Header("AR Config Options")]
    public UnityARAlignment startAlignment = UnityARAlignment.UnityARAlignmentGravity;
    public UnityARPlaneDetection planeDetection = UnityARPlaneDetection.Horizontal;
    public bool getPointCloud = true;
    public bool enableLightEstimation = true;
    public bool enableAutoFocus = true;
    public UnityAREnvironmentTexturing environmentTexturing = UnityAREnvironmentTexturing.UnityAREnvironmentTexturingNone;

    [Header("Image Tracking")]
    public ARReferenceImagesSet detectionImages = null;
    public int maximumNumberOfTrackedImages = 0;

    [Header("Object Tracking")]
    public ARReferenceObjectsSetAsset detectionObjects = null;
    private bool sessionStarted = false;

    // 以下略
}

publicのCamera m_cameraではCameraクラスのインスタンスを指定する必要があり、ここにMain Cameraを割り当てています。
Headerを指定すると、Inspectorビューでパラメーターのグループ名として表示されます。
publicのパラメータがenumの場合はInspectorではドロップダウンで表示されます。
例えばUnityARAlignmentはこのenumがUnityARSessionNativeInterface.csに定義されています。
デフォルトで値を入れておけばInspectorビューでの初期値となります。

StartとUpdate

各スクリプトにはStart()メソッドとUpdate()メソッドが用意されていることが多いです。
Startは最初に1度だけ実行され、Updateは毎フレームで実行されます。
フレームはゲーム画面を常に最新に保つためのクロックのようなものです。

UnityARCameraManagerの場合、Start()メソッド内でUnityARSessionNativeInterfaceのセッションを取得し、セッションを開始します。
UnityARSessionNativeInterfaceはUnityでARを取り扱う上でのベースとなるクラスで、このセッションとしてすべての処理を管理します。
Update()メソッドでは各フレームにおけるカメラの物理的なポジション情報をデバイスから取得し、メンバのm_cameraにセットする。これにより、カメラのいち情報を内部で保持することができます。(別の処理で参照するなど)

SetCameraは初期だと誰も使っていなさそうですね、外部からカメラを再割り当てする感じかな。

スクリプトを読んで全体像を理解する カメラ編

ARCameraManagerのCameraメンバとして設定されているMainCameraに割り当てられているスクリプトをチェックします。
- UnityARVideo

メンバとしてMaterialが割り当てられています。YUVMaterialが割り当てられます。
いろいろ書いてあってややこしい。これはiOSのカメラからの情報をUnityCameraに展開するスクリプトなので、理解は難しいです。
このカメラ映像がUnityCameraに割り当てられる際にじゃまにならないよう、Cameraの設定でClear Clear FlagsはDepth onlyにする必要があります。
- UnityARCameraNearFar

SetCameraNearFar(iOS側:外部IF)経由でUnityCameraのNearとFarを設定します。
これらの値は、3D空間にものを描画するときの手前側と奥側を設定するものです。イメージとしては、AR空間に置かれた物体にカメラを向けながらじりじりと近づいたとき、ある瞬間から画面に映らなくなるような処理に使います。

ここまでに出てきた
UnityARVideo, UnityARCameraNearFar, UnityARCameraManagerの3つのスクリプトはARアプリ制作における必須アイテムです。

スクリプトを読んで全体像を理解する

UnityARKitControl

次はUnityARKitControlについてスクリプトをチェックします。
UnityARKitControlにはpublicメンバがないので独立スクリプトです。
Start処理はシンプルで以下のパラメーターのセットを行います。

  • runOptions
  • alignmentOptions
  • planeOptions

このスクリプトでは主にOnGUIで処理が行われます。OnGUIは先のUpdateに似た事前に定義されたタイミングで呼び出されるメソッドです。
Updateは毎フレームごと、つまりユーザーのオペレーションがあろうがなかろうが、一定間隔で実行されます。一方で、OnGUIはイベントが発生するたびに呼び出されるメソッドです。ユーザーが操作したときなどのイベント発生毎に呼び出されます。

OnGUIでは主にARSessionのStopとStartがコントロールされています。

WorldMapManager

次はWorldMapManagerについてスクリプトをチェックします。
WorldMapManagerは先程のUnityARCameraManagerをメンバに持っています。

まずStartメソッドではARFrameUpdatedEventにイベントが登録されています。
これはその名の通りフレームごとに発生するイベントです。
登録されたイベントはOnFrameUpdateです。
OnFrameUpdateではちょっとしたログの登録しかされないので、ここは本体ではないです。
WorldMapManagerにはSave()とLoad()が用意されており、これらはCanvasのSave buttonとLoad buttonに割り当てられています。
そのためこれらのボタンがクリックされるとこのメソッドに入ります。
まずSaveメソッドでは、ARWorldMapをpathに保存します。ARWorldMapについてはARKit2.0のReadMeを見ると色々書いてあります。
WhatsNewInARKit2_0.mdを見てください。
このARWorldMapはARKit2.0で追加された、AR空間の共有を実現するために非常に重要な仕組みです。
SaveSerializedとLoadSerializedはSaveとLoadの別パターンで、ARWorldMapをシリアライズしてByte列で保存するという違いがある。

Canvas (Buttons)

Canvas中のSave ButtonとLoad ButtonはWorldMapManagerのSaveとLoadが割り当てられています。

Generate Planes

Generate PlanesにはUnityARGeneratePlane.csのスクリプトが割り当てられています。
- UnityARGeneratePlane

publicでGameObjectが割り当てられています。デバッグ用のplanePrefabです。
デバッグ用というのは、このPrefabを開くとわかるように、境界線付き平面だからです。
通常のアプリには不要な線が表示されているので、Debugです。

Start処理ではまずUnityARAnchorManagerのインスタンス生成をしています。UnityARAnchorManagerは平面のアンカー情報を保持するクラスで、イベントドリブンでアンカー情報を更新します。ARGeneratePlaneではこのクラスからアンカーを教えてもらって、以後の処理をします。

次にUnityARUtilityでplanePrefabを初期化します。これで、先のDebug用Prefabがセットされました。あとはARUtility側でイベント更新に合わせてPrefabが画面上に表示されます。

HitCubeParent/HitCube

HitCubeにはBoxColliderがセットされています。ColliderはUnity空間上での物理量同士の接触を発生させるためにセットするパラメーターです。
これがないと物体を物体が通り抜けるようになってしまいます。Meshも定義されているので視認可能な物体ということになります。

HitCubeには次のスクリプトが割り当てられています。
- UnityARHitTestExample.cs
- publicなメンバとして以下の3つが用意されています。
- Transform
- HitCubeParentがセットされています
- LayerMask
- float maxRayDistance
- Unity上でのデバッグ用なので無視してOK

このスクリプトではUpdate処理が主役です。Update処理では画面がタッチされたポジションを取得します。
このポジションを使って、HitTestWithResultTypeを呼び出し、UnityARSessionNativeInterfaceがうまいことやって、ヒット位置を検出し、m_HitTransformに位置と回転をセットします。これにより、Cubeが配置されます。

おしまい

これでUnityARWorldMapの全体像チェックはおしまいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む