Terrain Elevation

Terrain elevation lets you add fully-styleable three-dimensional terrain to the games you create with the Maps SDK for Unity. Using elevation data from Google Earth, you can add a dimension of realism to in-game terrain. You can display the hills, valleys and other land features that you would find at a specific location in the real world, making it easier for players to recognize their surroundings and orient themselves.

For example, the following image shows a terrain elevation rendering of the Grand Canyon. The image uses relatively simple styling, blending rocky and grassy textures on slopes, but more complex styles are possible.

A Terrain Elevation image of the Grand Canyon

Since terrain elevation is integrated with the Unity Terrain Engine, the terrain is generated as Unity terrain tiles. Existing map features are automatically adjusted to align with the terrain. You have full control of the style of the terrain using Terrain Layers, and can define custom methods to blend layers based on the terrain’s properties. This is similar to Unity's terrain painting tools, but it can be applied at run-time. You don't need to know the particulars of the terrain mesh.

After each terrain tile is created, the game is notified by the Maps SDK for Unity event system. You can integrate additional logic into the terrain generation pipeline if needed.

The Maps SDK for Unity includes an example scene that demonstrates how to use Terrain Layers to style terrain elevation. You can find this scene in Unity's Project pane, inside the Assets > GoogleMaps > Examples folder. The scene includes a GameObject called Terrain Example Script that contains the C# script component TerrainExample.cs.

For more information about example scenes, see Maps SDK for Unity Example Scenes.

Enable terrain elevation

Enable terrain elevation using the Maps SDK for Unity Maps Service component before Awake() is called.

To enable terrain elevation using the Maps Service component:

  1. From the Unity Inspector, open the Maps Service script component.

  2. Check the Enable Terrain checkbox under Map Feature Options > Terrain.

Configure terrain parameters

When you initialize terrain elevation, you must configure the following parameters in the MapsService component.

TerrainMeshMetersPerPoint

The target resolution of generated Unity Terrain tiles, in meters per point. The default value is 1.

The actual resolution of each terrain tile may differ from the specified TerrainMeshMetersPerPoint value. The heightmap resolution of Unity Terrain tiles must be a power of 2, plus 1. The Maps SDK for Unity rounds the provided value to the nearest power of 2, plus 1 to meet this requirement.

When used with the Mixed Zoom component, the TerrainMeshMetersPerPoint value is automatically doubled each time the zoom level is lowered.

AltitudePrecision

The vertical precision of terrain altitudes in meters, between 0.01 (centimeter-level precision) and 10000 (10-kilometer-level precision). The default value is 0.01.

Painting the Terrain Surface

Unity's terrain engine renders the terrain surface by blending a set of terrain layers together according to a collection of alpha maps. Each terrain layer has some associated textures (for example, diffuse, normals). A terrain layer may be shared by multiple terrain tiles.

Each terrain tile has one alpha map for each of its terrain layers that controls the blending weight of that layer at any given point on the tile's surface. The weights of all the layers at any given point should sum to 1. The terrain layer textures are tiled across the terrain surface while the alpha map is scaled so that it covers the whole surface of each tile once.

For performance reasons the alpha maps must be generated programmatically. Run a shader program that samples from a feature mask image containing color-coded map features. The feature mask is colored according to the materials supplied as part of the regular styling configuration for each material and included in the arguments to the AlphaMapsNeedPaint event. Use an appropriate unlit material with a uniform color to color each feature. For basemap features such as regions or segments, make sure that your material uses an appropriate base map-compatible shader.

By default, no features are rendered into the feature mask. For a feature to be rendered into the feature mask, set the GameObjectLayer field in its style configuration to the same layer that you specified for terrain rendering in your TerrainStyle object. If you are using a ground plane object to cover gaps in the ground between features, you must also place this plane on the terrain rendering layer and assign an appropriate material to avoid gaps in the feature mask.

The feature mask is painted by rendering the terrain painting layer within the relevant area of the scene using an orthographic projection. If you have not covered the whole area with appropriate color-coded game objects then the underlying skybox will appear in the feature mask. Maps SDK for Unity will ensure that all of the relevant map feature game objects have been created before attempting to paint the feature mask, but it is up to you to place the ground plane. A suitable ground plane object has already been placed for you in the examples supplied with the Maps SDK for Unity.

The alpha map painting itself takes place in a coroutine that you specify inside your handler for the AlphaMapsNeedPaint event. The contents of this coroutine will vary depending on your desired surface appearance and approach, but at some point before returning the coroutine must set the terrain tile's alpha maps. These are packed in groups of four into ARGB control textures, with each channel representing the alpha map for a given layer. The technique used for writing to these control textures will vary depending upon the Unity version you are using. For example, in Unity 2019.2+ use TerrainData.CopyActiveRenderTextureToTexture. The terrain example distributed with the Maps SDK for Unity illustrates the recommended techniques for the supported versions of Unity.

Note that the painting coroutine may be cancelled without returning, so you must use the delegate provided by AlphaMapsNeedPaintArgs to register a finalizer to clean up any temporary resources you have created for use within the coroutine (for example, temporary render textures).

See the packaged examples for further details.

Displacing structures

When terrain elevation is enabled, structures such as buildings and landmarks are vertically aligned with the terrain.

For extruded structures, each structure is placed at the lowest altitude that intersects with its footprint, ensuring there are no gaps between the terrain and the bottom of the structure. Each extrusion is then elongated to prevent any roofs from clipping into the ground, whilst still maintaining the overall aspect of the rest of the building.

Modeled structures only follow the above process for placement, with no modification to the structure's model. Since a modeled structure is an arbitrary shape, the footprint is defined by the vertices at the lowest point in the structure.

Interaction with Unity

Working with Parents and Transforms

GameObjects generated by the Maps SDK for Unity are, by default, all parented to the transform of the GameObject containing the MapsService component (the map anchor). All non-Terrain GameObjects correctly follow the transform of the map anchor.

Unity does not support rotation and scaling transforations for Terrain objects. As a result, Terrain GameObjects generated by Maps SDK for Unity cannot be rotated or scaled, nor will they follow the parent GameObject when these kinds of transforms are applied. Translation is supported, as long as the Terrain GameObject is not marked as static.

As a result, Maps SDK for Unity does not support any object transformations involving Terrain, and attempting to do so may result in unusual or unexpected behaviour.

On-Device Rendering

Unity's Terrain system uses specific assets for on-device rendering. These are automatically included when Terrain is added to your scene at edit time. When used exclusively at runtime, as in the Maps SDK for Unity, these assets must be explicitly included. Without them Terrain may render incorrectly or not at all.

Unity's recommended approach is to include these assets by adding a Terrain GameObject somewhere in your scene. This automatically adds a dependency to all necessary assets, and is robust against changes between Unity versions. You can then hide this Terrain GameObject by unchecking the box next to its name in the Inspector. This approach is demonstated in the bundled Terrain example scene:

Terrain asset inclusion as demonstrated by the Terrain example scene.