- 投稿日:2019-07-11T22:10:06+09:00
Unity内のファイルやHierarchyの名前を一括で変更してくれるEz Rename.の紹介
はじめに
VCI(Virtual Cast Interactive)の作成時に、各GameObjectの名前やMaterial、Audioの名前の付け方を統一したりインクリメント形式で付けると、luaスクリプトで操作する際に取り回しがしやすい事が多いです。
ということで、今回はファイル名やHierarchyの名前を一括で変更することのできるEz Rename.というアセットの使い方を解説していきたいと思います。
こんなアセットです。
1. Ez Rename.のダウンロード・インポート
まず、Ez Rename.をダウンロード・インポートする必要があります。
UnityのAsset Store内でダウンロード・インポートを行ってください。
Unityのアセットストアの使い方については下記サイトを参考にしてください。
Unityのアセットストア(AssetStore)を使う方法【初心者向け】
下記動画Gifのように検索をかけると出てきますので、それのダウンロード・インポートボタンを押してImportしてください。
2. Ez Rename.のウィンドウの表示
Window
メニューからEz Rename
を選択して、Open
から、Ez Rename.のウィンドウを表示することができます。
こちらを使って名前の変更を行います。
3. Ez Rename.でできること。
使い方についてはこちらに載っています。英語ですが。
Ez Rename Guide
英語を読みたくない方向けに、ざっくりとした解説を記載します。Rename
・複数の名前の変更が一括でできます。
・赤い場所をクリックすると、現在選択しているGameObject
かAsset
の名前をコピーできます。
・Hierarchy
ボタンを押せば、選択しているHierarchy
のGameObject
の名前を変更します。
・Poject Folder
ボタンを押せば、選択しているProject
のファイルの名前を変更します。
・CMD + Z もしくは CTRL + Zで変更を取り消すことができます。
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で変更を取り消すことができます。
- 投稿日:2019-07-11T11:50:06+09:00
【VFX Graph】連番アニメーションを使ってみた
はじめに
Visual Effect Graphでスプライトシートを使った連番アニメーションを使ってみました。
環境
【Unityバージョン】
Unity2018.3.14f1【パッケージ】
Hight Definition RP - Version 4.1.0(Preview)
Visual Effect Graph - Version 4.10.0(Preview)【OS】
Windows 10Visual Effect Graph 完成図
今回作成したVisual Effect Graphは以下になります。
STEP0. スプライトシートの用意
今回のエフェクトでは、以下のテクスチャを使用しました。
Photoshopを使って手描きで作成しました。STEP1. UV Mode = Flipbook に設定
Output系ノードの
Uv Mode
をFlipbook
に設定し、スプライトシートのテクスチャとスプライトシート分割数を設定します。ただし、これだけではまだテクスチャは動きません。
STEP2. Flipbook Playerを追加
Updateノードに
Flipbook Player
ブロックを追加することで、アニメーションが動くようになります。
frameRateの部分にフレームレートを指定します。 今回は24を指定しました。
以上でエフェクトは完成です。
完成したエフェクト
炎が光っている感じはPost Processing StackのBloomを使って作っています。
- 投稿日:2019-07-11T08:45:53+09:00
[Unity] Destory処理中のOnDisableとOnDestroyの呼び出され方と、その最中にGameObjectの親子関係を解除したときの挙動
結論から
OnDisableやOnDestroyで親子関係を変えると意図しない挙動を引き起こしやすいので
Destroyする前に親子関係を解除した方が良い検証用GameObjectの構造とコード
DestroyTestDestroyTest : 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も呼ばれる
Editorの操作から削除した場合
Disableは孫→子→親の逆順で呼ばれ、Destroyはコード側の操作と同じ順序で呼ばれる
親のOnDestroyで親子関係を解除した場合
すべてのOnDisableが呼び出された後、親子関係が解除され親のOnDestroyのみ呼ばれる
この場合DestroyしたGameObjectの直下にある子のみdisableのままになり孫はEnableが呼ばれコンポーネントが起動する
コードにOnEnableを書き加え確認するとしっかり呼ばれているのを確認できる
Destroy処理の途中で親子関係を外す場合に期待する挙動としては確かに子はDisableされずEnableのままにしてほしいと思うので
中断できた場合は改めてEnableにするのだろうが
構造的に子か否かでその処理が走るかどうか決めていて親になった「子」には適用されないのだろう親のOnDisableで親子関係を解除した場合
子のOnDestroyで親を外した時
親を外す処理はDestory中には不可能で、エラーになりそのままDestroyされる
子のOnDisableで親を外した時
子でOnDisableの伝播が止まり孫はDisableされていないのでOnEnableも呼ばれない
子はDisableのままになる
Unityが用意しているコンポーネントは?
子がRootへ変化する状況では同じくDisableされる
Particle Systemなどは出てるパーティクルが一度すべて消える感想
あんまり無い状況かもしれませんが、Destory中に親子関係を解除するとコンポーネントがDisableのままというのは
結構罠だと思うので、事前に解除しておきましょう
- 投稿日:2019-07-11T02:19:18+09:00
AzurePlayFabのランキング機能を使ってみた&ついでにランキング報酬も配ってみた
まえがき
オンラインゲームにかかせないランキング機能、自分で作るのは少し面倒ですよね。
PlayFab にはユーザーのランキングを管理したり、ランキングに応じて報酬を配ったりできる機能があります。今回は以前作ったユニティちゃんの縄跳びゲームに PlayFab のランキング機能を組み込んでみましたが、簡単便利で素敵だったので記事に残しておこうと思います。
成果物
使用する PlayFab の API
- UpdateUserTitleDisplayName - ランキングなどに表示するユーザー名を登録します
- UpdatePlayerStatistics - ランキングの集計対象にするデータ(スコアなど)を登録します
- GetLeaderboard - ランキングを取得します(1位から10位のランキングを取得する場合などはこちら)
- GetLeaderboardAroundPlayer - ランキングを取得します(自分の前後のランキングを取得する場合などはこちら)
1. 事前準備
1.1. クライアントから PlayFab への統計情報のポストを許可しておく
PlayFab は統計情報(スコアなど)をクライアントから送信することをデフォルトでは禁止しています。
チート対策のために基本的にはサーバー側で処理してね、とのことですが今回は個人制作の趣味のゲームですし、クライアントからサクッと値を送信したいと思います。
そのために GameManager の設定画面で
クライアントにプレイヤー統計情報のポストを許可する
を有効にします。
これを忘れるとクライアントから統計情報を送信したときに下記のエラーがでるので注意してください。
1.2. ランキングの定義を作成しておく
統計情報名
わかりやすい名前ならなんでも大丈夫です。
一度決めると変更できないので慎重に。リセット頻度
今回は手動にしますが、毎時/毎日/毎週/毎月なども選べます。
ランキングリセットの際は自動で報酬を配布したりすることもできます。(後述)集計方法
今回はプレイヤーごとの最多ジャンプ成功数をランキング表示したいので最大
にしておきます。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 のプレイヤー一覧などにも自動的に表示されます。
地味に嬉しいですね!
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 に組み込むだけでランキングの完成です!
ちなみにランキングのデータは GameManager で確認することが可能です。便利ですね。
そういえば今回は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. ランキング報酬の配布
プライズテーブルを開いて、新しいプライズテーブルを作成します。
ランキング1~5位には魔法石10個、6~10位には魔法石5個を配る設定を作ってみました。
画面が直感的に操作できて素敵です。(スクショが長くてごめんなさい)
※アイテムは複数種類を一度に配布することも可能です。
※無料プランではランキング10位までしか報酬を配れないので注意してください。
※$99.99課金すると1000位まで配れるようになります。
※報酬を配る以外にも、ランキングに応じてメールを送信する、プッシュ通知を送る、自分で書いたスクリプトを実行するなどの処理が可能です。JumpCount のランキング表示に戻って、今すぐリセットを押します。
イベントが終わったらポチッとリセットする感じの運用ですね。
確認画面が表示されるのでリセットしてください。
これでランキングがリセットされて、同時に報酬が配布されます。
先程1位だったNishiさんのインベントリを覗いてみると、ちゃんと魔法石が配布されていますね。
あとがき
ゲームにランキングを簡単に実装できると聞いて試してみましたが、想像以上に簡単で驚きました。
報酬の配布もとても便利で最高ではないでしょうか。
- 投稿日:2019-07-11T02:19:18+09:00
AzurePlayFabのとても便利なランキング機能を使ってみた&ついでにランキング報酬も配ってみた
まえがき
オンラインゲームにかかせないランキング機能、自分で作るのは少し面倒ですよね。
PlayFab にはユーザーのランキングを管理したり、ランキングに応じて報酬を配ったりできる機能があります。試しに使ってみたところ、とても便利な機能だったので記事に残しておこうと思います。
成果物
使用する PlayFab の API
- UpdateUserTitleDisplayName - ランキングなどに表示するユーザー名を登録します
- UpdatePlayerStatistics - ランキングの集計対象にするデータ(スコアなど)を登録します
- GetLeaderboard - ランキングを取得します(1位から10位のランキングを取得する場合などはこちら)
- GetLeaderboardAroundPlayer - ランキングを取得します(自分の前後のランキングを取得する場合などはこちら)
1. 事前準備
1.1. クライアントから PlayFab への統計情報のポストを許可しておく
PlayFab は統計情報(スコアなど)をクライアントから送信することをデフォルトでは禁止しています。
チート対策のために基本的にはサーバー側で処理してね、とのことですが今回は個人制作の趣味のゲームですし、クライアントからサクッと値を送信したいと思います。
そのために GameManager の設定画面で
クライアントにプレイヤー統計情報のポストを許可する
を有効にします。
これを忘れるとクライアントから統計情報を送信したときに下記のエラーがでるので注意してください。
1.2. ランキングの定義を作成しておく
統計情報名
わかりやすい名前ならなんでも大丈夫です。
一度決めると変更できないので慎重に。リセット頻度
今回は手動にしますが、毎時/毎日/毎週/毎月なども選べます。
ランキングリセットの際は自動で報酬を配布したりすることもできます。(後述)集計方法
今回はプレイヤーごとの最多ジャンプ成功数をランキング表示したいので最大
にしておきます。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 のプレイヤー一覧などにも自動的に表示されます。
地味に嬉しいですね!
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 に組み込むだけでランキングの完成です!
ちなみにランキングのデータは GameManager で確認することが可能です。便利ですね。
そういえば今回は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. ランキング報酬の配布
プライズテーブルを開いて、新しいプライズテーブルを作成します。
ランキング1~5位には魔法石10個、6~10位には魔法石5個を配る設定を作ってみました。
画面が直感的に操作できて素敵です。(スクショが長くてごめんなさい)
※アイテムは複数種類を一度に配布することも可能です。
※無料プランではランキング10位までしか報酬を配れないので注意してください。
※$99.99課金すると1000位まで配れるようになります。
※報酬を配る以外にも、ランキングに応じてメールを送信する、プッシュ通知を送る、自分で書いたスクリプトを実行するなどの処理が可能です。JumpCount のランキング表示に戻って、今すぐリセットを押します。
イベントが終わったらポチッとリセットする感じの運用ですね。
確認画面が表示されるのでリセットしてください。
これでランキングがリセットされて、同時に報酬が配布されます。
先程1位だったNishiさんのインベントリを覗いてみると、ちゃんと魔法石が配布されていますね。
あとがき
ゲームにランキングを簡単に実装できると聞いて試してみましたが、想像以上に簡単で驚きました。
報酬の配布もとても便利で最高ではないでしょうか。
- 投稿日:2019-07-11T00:39:06+09:00
UnityでARKit2 - 第四回 -
UnityでARアプリ開発をやってみたい 第四回
- 第一回: UnityでARKit2
- 第二回: UnityでARKit2 第二回
- 第三回: UnityでARKit2 第三回
- 第四回: UnityでARKit2 第四回 --> この記事
1. この記事でやること
BitBucketから拝借してきたunity-arkit-pluginのExampleにあるUnityARWorldMapをちゃんと読もうの回です。
2. UnityARWorldMapを理解したい
UnityARWorldMapはUnityARKitPluginに用意されているExampleのUnityプロジェクトです。
ここではUnityARWorldMapがどういうことをやっているのかを理解することを目的としています。
まずは構成要素からチェックしていきます。Hierarchy
UniryARWorldMapの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の全体像チェックはおしまいです。