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.
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:
From the Unity Inspector, open the Maps Service script component.
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 performing the following steps:
Add a Terrain GameObject somewhere in your scene.
Enable
Draw Instanced
for the GameObject's Terrain component, via the component's settings in the inspector.
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: