Maps SDK for Unity の基本概念

ここでは、Maps SDK for Unity を理解し、適切に使用するために必要な基本概念を説明します。

MapsService クラスとコンポーネント

MapsService クラスは、Maps SDK for Unity を操作するためのエントリ ポイントとなります。このクラスは ApiKey をカプセル化し、GameObjectManagerLoadMap 関数、および EventsGameObject 作成パイプラインから公開します。

Unity プロジェクトで Maps SDK for Unity を使用するには、Map Service (Script) コンポーネントをシーンの空の GameObject に追加します。生成された地図対象物 GameObject が、このアンカー GameObject の子として自動的に追加されます。Maps Service (Script) を基本 GameObject に追加すると、以下に示すように、Unity Inspector の公開属性にアクセスできます。

Maps Service (Script)

Unity GameObject としての地理的対象物

Maps SDK for Unity は、Google マップ データベースから地理的対象物(建物、道路、水域など)を取得し、Unity GameObject としてゲーム内にレンダリングします。ランタイム時に、これらの対象物は、MapsService コンポーネントが追加されている GameObject の子として作成され、「{MapFeatureType} ({PlaceID})」という形式で名前が付けられます。

SDK ゲーム オブジェクト

GameObject の作成

ゲームプレー中、Maps SDK for Unity は、(Semantic Tile API を使用し)セマンティック ベクタータイルとして、Google マップ データベースから地理データを取得します。このデータをその場でデコードし、すぐに Unity GameObject に変換します。この方法では、地図対象物データ(メタデータとジオメトリ データの両方)への早期のアクセスが可能なので、パイプラインの最後に到達する前に GameObject をカスタマイズできます。

ベクタータイル データを受け取った Maps SDK for Unity は、まず、そこから MapFeature オブジェクトを構築します。

パイプラインの中間ステージで、MapFeature オブジェクトが特殊化され、特定のタイプ(たとえば、Google.Maps.Feature.ModeledStructure)になります。特定のタイプになった MapFeature オブジェクトに MapFeatureShape ジオメトリの詳細(ModeledStructure の場合 ModeledVolume)が含まれます。これらの詳細には、MapFeature 固有のデータ(頂点や三角形など)と、共通フィールドにアクセスするための共有インターフェース(境界ボックスなど)が含まれます。

ジオメトリ データは Unity メッシュに変換され、MeshFilter を介して GameObject に追加され、MeshRendererMeshRenderer で表示されます。

パイプラインへのアクセス

MapFeature は、パイプラインのさまざまなステージでトリガーされるイベントを介して公開されます。たとえば、GameObject が作成される直前に WillCreate イベントを呼び出し、スタイルを設定したり、作成をキャンセルしたりできます。また、GameObject が作成された後に DidCreate イベントを呼び出し、完成したメッシュに追加や変更を加えることができます。

たとえば、WillCreateExtrudedStructureEvent の呼び出し後に ExtrudedStructures を調べ、高さ 20 m 未満の建物をすべて非表示にする(またはまったく作成しない)こともできます。

イベントの種類

Google.Maps.Event 名前空間には、地理的対象物のタイプごとのイベントクラスが含まれています。

これらの種類のイベントには、サブスクライブ可能な公開メンバー イベント オブジェクト WillCreateDidCreate が含まれています。次のサンプルコードを参照してください。

dynamicMapsService.MapsService.Events.ExtrudedStructureEvents.DidCreate.AddListener(args => {

    // Apply nine-sliced walls and roof materials to this building.
    buildingTexturer.AssignNineSlicedMaterials(args.GameObject);

    // Add a border around the building base using the Building Border Builder class,
    // coloring it using the given border Material.
    Extruder.AddBuildingBorder(args.GameObject, args.MapFeature.Shape, BuildingAndRoadBorder);
});

WillCreate イベント

WillCreate イベントは、MapFeature が作成された直後、GameObject がそこから生成される前に呼び出されます。WillCreate イベントを使用して、MapFeature から作成された GameObject を中止したり、カスタマイズしたりできます。WillCreate イベントの引数の形式は次のとおりです。

using System.ComponentModel;
using Google.Maps.Decoded;
using UnityEngine;

namespace Google.Maps {
  public class WillCreateGameObjectEventArgs<T, U>
      : CancelEventArgs where T : IMapObject, U : IGameObjectStyle {

    public readonly T MapObject;
    public U Style;
    public GameObject Prefab;

    Public WillCreateGameObjectEventArgs(T mapObject, U defaultStyle, GameObject prefab) {
      MapObject = mapObject;
      Style = defaultStyle;
      Prefab = prefab;
    }
  }
}
  • CancelCancelEventArgs から継承)を true に設定すると、GameObject の作成が中止されます。
  • MapObject は読み取り専用です。
  • Style を設定すると、作成した GameObject の外観をカスタマイズできます。
  • Prefab を設定すると、生成されるはずだった GameObject がプレハブに置き換えられます。

DidCreate イベント

DidCreate イベントは、GameObject が作成され、シーンに追加された後で呼び出されます。GameObject の作成に成功すると通知が届き、処理を続行できるようになります。DidCreate イベントの引数の形式は次のとおりです。

using System.ComponentModel;
using Google.Maps.Decoded;
using UnityEngine;

namespace Google.Maps {
  public class DidCreateGameObjectEventArgs<T, U>
      : EventArgs where T : IMapObject, U : IGameObjectStyle {

    public readonly T MapObject;
    public GameObject CreatedObject;

    Public DidCreateGameObjectEventArgs(T mapObject, GameObject createdObject) {
      MapObject = mapObject;
      CreatedObject = createdObject;
    }
  }
}
  • MapObject は読み込み専用です。変更してもシーンは変わりません。
  • CreatedObject を変更すると、シーンに追加された GameObject は変更されます。

建物

建物には、押し出し成形された建造物とモデル化された建造物の 2 種類があります。

押し出し成形された建造物

押し出し成形された建造物は、枠線(2D フットプリント)と高さに基づいて生成されます。Maps SDK for Unity は、この方法でほとんどの建物を表現し、次の 3 つの方法で生成します。

  • 現実世界の高さデータを使用します(この情報が入手可能な場合)。これはデフォルトの設定です。

  • すべての建物に固定された高さを指定し、実際の高さを無視します。

  • 現実世界の高さがわからないすべての建物にバックアップの高さを指定します。デフォルト値は 10 m です。

これらの 3 つの方法を組み合わせることで、建物の高さがさまざまな(現実世界の高さを反映した)都市景観、または建物の高さが一定の都市景観、またはそれらを組み合わせた都市景観を作成できます。

モデル化された建造物

モデル化された建造物は、モザイク化された三角形の標準 3D モデリング手法を使用して生成されます。この手法は、自由の女神像などのランドマーク的な建物でよく使用されます。

モデル化された自由の女神

マテリアルの適用

Unity では、レンダリング プロセスにシェーダーマテリアルテクスチャを使用して GameObject にリアリティを持たせます。シェーダーは、特定のテクスチャ、色、使用するその他の設定が保存されたマテリアルに基づいて、表示されるジオメトリへのテクスチャ、色、照明などの適用方法を定義します。使用するテクスチャ、タイリング情報、色への参照を含めることで、マテリアルを使ってサーフェイスのレンダリング方法を定義します。

シェーダーは、照明入力とマテリアル設定に基づいて各ピクセルの色を計算するロジックを含む小さなスクリプトです。Maps SDK for Unity には、モデル化された建造物用の標準シェーダーと基本地図対象物用のシェーダーが用意されていますが、高度なマテリアル アプリケーションにも対応しています。地図対象物 GameObject の UV マッピングの座標は、どの基本マテリアルでも適用でき、修正を加えなくても問題ない程度に計算されます。

さらに高度なマテリアル エフェクトの場合、Map SDK for Unity では追加の UV チャネルを介した頂点ごとの追加データと、GoogleMapsShaderLib ライブラリを介した CG シェーダーに便利な多くの関数が提供されます。 これにより、建物のテクスチャの 9 スライス(テクスチャを建物の屋根、土台、壁の角、タイル状の壁にカット)などが可能になります。

詳しくは、Unity ユーザー マニュアルのマテリアルの作成と使用をご覧ください。

UV チャネル

MapFeature 型ごとの UV チャネルには、次の形式のデータが含まれます。

ExtrudedStructure

ExtrudedStructure 上の各壁は、次の形式のクワッドとして構築されます。

壁

壁の UV 座標はクワッドごとに計算されます。頂点はクワッド間で共有されません。これにより、壁間の角張った垂直線が可能になります(つまり、壁の角が柔らかい丸ではなく角張って表示されます)。

チャネル 0: (x, y, 幅, 高さ)
xy は、壁のこのクワッド(正方形断面)の左下隅と相対する座標です。一方、高さは、壁のこのクワッドの幅と高さです。これは、壁を構成するすべてのクワッドに適用されます。
屋根

屋根のテクスチャは、座標軸に平行か、ExtrudedStructure の方向に並行かの選択があります。これは、ExtrudedStructureStyle オブジェクトで設定します。

チャネル 0: (x, y, 幅, 高さ)
xy は、屋根の左下隅と相対する各頂点の座標です。具体的には、屋根の座標軸に平行な最小境界ボックスの角です。 高さは、屋根の境界ボックスのサイズを定義します。

Region

チャネル 0: (x, y, 幅, 高さ)
xy は、領域の座標軸に平行な境界ボックスの左下隅に相対する座標です。高さは、境界ボックスのサイズを定義します。

Segment

チャンネル 0: (x, y, 幅, 長さ)
xy は、セグメントがまっすぐになるように計算された各頂点の座標です。これにより、テクスチャを角に沿って折り曲げることができます。長さは、セグメントのサイズを定義します。

ModeledStructure

チャネル 0:
現時点でテクスチャ座標の実装がないため、各座標は(0, 0, 0, 0)に設定されます。

GoogleMapsShaderLib

Map SDK for Unity には、GoogleMapsShaderLib というシェーダー ライブラリが含まれており、これにより MapFeature GameObject に適したシェーダーを作成できます。このライブラリは、GoogleMapsShaderLib.cginc ファイルに実装されています。このライブラリを使用するには、次の #include ディレクティブをシェーダー スクリプトの CGPROGRAM フラグ セクションに含めます。

CGPROGRAM
// ...
#include "/Assets/GoogleMaps/Materials/GoogleMapsShaderLib.cginc"
// ...
ENDCG

シェーダー ライブラリは、GoogleMaps.unitypackage 内にバンドルされています。このパッケージをインポートすると、プロジェクト フォルダ /Assets/GoogleMaps/Materials/ 内に GoogleMapsShaderLib.cginc が格納されます。

9 スライス

GoogleMapsShaderLib には、テクスチャの 9 スライスを提供するためにフラグメント シェーダーで使用できる便利な関数が含まれています。9 スライスは、サーフェイスをテクスチャで覆う技術です。テクスチャは一連の境界を使用して 9 つの部分に分割されます。境界の間のエリアはタイル状になり、境界外のエリアは次の図のように固定されます。

9 スライス

たとえば、9 スライスされたテクスチャを建物の壁に適用すると、テクスチャの上部が壁の最上部(屋根のすぐ下)に、テクスチャの下部が壁の下部(土台に接続)に、テクスチャの辺が壁の縁に適用され、テクスチャの中央のエリアが壁全体で均等にタイル状になります。

別の例として、道路では、9 スライスによって歩道の幅を固定しつつ、道路の幅に応じて車線数を変更できます。

9 スライスを使用するには、GoogleMapsShaderLib.cginc をシェーダーに追加し、nineSlice 関数を呼び出します。サンプル シェーダーとマテリアルは GoogleMaps.unitypackage に含まれ、nineSlice 関数を使用して、可変サイズの現実的なスカイスクレイパーを作成する(引き延ばしたり引き剥がしたりしない)方法を示しています。

マテリアルの場所の例
/Assets/GoogleMaps/Examples/04_Advanced/MoreStyling/Materials/NineSlicing
シェーダーの場所の例
/Assets/GoogleMaps/Examples/04_Advanced/MoreStyling/Materials/NineSlicing/BuildingWall.shader

9 スライスはどの MapFeature でも使用できますが、ModeledStructures は現在テクスチャ座標がないため使用できません。

座標系

Maps SDK for Unity 座標系では、ウェブ メルカトル図法を使用して、球面 WGS 84 の緯度経度とデカルト座標 Unity ワールド空間(Vector3)間を変換します。

Vector3 の値はフローティング起点に対応した値で、通常はユーザーの開始位置に設定されます。そのため、セッションの外(つまりサーバー上やユーザーのデバイス上)では、Vector3 の値を保持しないでください。物理的な世界の場所を指定する際は、緯度と経度のペアを使用することをおすすめします。

浮動小数点の安定性の問題を避けるため、フローティング起点が使用されます。Unity の Vector3 クラスでは、単精度浮動小数点数を使用しますが、浮動小数点数が大きくなるほど表現できる精度は低くなります。ユーザーが離れた場所へ移動し、処理に問題が生じるようなときは、フローティング起点を更新できます。更新する頻度に応じて、比較的小さい値(100 m や 200 m など)または大きい値(1 km 以上)を設定できます。

Unity ワールド空間は、最初の起点の緯度に基づいて 1:1(メートル)にスケーリングされます。メルカトル図法では、スケールは緯度によって若干異なるため、Unity ワールド空間のスケールはユーザーが南北に移動すると 1:1 から少しずつ外れていきます。ただし、それに気付くほどユーザーが遠く(または速く)動くとは考えられません。

Maps SDK for Unity には、Google.Maps.LatLng と Unity Worldspace(Vector3)間を変換する変換関数(フローティング起点とスケールを考慮)が含まれています。

読み込みエラー

地図データをネットワークから読み込む際に発生するエラーは、MapLoadErrorEvent イベントで処理されます。イベント ハンドラを追加しなくても、ほとんどのタイプのエラーが Maps SDK for Unity で処理されます。ただし、アプリでの処理が必要となるエラーもあります。これは MapLoadErrorArgs.DetailedErrorCode で指定されます。下記の説明をご覧ください。

UnsupportedClientVersion

このバージョンの Maps SDK for Unity は、現在の API キーとの組み合わせではサポートされていない可能性があります。通常、ユーザーは新しいバージョンのアプリに更新するよう促されます。

通常、このエラーは、Maps SDK for Unity バージョンが古すぎるために発生します。まれに、Maps SDK for Unity のバージョンや API キーで重大な問題が発生した場合に、このエラーが使用されるケースがあります。Google は、アプリの有効バージョンが更新されるまでこのようなエラーが発生しないよう努めます。

このエラーが発生した場合には、アプリに適切なアップグレード パスを持たせることをおすすめします。これにより、ユーザーは、サポートされている SDK バージョンで新しいバージョンのアプリに移行できます。詳しくは、クライアント強制スイッチのドキュメントをご覧ください。

既知の問題

基本地図の対象物はすべて同じ平面にレンダリングされるため、Z 検定なしでは前後逆にレンダリングされます。基本地図に適用さる交換マテリアルで Z 検定を ZTest Always に設定して、対象物が正しくレンダリングされるようにする必要があります。

Google では、GoogleMaps.unitypackage に、これらの問題に対処するサンプル シェーダーを含めました。これは "BaseMapTextured.shader と呼ばれ、/Assets/GoogleMaps/Materials/ フォルダにあります。マテリアルで使用するには、マテリアル インスペクターのシェーダー プルダウンから [Google] > [Maps] > [Shaders] > [BaseMap Textured] を選択します。

Feature.Region または Feature.AreaWater のオブジェクトのスタイルを設定する際、スタイル設定オブジェクト内の FillModeType 列挙型を介して選択したマテリアル、カスタム色、または自動生成された色を使用して、塗りつぶしを適用できます。 Auto カラーは、領域の使用タイプの値に基づいて生成されます。