平面の上にポータルをインスタンス化する

Tutorial

Beginner

+10XP

60 mins

Unity Technologies

平面の上にポータルをインスタンス化する

このポータルのために、多くの設定作業を行ってきました。具体的には、ポータルのテーマを選択し、平面の検出を設定し、ユーザーがタッチした位置を検出し、シーンへのレイキャストを使用して有効な平面がタッチされたかどうかを特定しました。このチュートリアルでは、環境内の選択された平面上に、ポータルのゲームオブジェクトを実際にスポーン(またはインスタンス化)します。

Languages available:

1. 概要

このポータルのために、多くの設定作業を行ってきました。具体的には、ポータルのテーマを選択し、平面の検出を設定し、ユーザーがタッチした位置を検出し、シーンへのレイキャストを使用して有効な平面がタッチされたかどうかを特定しました。ここでは、環境内で選択された平面上にポータルのゲームオブジェクトを実際にスポーン(またはインスタンス化)します。

このチュートリアルを完了すると、プロジェクトは以下のビデオデモのようになります。

このポータルをシーンにスポーンする上で最もやっかいなのは、それらのうち 1 つだけをスポーンするという点です。新しい If ノードを使用して、何百ものポータルを一度に誤ってスポーンしないようにする必要があります。

それでは始めましょう!

2. オブジェクトをインスタンス化する方法

シーンに新しいオブジェクト(ゲームオブジェクト)をスポーンする場合、それは「インスタンス化」と呼ばれることがよくあります。オブジェクトの新しいインスタンス(バージョン)を作成するためです。今回は、ポータルプレハブの新しいインスタンスを作成します。

このオブジェクトをインスタンス化するときには、以下の入力を定義する必要があります。

  • Original として使用するプレハブ
  • 新しいインスタンスの Position
  • 新しいインスタンスの Rotation

これらの入力についてそれぞれ詳しく見ていきましょう。

Original

Original 入力には、インスタンス化したいプレハブを選択します。アプリケーションで机や床の水平な平面を検出する場合は、上からのぞき込むことができる水平なポータルを選択します。アプリケーションで壁やドアの垂直な平面を検出する場合は、窓のようにのぞき込むことができる垂直なポータルを選択します。

ポータルは _ARPortal > Prefabs > Portals にあります。3 つすべての環境に対して水平と垂直のオプションが用意されています。

Position

目標は、ポータルを平面と同じ位置に配置することです。平面の位置を取得するために、Find Object Of Type ノードと Transform: Get Position ノードを使用します。その後、ポータルのゲームオブジェクトをインスタンス化するときにその同じ位置を使用できます。

Rotation

ポータルの回転も、平面の回転と一致している必要があります。Transform: Get Position ノードを使用して平面の位置を取得したのと同じように、Transform: Get Rotation ノードを使用して平面の回転を取得します。

3. ポータルをインスタンス化する

このポータルをインスタンス化する方法について理解できたので、ビデオを視聴するか、以下の手順に従って、ビジュアルスクリプトを更新しましょう。

1. 「Script Graph」ウィンドウで TapToPlace スクリプトグラフが開いた状態になっていることを確認します。

2. グラフエディターで、On Update シーケンスの末尾に、新しい Game Object: Find Object of Type (Type) ノードを追加します。Type 入力を「AR Plane」に設定します。

3. 新しい Game Object: Instantiate ノードを追加して、シーケンスの末尾に結び付けます。必ず、次の 3 つの入力を持つ Instantiate ノードを選択してください:Original、Position、Rotation。

4. Original 入力には、オブジェクトピッカー(丸)を使用して水平または垂直なポータルプレハブを選択します。

5. Position 入力に対しては、Transform: Get Position ノードを作成します。Find Object of Type ノードの出力を新しい Get Position ノードにアタッチし、次にそれを Instantiate ノードの Position 入力に結び付けます。

6. Rotation 入力に対しては、Transform: Get Rotation ノードを作成します。Find Object of Type ノードの出力を新しい Get Rotation ノードにアタッチし、次にそれを Instantiate ノードの Rotation 入力に結び付けます。

7. アプリケーションをビルドして実行し、新しい機能をプレビューします。有効な平面をタッチすると、平面の中央にポータルがスポーンするはずです。

垂直な平面に関するトラブルシューティング

重要:垂直な平面とポータルを使用している場合は、(以下のように)ポータルが壁に張りつく形ではなく、下向きに回転してスポーンすることに気づかれるでしょう。

ご安心ください。次のステップで修正します。

4. 垂直なポータルの回転を修正する

垂直なポータルを使用している場合は、このステップを完了してポータルのスポーンの回転を修正してください。水平なポータルを使用している場合は、このステップを完了する必要はありませんが、平面上のオブジェクトの向きを設定する方法について深く理解するために、ひととおり読んでおくことをお勧めします。

垂直なポータルを作成しようとすると、ポータルが下向きにスポーンすることに気づきます。

問題は、垂直な平面が床から見て 90 度回転しているという点にあります。ポータルの回転を平面と一致するように設定すると、ポータルも床から見て 90 度回転することになります。

これを可視化するために、垂直なポータルが水平な平面上にスポーンする様子を以下の画像に示します。

しかし、この平面を 90 度回転して、垂直な壁の位置に置くとどうなるかをご覧ください。ポータルは下向きに回転します。

この下向きの回転を修正するには、ポータルウィンドウを逆向きに回転させて平らに置き、垂直な平面上にスポーンしたときにはポータルも垂直になるようにする必要があります。

以下の手順に従って、垂直なポータルを回転させ、垂直な平面に張りつくようにスポーンさせます。

1. Project ウィンドウから _ARPortal > Prefabs > Portals に移動し、使用しているポータルをダブルクリックして、シーンビューでプレハブを開きます。

2. 「Hierarchy」で Window ゲームオブジェクトを選択し、シーンビューで 90 度回転させて上を向くようにします。ウィンドウの外面がシーンギズモの緑の Y 軸アームの方向を向き、ウィンドウの上部が青い Z 軸アームの方向を向くようにする必要があります。

重要Window の親ゲームオブジェクトではなく、子ゲームオブジェクトを回転させる必要があります。最上位の親ゲームオブジェクトを回転させても、インスタンス化するとリセットされます。そのため、この親ゲームオブジェクトの回転を編集しても、オーバーライドされてしまいます。

3. アプリケーションをビルドして実行し、新しい機能をプレビューします。垂直なポータルをインスタンス化すると、垂直な平面に張りつくように、正しい向きで表示されるはずです。

5. アクションが 1 回しか実行されないように制限する方法

前のステップでは、平面上に 1 つのポータルをスポーンしただけだと思われたかもしれません。しかし実際には、何百ものポータルをスポーンしていた可能性があります!

以下のビデオのデバッグ UI は、シーン内の現在のオブジェクトの数を表示しています。ご覧のように、ユーザーの指が画面に触れている間、ポータルは生成され続けます。

複数のポータルがスポーンされることは、現段階では大きな問題に見えないかもしれません。しかし、ポータル内にシーン全体をスポーンさせる段階になると、複数のポータルをインスタンス化することでアプリケーションの速度が大幅に低下するおそれがあります。

1 つのポータルをスポーンするプロセス

ノードシーケンスを複数回実行できないようにすることで、多数のポータルがスポーンされるのを防ぐことができます。以下のロジックを使用して、Boolean を使用してシーケンスを実行する回数を制限できます。

  1. Boolean 変数を作成し、デフォルトで false に設定します。
  2. ノードシーケンスの末尾で、その Boolean を true に設定します。
  3. Boolean が false の場合にのみシーケンスを実行します。

以下の図は、この Boolean のロジックを可視化したものです。

ノート:スポーンされたオブジェクトの数をご自身のアプリケーションのデバッグ UI に表示したい場合は、以下のビジュアルスクリプトを確認してください。これは完全に任意です。

6. Boolean 値を設定する

前のステップで学習したように、この Boolean ロジックの設定は 3 段階のプロセスになります。ステージ 1 とステージ 2 を以下に示します。

ステージ 1:Boolean 変数を作成し、false に設定する

以下の手順に従って、新しい Boolean 変数を設定します。

1. 「Script Graph」ウィンドウで TapToPlace スクリプトが開かれていることを確認します。

2. 「Blackboard」の「Object」タブで、「portalSpawned」という名前の新しい変数を追加し、その「Type」を「Boolean」に設定します。

3. チェックボックスはオフのままにしてください。これは、デフォルトで false であることを意味します。

ステージ 2:シーケンスの末尾で Boolean を false に設定する

ビデオを視聴するか、以下の指示に従って、Boolean 値を false に設定します。

1. Instantiate」ノードの後に、「Set Object Variable」ノードを結び付けます。変数の「Name」を「portalSpawned」に設定します。

2. New Value 入力ノードを新しい Boolean Literal ノードに結び付けます。

3. Boolean ノードのチェックボックスをオンにして、新しい値を true に設定します。

7. If ノードを使用してシーケンスを 1 回だけ実行する

これで、最初のインスタンス化シーケンスを実行した後に、portalSpawned の Boolean は true に設定されます。このプロセスの最終段階は、portalSpawned の Boolean が true の場合にシーケンスを再び実行しないようにすることです。このロジックを実装するには、If ノードを使用します。

If ノードには、Boolean の Condition 入力と、True 出力および False 出力が備わっています。これにより、Boolean を結び付けて、その Boolean が true の場合はあるシーケンスを開始し、その Boolean が false の場合は別のシーケンスを開始することができます。

ビデオを視聴するか、以下の指示に従って、スクリプトの開始時に portalSpawned の Boolean が false かどうかを確認しましょう。

1. On Update シーケンスの冒頭で、On Update ノードの直後に新しい If ノードを追加します。

2. If ノードの Condition 入力を、Get portalSpawned 変数ノードに結び付けます。これは、「Blackboard」から変数をドラッグする代わりの方法です。

3. If ノードの False 出力フローを、シーケンスの残りの部分に結び付けます。これで、シーケンスの残りの部分は、portalSpawned が false の場合にのみ実行されます。

新しい Boolean 制御をテストする

シーン内には 1 つのポータルしかスポーンできなくなっているはずです。それをテストするために、最初に表示された平面の上にポータルをスポーンしてから、2 番目に表示された平面の上に 2 番目のポータルをスポーンしてみてください。2 番目のポータルをスポーンできなくなっているはずです。

ビジュアルスクリプティングスキルを試す任意の課題として、上の例のように、デバッグ UI を使用して現在の Boolean 値を表示してみることもできます。

8. ポータルをスポーンした後にすべての平面を無効にする

有効なポータルを表示した後は、アプリケーションで既存の AR 平面をすべて削除し、新しい AR 平面を表示しないようにする必要があります。ユーザーの注目は、注意をそらす機能しない半透明の平面ではなく、シーン内の 1 つのポータルだけに向けられる必要があります。

便利なことに、AR Plane Manager には以下の 2 つのノードが含まれています。

  • AR Plane Manager: Set Trackables Active:これを使用して、既存の平面をすべて無効にすることができます。
  • AR Plane Manager: Set Enabled:これを使用して AR Plane Manager 全体を無効にし、新しい平面の生成を防ぐことができます。

これらのノードを使用するには、新しい AR Plane Manager 変数を作成する必要もあります。

ビデオを視聴するか、以下の指示に従って、既存の平面と新しく検出される平面をすべて無効にしましょう。

1. 「Blackboard」の「Object」タブで、「arPlaneManager」という名前の新しい変数を作成し、その「Type」を「AR Plane Manager」に設定します。オブジェクトピッカー(丸)を使用して、AR Session Origin ゲームオブジェクトを選択します。

2. シーケンスの末尾に、新しい AR Plane Manager: Set Trackables Active ノードを追加します。新しいノードの「Active」チェックボックスがオフになっていることを確認してください。これにより、トラッカブル平面が無効になります。

3. シーケンスの末尾に、AR Plane Manager: Set Enabled ノードを追加します。このノードのチェックボックスがオフになっていることを確認してください。これにより、Plane Manager が無効になります。

4. 新しいノード両方の AR Plane Manager 入力を、arPlaneManager Object 変数に結び付けます。

5. アプリケーションをビルドして実行し、新しい機能をプレビューします。ポータルがスポーンされると、すべての平面が消え、新しい平面は検出されなくなるはずです。

6. アプリケーションが期待どおり動作していることを確認したら、このタイミングで Debug Canvas ゲームオブジェクトを無効にし、Debug UI ノードに関連するすべてのノードを切り離しましょう。

9. 他にもトライしてほしいこと

さらなるスキルの向上や、新しいコンセプトの模索、現プロジェクトについての改善などを考えているのであれば、以下の任意のアクティビティもぜひ見るようにしてみてください。それぞれ「初級」、「中級」、「上級」のタグが付いているので、難易度を選択できます。

これらのアクティビティは完全に任意であるため、興味がなければこのステップをスキップしてもかまいません。

ただ、今回の学習体験を最大限に生かすためにも、このアクティビティのうち少なくとも 1 つは試してみることをお勧めします。頑張ってください!

初級:ポータルがスポーンされるときにパーティクルエフェクトを追加する

ポータルをスポーンさせるのは、とても不思議で魔法のような体験です。スポーンのアクションに伴って何かジュアルエフェクト(VFX)が発生すれば、ユーザーにとってさらにエキサイティングな体験となるでしょう。以下のガイダンスを使用するとこの課題の完了に役立ちます。

  • 独自のパーティクルエフェクトを作成するか、アセットストアからダウンロードすることができます。
  • ポータルに使用したのと同じインスタンス化手法を使用してパーティクルシステムをインスタンス化できます。または、ポータルウィンドウ自体の子オブジェクトとしてパーティクルシステムをアタッチすることもできます。

さらにガイダンスが必要な場合は、「Creative Core:VFX」で VFX の詳細を学んでください。

中級:ポータルがスポーンされるときにサウンドを追加する

スポーンイベントに伴ってサウンドが発生すれば、ユーザーにとってさらに満足感のあるはっきりした体験となるでしょう。ポータルをスポーンするシーケンスにサウンドを追加してみましょう。以下のガイダンスを使用するとこの課題の完了に役立ちます。

  • シーンに新しい Audio Source ゲームオブジェクトを作成し、その「Audio Clip」プロパティにサウンドエフェクトを割り当てます。
  • Audio Source: Play ノードを追加して、ポータルをスポーンするときにサウンドを再生します。

さらにガイダンスが必要な場合は、「Creative Core:オーディオ」でオーディオの詳細を学んでください。

上級:一度に 1 つの平面のみを許可する

環境内で検出される平面が数多くあると、ユーザーは少し圧倒されてしまうかもしれません。代わりに、検出された 1 つの平面だけが一度にシーンに存在できるようにすれば、ユーザー体験が改善されるかもしれません。以下のガイダンスを使用するとこの課題の完了に役立ちます。

  • 「LimitPlanes」という名前の新しいスクリプトマシンを作成して、その機能を制御します。このような追加の機能は、メインスクリプトとは別に管理すると便利です。
  • Count Items ノードと Game Objects: Find Objects of Type ノードを使用して、現在の AR Plane 型のゲームオブジェクト数を取得します。
  • Greater or Equal ノードと If ノードを使用して、シーン内に 1 つ以上の AR 平面が存在するかどうかを確認します。
  • シーン内に 1 つ以上の平面が存在する場合は、AR Plane Manager を無効にします。
  • Null Check ノードを使用して、AR Plane Manager が存在する場合にのみこのシーケンスを実行します。

ノート:現在の平面の数を表示するデバッグ UI は、デモのために設定されたものです。この課題では要求されていません。

10. 次のステップ

このチュートリアルでは、環境内で検出された平面上に 1 つのポータルをインスタンス化する処理を制御できました。次のチュートリアルでは、ポータルウィンドウの背後に 1 つのシーン全体をデザインし、モバイルでのパフォーマンス用に最適化します。

Complete this Tutorial