Schlüsselkonzepte des Maps SDK for Unity

In den folgenden Abschnitten werden die Konzepte beschrieben, die für das Verständnis und die Verwendung des Maps SDK for Unity wichtig sind.

Klasse und Komponente „MapsService“

Die Klasse MapsService dient als Einstiegspunkt für die Interaktion mit dem Maps SDK for Unity. Sie kapselt den ApiKey und macht den GameObjectManager, die Funktion LoadMap sowie Ereignisse aus der GameObject Creation-Pipeline verfügbar.

Wenn Sie das Maps SDK for Unity in Ihrem Unity-Projekt verwenden möchten, fügen Sie die Map Service-Skriptkomponente in einer leeren GameObject in Ihrer Szene ein. Der Kartendienst fügt automatisch generierte GameObjects für Kartenelemente als untergeordnete Elemente dieses Anker-GameObject hinzu. Wenn der Maps Service (Script) an Ihr Basis-GameObject angehängt ist, können Sie wie hier gezeigt im Unity Inspector auf dessen öffentliche Attribute zugreifen.

Maps-Dienst (Script)

Geografische Elemente als Unity GameObjects

Mit dem Maps SDK for Unity werden geografische Elemente wie Gebäude, Straßen und Gewässer aus der Google Maps-Datenbank als Unity GameObjects in Spielen gerendert. Während der Laufzeit werden sie als untergeordnete Elemente des GameObjects erstellt, an das die MapsService-Komponente angehängt ist. Sie haben Namen im Format {MapFeatureType}({PlaceID}).

SDK-Spielobjekte

GameObject-Erstellung

Während des Spiels ruft das SDK Geodaten aus der Google Maps-Datenbank ab – als semantische Vektorkacheln (über die Semantic Tile API). Es decodiert diese Daten spontan und wandelt sie in Unity GameObjects um. Bei diesem Ansatz können Sie so bald wie möglich auf Kartenelementdaten (sowohl die Metadaten als auch die Geometriedaten) zugreifen und die GameObjects anpassen, bevor sie das Ende der Pipeline erreichen.

Wenn das Maps SDK for Unity Vektordaten empfängt, wird als Erstes ein MapFeature-Objekt daraus erstellt.

In einer Zwischenphase der Pipeline sind MapFeature-Objekte spezialisiert. Sie werden also zu spezifischen Typen (z. B. Google.Maps.Feature.ModeledStructure). Diese speziellen MapFeature-Objekte enthalten die MapFeatureShape-Geometriedetails (bei ModeledStructure ModeledVolume). Zu diesen Details gehören sowohl MapFeature-spezifische Daten (z. B. Eckpunkte und Dreiecke) als auch gemeinsame Schnittstellen für den Zugriff auf allgemeine Felder (z. B. Begrenzungsrahmen).

Geometriedaten werden in ein Unity Mesh konvertiert und über MeshFilter dem generierten GameObject hinzugefügt und dann mit einem MeshRenderer-Element angezeigt.

Auf die Pipeline zugreifen

MapFeatures sind für Sie über Ereignisse sichtbar, die in verschiedenen Phasen der Pipeline ausgelöst werden. Dazu gehören WillCreate-Ereignisse, die direkt vor dem GameObject ausgelöst werden, sodass Sie Stiloptionen angeben oder sogar die Erstellung abbrechen können. Außerdem werden DidCreate-Ereignisse ausgelöst, die direkt nach dem Erstellen des GameObjects ausgelöst werden, sodass Sie dem fertigen Mesh-Netzwerk hinzufügen oder Änderungen daran vornehmen können.

Beispielsweise können Sie ExtrudedStructures nach den WillCreateExtrudedStructureEvent-Bränden untersuchen und alle Gebäude ausblenden, die kürzer als 20 Meter sind. Alternativ können Sie die Erstellung ganz überspringen.

Ereignistypen

Der Namespace Google.Maps.Event enthält eine Ereignisklasse für jeden Typ geografischer Elemente.

Jeder dieser Ereignistypen hat ein WillCreate- und ein öffentliches DidCreate-Ereignisobjekt, das Sie abonnieren können, wie im folgenden Codebeispiel veranschaulicht.

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 Ereignisse

WillCreate-Ereignisse werden sofort ausgelöst, nachdem ein MapFeature-Element erstellt wurde, aber bevor das endgültige GameObject daraus generiert wird. Mit WillCreate-Ereignissen können Sie die aus MapFeature erstellten GameObjects unterdrücken oder anpassen. Argumente von WillCreate-Ereignissen haben das folgende Format:

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;
    }
  }
}
  • Wenn Sie für Cancel (von CancelEventArgs übernommen) den Wert true festlegen, wird das Erstellen des GameObject unterdrückt.
  • MapObject ist schreibgeschützt.
  • Mit der Einstellung Style können Sie die Darstellung des erstellten GameObjects anpassen.
  • Mit der Einstellung Prefab wird das GameObject, das sonst generiert worden wäre, durch die Voreinstellung ersetzt.

DidCreate Ereignisse

DidCreate-Ereignisse werden ausgelöst, nachdem ein GameObject generiert wurde, nachdem es der Szene hinzugefügt wurde. Sie benachrichtigen Sie, wenn das GameObject erfolgreich erstellt wurde, sodass Sie es weiter verarbeiten können. DidCreate-Ereignisargumente haben das folgende Format:

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 ist schreibgeschützt. Eine Änderung führt also nicht zu einer Änderung der Szene.
  • Durch das Ändern von CreatedObject wird das zur Szene hinzugefügte GameObject geändert.

Gebäude

Es gibt zwei Arten von Gebäuden: extrudierte Gebäude und modellierte Gebäude.

Extrudierte Gebäude

Extrudierte Gebäude werden aus einem Umriss (einem 2D-Grundriss) und einer Höhe generiert. Das SDK stellt die meisten Gebäude auf diese Weise dar und generiert sie auf drei Arten:

  • Verwendung von realen Höhendaten (sofern diese Informationen verfügbar sind). Das ist die Standardeinstellung.

  • Für alle Gebäude wird eine feste Höhe ohne Berücksichtigung der tatsächlichen Höhe angegeben.

  • Indem Sie eine Sicherungshöhe für alle Gebäude angeben, die keine tatsächliche Höhe haben (standardmäßig ist dieser Wert auf 10 Meter festgelegt).

Durch die Kombination dieser drei Methoden lassen sich mit dem Maps SDK for Unity Stadtansichten mit realistischer Varianz für die reale Welt, mit konstanter Gebäudehöhe oder einer Mischung aus beidem erstellen.

Modellierte Gebäude

Modellierte Strukturen werden nach dem Standardansatz für die 3D-Modellierung mit tesselierten Dreiecken generiert. Dieser Ansatz wird normalerweise für Sehenswürdigkeiten wie die Freiheitsstatue verwendet.

Die modellierte Freiheitsstatue

Materialien anwenden

In Unity werden für den Renderingprozess Shader, Materialien und Texturen verwendet, um GameObjects realistischer zu gestalten. Shader definieren, wie Texturen, Farben und Beleuchtung auf die angezeigte Geometrie angewendet werden. Die spezifischen Texturen, Farben und anderen verwendeten Einstellungen werden als Material gespeichert. Mithilfe von Materialien definieren Sie, wie eine Oberfläche gerendert wird. Dazu beziehen Sie Verweise auf die verwendeten Texturen, auf Kacheln und Farben.

Shader sind kleine Skripts, die die Logik für die Berechnung der Farbe jedes Pixels – basierend auf der Eingabe der Beleuchtung und der Materialkonfiguration – enthalten. Das Maps SDK for Unity enthält einen Standard-Shader für modellierte Strukturen und einen weiteren für Basiskartenfeatures, unterstützt aber auch erweiterte Materialanwendungen. Die Koordinaten für die UV-Zuordnung werden für GameObjects für Kartenelemente so berechnet, dass jedes Grundmaterial angewendet werden kann und ohne Änderung angemessen aussieht.

Für komplexere Materialeffekte bietet das Maps SDK for Unity zusätzliche Daten pro Scheitelpunkt über zusätzliche UV-Kanäle sowie eine Reihe von praktischen Funktionen für cg-Shader über die GoogleMapsShaderLib-Bibliothek. Dies ermöglicht beispielsweise Gebäudetexturen mit neun Schliffen, mit denen dem Dach, dem Boden, den Wandecken und den gekachelten Wänden eines Gebäudes Texturen ausgeschnitten werden.

Weitere Informationen finden Sie unter Erstellen und Verwenden von Materialien im Unity-Nutzerhandbuch.

UV-Kanäle

Die UV-Kanäle für jeden MapFeature-Typ enthalten Daten in folgender Form:

ExtrudedStructure

Walls

Jede Wand eines ExtrudedStructure wird als Quadrat der folgenden Form konstruiert:

Walls

Die UV-Koordinaten für Wände werden pro Quadrat berechnet. Eckpunkte werden nicht zwischen den Vierecken geteilt, um harte Normalen zwischen Wänden zu ermöglichen (d. h., die Ecken der Wände erscheinen als harte Winkel statt als weiche, abgerundete Kanten).

Kanal 0: (x, y, Breite, Höhe)
x und y sind die Koordinaten relativ zur unteren linken Ecke dieses Quadrats (quadratischer Abschnitt) der Wand. width und height sind Breite und Höhe dieses Quadrats der Wand. Dies gilt für jedes Viereck, das die Wand bildet.
Dach

Dachtexturen können entweder achsen- oder an der Richtung von ExtrudedStructure ausgerichtet sein. Sie legen dies über das Objekt ExtrudedStructureStyle fest.

Kanal 0: (x, y, Breite, Höhe)
x und y sind die Koordinaten der einzelnen Scheitelpunkte in Bezug auf die linke untere Ecke des Dachs, genauer gesagt die Ecke des an der Achse ausgerichteten Begrenzungsrahmens des Dachs an der Mindestabdeckung. width und height definieren die Größe des Begrenzungsrahmens des Dachs.

Region

Kanal 0: (x, y, Breite, Höhe)
x und y sind die Koordinaten jedes Scheitelpunkts im Verhältnis zur linken unteren Ecke des achsenbündigen Begrenzungsrahmens für den Bereich. width und height definieren die Größe des Begrenzungsrahmens.

Segment

Kanal 0: (x, y, Breite, Länge)
x und y sind die Koordinaten der einzelnen Eckpunkte. Sie werden so berechnet, als wäre das Segment vollständig gerade, damit sich die Textur um Ecken biegen kann. width und length definieren die Abmessungen des Segments.

ModeledStructure

Kanal 0:
Jede Koordinate ist auf (0, 0, 0, 0) festgelegt, da derzeit keine Texturkoordinaten implementiert sind.

GoogleMapsShaderLib

Das Maps SDK for Unity enthält eine Shader-Bibliothek namens GoogleMapsShaderLib, mit der Sie Shader erstellen können, die gut mit MapFeature-GameObjects funktionieren. Die Bibliothek wird in der Datei GoogleMapsShaderLib.cginc implementiert. Sie können die Bibliothek verwenden, indem Sie die folgende #include-Anweisung in den Abschnitt der CGPROGRAM-Flags in Ihrem Shader-Skript aufnehmen.

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

Die Shader-Bibliothek ist im GoogleMaps.unitypackage gebündelt. Nachdem Sie das Paket importiert haben, finden Sie GoogleMapsShaderLib.cginc im Projektordner /Assets/GoogleMaps/Materials/.

Neun

GoogleMapsShaderLib enthält eine praktische Funktion, die Sie in Fragment-Shadern verwenden können, um Texturen neun Slicing zu untergliedern. Das Neun-Schneiden ist ein Verfahren zum Abdecken von Oberflächen mit einer Textur, wobei die Textur mithilfe einer Reihe von Begrenzungen in neun Teile unterteilt wird. Bereiche zwischen den Grenzen werden gekachelt und Bereiche außerhalb der Grenzen bleiben fixiert – wie hier dargestellt:

Neun

Wenn Sie beispielsweise eine Textur mit neun Scheiben auf die Wand eines Gebäudes anwenden, wird der obere Teil der Textur auf die Oberseite der Wand (direkt unter dem Dach) und die Unterseite der Textur (die mit dem Boden verbunden) auf die Wand angewendet. Die Seiten der Textur werden auf die Ränder der Wand angewendet und der Bereich in der Mitte der Textur gleichmäßig über die Wand verteilt.

Bei Straßen (in einem anderen Beispiel) können Sie so einen Bürgersteig mit einer festen Breite, aber je nach Breite der Straße mit einer unterschiedlichen Anzahl von Fahrspuren erstellen.

Dazu fügen Sie GoogleMapsShaderLib.cginc in Ihren Shader ein und rufen dann die Funktion nineSlice auf. Beispiel-Shader und -Materialien sind im GoogleMaps.unitypackage enthalten. Sie zeigen, wie Sie mit der Funktion nineSlice einen realistischen Skyscraper unterschiedlicher Größe erstellen können, ohne sich zu strecken oder zu zerreißen.

Standort für Beispielmaterialien
/Assets/GoogleMaps/Examples/04_Advanced/MoreStyling/Materials/NineSlicing
Beispiel für einen Shader-Standort
/Assets/GoogleMaps/Examples/04_Advanced/MoreStyling/Materials/NineSlicing/BuildingWall.shader

Sie können für jedes MapFeature-Element mit Ausnahme von ModeledStructures, das derzeit keine Texturkoordinaten hat, das Segmentieren nach Neun verwenden.

Das Koordinatensystem

Das Koordinatensystem des Maps SDK for Unity verwendet die Web Mercator-Projektion, um zwischen sphärischen Breiten- und Längengraden im WGS 84-Format und kartesischen Unity Worldspace (Vector3) umzuwandeln.

Vector3-Werte beziehen sich auf einen Floating-Ursprung, der normalerweise auf die Startposition des Nutzers festgelegt ist. Daher sollten Sie Vector3-Werte nicht außerhalb einer Sitzung, d. h. auf Ihrem Server oder dem Gerät des Nutzers, beibehalten. Wir empfehlen, Standorte in der realen Welt mithilfe von Paaren aus Breiten- und Längengrad anzugeben.

Ein Floating-Ursprung wird verwendet, um Stabilitätsprobleme bei Gleitkommazahlen zu vermeiden. Die Vector3-Klasse von Unity verwendet Gleitkommazahlen mit einfacher Genauigkeit und die Dichte der darstellbaren Gleitkommazahlen nimmt mit zunehmender Größe ab. Das bedeutet, dass größere Gleitkommazahlen weniger genau sind. Sie können den schwebenden Ursprung immer dann aktualisieren, wenn Nutzer sich weit genug vom Ursprung entfernen, dass dies zu einem Problem wird. Sie können einen relativ kleinen Wert (z. B. 100 oder 200 Meter) oder einen größeren Wert (über 1 km) festlegen, je nachdem, wie oft Sie Daten aktualisieren möchten.

Unity Worldspace wird basierend auf dem Breitengrad des anfänglichen Startorts auf 1:1 (Meter) skaliert. In der Mercator-Projektion variiert die Größe je nach Breitengrad leicht. Daher weicht die Einheit von 1:1 geringfügig von 1:1 ab, wenn sich Nutzer nach Norden und Süden bewegen. Es wird jedoch nicht erwartet, dass die Nutzer sich weit (oder schnell) genug bewegen, damit dies auffällt.

Das Maps SDK for Unity enthält Konvertierungsfunktionen zum Konvertieren zwischen Google.Maps.LatLng und Unity Worldspace (Vector3) und berücksichtigt dabei Gleitkommazahl und Gleitkommazahl.

Ladefehler

Fehler, die beim Laden von Kartendaten aus dem Netzwerk auftreten, können mit dem Ereignis MapLoadErrorEvent behoben werden. Das Maps SDK for Unity verarbeitet die meisten Fehlertypen selbst, wenn Sie keinen Event-Handler hinzufügen. Es liegt jedoch ein Fehler vor, der eine Aktion Ihrer Anwendung erfordert. Dies wird durch MapLoadErrorArgs.DetailedErrorCode angegeben und unten beschrieben.

UnsupportedClientVersion

Diese Version des Maps SDK for Unity wird nicht mehr unterstützt – möglicherweise in Kombination mit dem aktuellen API-Schlüssel. In der Regel sollte Ihre App den Nutzer dazu auffordern, auf eine neuere Version Ihrer App zu aktualisieren.

Dieser Fehler bedeutet in der Regel, dass die Version des Maps SDK for Unity veraltet ist. In seltenen Fällen können wir diese Funktion nutzen, wenn wir ein kritisches Problem mit einer Version des Maps SDK for Unity oder mit einem API-Schlüssel feststellen. Wir werden uns bemühen, dies zu kommunizieren und sicherzustellen, dass dies nicht der Fall ist, bis eine funktionierende Version der App für ein Update verfügbar ist.

Als Best Practice sollten Sie dafür sorgen, dass Ihre App im Falle dieses Fehlers über einen geeigneten Upgradepfad verfügt, damit Ihre Nutzer zu einer neueren Version der App mit einer unterstützten SDK-Version migrieren können. Weitere Informationen finden Sie in der Dokumentation zum Client Kill Switch.

Bekannte Probleme

Basiskartenelemente werden rückwärts ohne Z-Tests gerendert, da alle Elemente dieses Typs in derselben Ebene gerendert werden. Sie müssen z-testing für alle Ersatzmaterialien, die Sie für Basiskartenelemente verwenden, auf ZTest Always setzen, damit sie korrekt gerendert werden.

Google hat im GoogleMaps.unitypackage einen Beispiel-Shader eingefügt, der diese Probleme löst. Sie heißt "BaseMapTextured.shader und befindet sich im Ordner /Assets/GoogleMaps/Materials/. Wenn Sie sie für ein Material verwenden möchten, wählen Sie im Shader-Drop-down-Menü des Material Inspectors Google > Maps > Shaders > BaseMap Textured aus.

Wenn Sie ein Feature.Region- oder Feature.AreaWater-Objekt gestalten, können Sie eine Füllung mit einem Material, einer benutzerdefinierten Farbe oder einer automatisch generierten Farbe anwenden, die über die Aufzählung FillModeType im Stilobjekt ausgewählt wird. Auto-Farben werden basierend auf dem Wert des Nutzungstyps der Region generiert.