Hex Terrains Framework
Search Results for

    Show / Hide Table of Contents

    Getting Started

    Terrain View

    Demo Scenes

    1. Install package from asset store.

    2. If you use a Universal Render Pipeline, you are good to go. But if you use a High Definition Render Pipeline, extract HDRP assets from included DemoAssets_HDRP.unitypackage (Assets/freewebtime/Samples/HexTerrains_Demo/DemoAssets_HDRP.unitypackage). Double click on the DemoAssets_HDRP.unitypackage, in the popup ensure that all assets are selected and press "Import" button. This will overwrite URP assets with HDRP ones in your demo scenes.

      Install HDRP Assets

    3. Navigate to folder Assets/freewebtime/Samples/HexTerrains_Demo/Scenes

    4. Open Static Terrains scene or Dynamic Terrains scene

      Demo Scene

    5. Press "Play" button

      Gameplay on Demo Scene

    6. To create another terrain, select "System" User Tool category, then "Create New"

      Create Terrain

    7. In openned window select a terrain prefab and put the settings you want.

      Create Terrain Popup

    8. Press "Create" button

    9. Enjoy!

      Gameplay

    In-game terrain editor

    1. In-game editor is a State Machine called (see class UserToolStateMachine). State Machine has a set of User Tool States like Deform Terrain, Paint Biomes, Paint Cell Items, Paint Countries, etc. Every UserToolState communicates with a Terrain using a proxy implementation of the IHexTerrainAPI (see HexTerrainAPI class).

    2. All User Tools are split between a set of categories:

      • Surfaces Tools

        (Deform, Level, Noise, Smooth, Apply Heightmap, Paint Biome, Auto-paint Biome, Stamp Height, Stamp Biome, Set Layer Visibility)

        Ground Tools

      • Cell Objects Tools

        (Paint Cell Object, Stamp Cell Object, Cell Object Index, Cell Object State, Cell Object Position, Cell Object Rotation, Cell Object Scale)

        Cell Items

      • Cell Entities Tools

        (Paint Cell Entity, Stamp Cell Entity, Cell Entity Index, Cell Entity State, Cell Entity Position, Cell Entity Rotation, Cell Entity Scale)

        Cell Entities

      • Cell Regions Tools

        (Paint Regions, Stamp Regions)

        Provinces

      • Cell Minerals Tools

        (Paint Minerals, Paint Mineral Index, Paint Minerals Amount, Heightmap, Deform, Noise, Smooth, Stamp)

        Provinces

      • GeoPlast Amount Tools

        (Level, Apply Heightmap, Deform, Noise, Smooth, Stamp)

        GeoPlast Amount

      • GeoPlast Density Tools

        (Level, Apply Heightmap, Deform, Noise, Smooth, Stamp)

        GeoPlast Amount

      • GeoPlast Heat Tools

        (Level, Apply Heightmap, Deform, Noise, Smooth, Stamp, Sun)

        GeoPlast Amount

      • System Tools

        (Toggle Visibility, Resize Terrain, Save Terrain, Load Terrain, Create New)

        System

    View Modes

    How to change the View Mode

    To change a view mode, click on "View Mode" dropdown and select an option you want.

    View Modes

    Hex Terrain supports rendering in a different view modes. View mode is a number, the value of the HexTerrainViewMode component on a Terrain Entity.

        /// <summary>
        /// Contains the current view mode of the terrain.
        /// </summary>
        public struct HexTerrainViewMode : IComponentData
        {
            /// <summary>
            /// The current view mode of the terrain.
            /// </summary>
            public int Value;
        }
    

    Take a look at the Terrain Prefab. The Hex Terrain Authoring component has a View Mode Collection Config field.

    How to Setup View Modes

    View Mode Collection on Terrain Prefab

    View Mode Collection Config is a scriptable object that can be created by selecting Create/Fwt/HexTerrains/View Modes/ViewMode Collection config

    Create View Mode Collection Config

    The asset holds a collection of View Mode configs. You may want to have different collections of View Modes for different terrains:

    View Mode Collection Asset

    There are several built-in view modes already, but it's very easy to expand the list. Here are few examples:

    • Default View Mode (Regular terrain view)

      ViewMode Normal

    • Biomes View Mode

      ViewMode Biome

    • Heighmap View Mode

      ViewMode Heightmap

    • Provinces View Mode

      ViewMode Provinces

    • Ocean Heat View Mode

      ViewMode Countries

    • Ocean Temperature View Mode

      ViewMode Countries

    • Minerals View Mode

      ViewMode Minerals

    • And others (see "Assets/Samples/com.freewebtime.hexterrains/2.0.0/HexTerrains_Demo/Configs/ViewModes" folder)

    To setup a ViewMode, create a new ViewMode asset scriptable object:

    Create ViewMode Asset

    Configure the ViewMode asset:

    Configure ViewMode Asset

    Add as much ColorMap layers as you need, and set which data should be displayed on each of them, and from which terrain layer to get the data.

    For example, there is a "Default" View Mode that fills 6 textures with color data: Ground Biome, Cell Entities, Cell Objects, Ocean Biomes, Snow Biomes, Clouds Biomes. All 6 textures are filled with colors from respective data layers and then are sent to the Minimap UI where are displayed together one on top of another. See preconfigured ViewMode configs for more details. Note that textures that are filled with colors should have Read/Write option enabled in the texture import settings:

    Enable Read/Write for Textures

    Most of data layers support a color map (they have a color map NativeArray and they fill a corresponding pixel with a color that respresents the current cell value). For example, the ChunkMesh has a BiomeMap data layer and each biome has it's own color:

    Biomes Color Palette

    or, for example, the Color setup for each Cell Object:

    Cell Object Colors

    Terrain materials by View Mode

    Take a look at configuration of one of your ChunkMesh Layer configs. For example, the Earth Ground Chunk Mesh Layer (Assets/freewebtime/Samples/HexTerrains_Demo/Configs/Terrain Layers/ChunkMesh/Ground_Earth ChunkMesh). You can see a Render Configs list and a Default Render Config. When ViewMode is 0, the ChunkMesh layer is rendered with RenderConfigs[0], when ViewMode is 1, it uses RenderConfigs[1], and so on. If there is no Render Config at index of a View Mode, the layer is rendered with Default Render Config. This way you can setup different looks in different View Modes.

    Terrain Render Configs

    Render Config is a collection of Materials to be used for a generated Terrain Chunk Mesh (one material per submesh):

    Color Map Textures2

    Color Map Textures2

    If you want to render a color map data on a terrain directly (the colors from Minimap on a terrain surface), in a terrain material for a specific ViewMode use the same texture that is used on Minimap UI, and make a material that uses UV3 (fourth UV set):

    Color Map Shader

    Color Map Textures3

    Create terrain on scene load

    If you want to have a terrain loaded at scene load, just put on the subscene a terrain prefab. If you have a HexTerrainEditor prefab on the scene, set a reference to the terrain prefab in the User Tools State Machine Authoring script in the field Terrain.

    You can find Terrain prefabs in the Samples folder by path "HexTerrains_Demo/Prefabs/Prefabs"

    Terrain Prefabs

    Put a prefab you want on the subscene. Now the terrain will be baked and appear on a scene in Play mode.

    If you have a Terrain Editor on the subscene, set it a reference to the terrain authoring game object.

    Terrain Entity Reference

    Note: if you don't set a reference to the terrain on the HexTerrainEditor, you will not be able to edit a terrain using the User Tools Panel at the bottom center of the screen.

    Note: HexTerrainEditor prefab is optional. It is needed for having the User Tools Panel to be created. For your gameplay it might not be needed, so feel free to get rid of it.

    How to interact with a Terrain

    1. To see how it's done, take a look at interface IHexTerrainAPI and it's example implementation HexTerrainAPI class:
    /// <summary>
    /// Provides a comprehensive interface for interacting with hexagonal terrain systems, enabling access to terrain
    /// entities, layers, settings, and related UI and environment functionality.
    /// </summary>
    /// <remarks>The IHexTerrainAPI interface exposes methods and properties for managing and querying various
    /// aspects of a hex terrain, including cell data, terrain layers, brush controls, visibility, and persistence. It
    /// supports advanced operations such as layer manipulation, raycasting, prefab configuration, and UI screen
    /// management. Implementations should ensure thread safety and proper initialization of terrain entities and layers
    /// before use. This interface is intended for use in applications that require dynamic and granular control over
    /// hex terrain features, such as editors or simulation tools.</remarks>
    public interface IHexTerrainAPI
    {
        ///...
        
        /// <summary>
        /// Returns a terrain layer of type <typeparamref name="TTerrainLayer"/> from the terrain layer group <typeparamref name="TTerrainLayerGroup"/> from the Terrain Entity
        /// </summary>
        /// <typeparam name="TTerrainLayer">Type of the Terrain layer to get from a layer group</typeparam>
        /// <typeparam name="TTerrainLayerGroup">Type of the Terrain Layer Group to find on the entity</typeparam>
        /// <param name="layerReference">reference data to needed layer</param>
        /// <returns>terrain layer if found and null otherwise</returns>
        TTerrainLayer GetTerrainLayer<TTerrainLayerGroup, TTerrainLayer>(HexTerrainLayerReference layerReference)
            where TTerrainLayer : HexTerrainLayer
            where TTerrainLayerGroup : HexTerrainLayerGroup
        {
            var layerGroup = GetTerrainLayer<TTerrainLayerGroup>();
            if (layerGroup != null)
            {
                return layerGroup.GetLayer<TTerrainLayer>(layerReference);
            }
    
            return null;
        }
    
    
        /// <summary>Returns the HeightMap value at the specified cell index from the specified ChunkMeshLayer.
        /// </summary>
        /// <typeparam name="TLayerGroup">type of HexTerrainLayerGroup entity component to get the ChunkMeshLayer from</typeparam>
        /// <typeparam name="TLayer">type of ChunkMeshLayer from the HexTerrainLayerGroup to get a cell value from</typeparam>
        /// <param name="cellIndex">cell index to get a value from</param>
        /// <param name="layerReference">reference to the layer to get a cell value from</param>
        /// <returns>value if found or null if not found</returns>
        float? GetCellHeight<TLayerGroup, TLayer>(int cellIndex, HexTerrainLayerReference layerReference)
            where TLayerGroup : HexTerrainLayerGroup, IComponentData
            where TLayer : ChunkMeshLayer;
    
    
        /// <summary>
        /// Sets the HeightMap value at the specified cell index at the specified ChunkMeshLayer.
        /// </summary>
        /// <typeparam name="TLayerGroup">type of HexTerrainLayerGroup entity component to get the ChunkMeshLayer from</typeparam>
        /// <typeparam name="TLayer">type of ChunkMeshLayer from the HexTerrainLayerGroup to set a cell value at</typeparam>
        /// <param name="cellIndex">cell index to set a value at</param>
        /// <param name="layerReference">reference to the layer to set a cell value at</param>
        /// <param name="value">value to set</param>
        /// <returns>true if value has been set, otherwise - false</returns>
        bool SetCellHeight<TLayerGroup, TLayer>(int cellIndex, HexTerrainLayerReference layerReference, float value)
            where TLayerGroup : HexTerrainLayerGroup, IComponentData
            where TLayer : ChunkMeshLayer;
    
    
        /// ...    
    }
    

    In general all the interactions are done by accessing components on the Terrain Entity:

    /// <summary>
    /// returns a data layer from the TerrainEntity <see cref="TerrainEntity"/> 
    /// </summary>
    /// <typeparam name="TDataLayer"></typeparam>
    /// <returns></returns>
    public virtual TDataLayer GetTerrainLayer<TDataLayer>() where TDataLayer : class
    {
        if (!EntityManager.Exists(TerrainEntity) || !EntityManager.TryGetComponentObject<TDataLayer>(TerrainEntity, out var dataLayer))
        {
            return default;
        }
        return dataLayer;
    }
    
    /// <summary>Returns the HeightMap value at the specified cell index from the specified ChunkMeshLayer.
    /// </summary>
    /// <typeparam name="TLayerGroup">type of HexTerrainLayerGroup entity component to get the ChunkMeshLayer from</typeparam>
    /// <typeparam name="TLayer">type of ChunkMeshLayer from the HexTerrainLayerGroup to get a cell value from</typeparam>
    /// <param name="cellIndex">cell index to get a value from</param>
    /// <param name="layerReference">reference to the layer to get a cell value from</param>
    /// <returns>value if found or null if not found</returns>
    public virtual float? GetCellHeight<TLayerGroup, TLayer>(int cellIndex, HexTerrainLayerReference layerReference)
        where TLayerGroup : HexTerrainLayerGroup, IComponentData
        where TLayer : ChunkMeshLayer
    {
        var layersList = GetTerrainLayer<TLayerGroup>();
        if (layersList == null)
        {
            return default;
        }
    
        var terrainLayer = layersList.GetLayer<TLayer>(layerReference);
        if (terrainLayer == null)
        {
            return default;
        }
    
        var dataLayer = terrainLayer.HeightMap;
    
        if (!dataLayer.TryGetData(cellIndex, out var value))
        {
            return default;
        }
    
        return value;
    }
    
    /// <summary>
    /// Sets the HeightMap value at the specified cell index at the specified ChunkMeshLayer.
    /// </summary>
    /// <typeparam name="TLayerGroup">type of HexTerrainLayerGroup entity component to get the ChunkMeshLayer from</typeparam>
    /// <typeparam name="TLayer">type of ChunkMeshLayer from the HexTerrainLayerGroup to set a cell value at</typeparam>
    /// <param name="cellIndex">cell index to set a value at</param>
    /// <param name="layerReference">reference to the layer to set a cell value at</param>
    /// <param name="value">value to set</param>
    /// <returns>true if value has been set, otherwise - false</returns>
    public virtual bool SetCellHeight<TLayerGroup, TLayer>(int cellIndex, HexTerrainLayerReference layerReference, float value)
        where TLayerGroup : HexTerrainLayerGroup, IComponentData
        where TLayer : ChunkMeshLayer
    {
        var layersList = GetTerrainLayer<TLayerGroup>();
        if (layersList == null)
        {
            return false;
        }
        var terrainLayer = layersList.GetLayer<TLayer>(layerReference);
        if (terrainLayer == null)
        {
            return false;
        }
    
        var dataLayer = terrainLayer.HeightMap;
        if (dataLayer == null)
        {
            return false;
        }
    
        return dataLayer.TrySetData(cellIndex, value);
    }
    
    • Edit this page
    In this article
    Back to top Generated by DocFX