Any ideas of how to make field for strategy game?

Hello,
I’m trying to figure out, what is the best way, to create things like paths and fields on a terrain ingame. Something like creating fields in Age of empires 3, wheres the texture was right on the ground. I think creating a plane right above the ground isn’t best solution (Because of humps etc.). I googled all day but all I found is that SetAlphamaps, but found only tuts for texturing all terrain, not only one specific section only for field or road.

Here is what i want.

2075617--135514--Farm_Final.jpg

It’s the same thing really, SetAlphamaps takes a position X and Z and a float[,] that containts the weights of the textures.

So you’ll need to convert your worldPosition to terrain position and then set the weights, then call SetAlphamaps with those position index. For example this is how I do fields for my game, it already has a BoxCollider with the proper size for the field:

public static void PaintDirtTexture(GameObject go)
    {
        Terrain mainTerrain = Terrain.activeTerrain;
        TerrainData terrainData = mainTerrain.terrainData;
       
        BoxCollider boxCol = go.GetComponent<BoxCollider>();
       
        Vector3 worldPos1 = new Vector3(boxCol.bounds.min.x, go.transform.position.y, boxCol.bounds.min.z);
        Vector3 worldPos2 = new Vector3(boxCol.bounds.max.x, go.transform.position.y, boxCol.bounds.max.z);
       
        Vector3 pos1 = getTerrainRelativeAlphaPosition(worldPos1);
        Vector3 pos2 = getTerrainRelativeAlphaPosition(worldPos2);
       
        int x1 = (int)pos1.x;
        int y1 = (int)pos1.y;
        int x2 = (int)pos2.x;
        int y2 = (int)pos2.y;
       
        int originX = Mathf.Min(x1, x2);
        int originY = Mathf.Min (y1, y2);
       
        int width = Mathf.Abs(x2 - x1);
        int height = Mathf.Abs(y2 - y1);
               
        float[, ,] alphas = terrainData.GetAlphamaps(originX, originY, width, height);
       
        for(int i = 0 ; i < height ; i++)
        {
            for(int j = 0 ; j < width ; j++)
            {
                alphas[i, j, 1] = 0.8f;
                alphas[i, j, 0] = 0.2f;
                alphas[i, j, 2] = 0.0f;
                alphas[i, j, 3] = 0.0f;
            }
        }
        terrainData.SetAlphamaps(originX, originY, alphas);
    }

    //Get terrain position from world position (returns X: int Y: int)
    public static Vector3 getTerrainRelativeAlphaPosition(Vector3 position)
    {
        Terrain terrain = Terrain.activeTerrain;
        Vector3 tempCoord = position - terrain.gameObject.transform.position;
        Vector3 coord;
       
        coord.x = tempCoord.x / terrain.terrainData.size.x;
        coord.y = tempCoord.y / terrain.terrainData.size.y;
        coord.z = tempCoord.z / terrain.terrainData.size.z;
       
        int hmWidth = terrain.terrainData.alphamapWidth;
        int hmHeight = terrain.terrainData.alphamapHeight;
       
        float posXinTerrain = coord.x * hmWidth;
        float posZinTerrain = coord.z * hmHeight;
               
        return new Vector3(posXinTerrain, posZinTerrain);
    }

This will only paint the area contained within the box. You need to make sure your collider is exacly the same ratio as your alphamaps resolution on your terrain or else you could end up with bleeding.

2 Likes

It works perfectly just like I wanted. Thank you!