2
\$\begingroup\$

I need the terrain texture to change at certain positions depending on where trees etc. are randomly positioned at runtime. I'm struggling to find any solid information about how to take a particular vector3 and tell the terrain to paint a different texture of size x at that location. So far I have found a lot of information about how to change textures based on height map information. As my map is flat, that information doesn't seem very relevant.

EDIT: using the following code when each tree was randomly instantiated:

    public void ChangeTextureAtTreeLocation(Vector3 treePosition)
    {

        int mapX = (int)(((treePosition.x - terrainPos.x) / terrainData.size.x) * terrainData.alphamapWidth);
        int mapZ = (int)(((treePosition.z - terrainPos.z) / terrainData.size.z) * terrainData.alphamapHeight);
        float[,,] splatmapData = terrainData.GetAlphamaps(1, 1, 4, 4);
        terrainData.SetAlphamaps( mapX, mapZ, splatmapData);
        terrain.Flush(); 
    }

got me this result:

enter image description here

As you can tell, the results aren't great. There are two main deficiencies:

  1. I don't know how to access the terrain texture array directly so I paint a portion of the map first (see the bottom left of the image), sample that portion, and then set that sample at the location of the trees. This is not ideal as I cannot change the shape, size, or opacity of the added terrain texture. There is also no blending between textures, which gives the texture a rabbit burrow look.
  2. you cannot see it in the image, but the textures do not appear under the trees but are directly north east of them. Not sure why that is. I'm assuming it has something to do with how textures are drawn relative to their origin.
\$\endgroup\$
  • \$\begingroup\$ What is terrainPos in this example? terrain.GetPosition()? I'm attempting to do the same thing you are and having no luck. \$\endgroup\$ – Matt May 22 '17 at 0:40
  • \$\begingroup\$ not sure. It's been a while since I looked at this code. I still want to achieve this behaviour so I'll look into again soon and post here \$\endgroup\$ – OwenAlexander May 24 '17 at 3:43
3
\$\begingroup\$

Terrain has a "setAlphaMaps" function you can use to modify the terrain splat maps at runtime.

You can find the documentation (along with an example) in the official unity documentation here: http://docs.unity3d.com/ScriptReference/TerrainData.SetAlphamaps.html

Just make sure you call Terrain.Flush when you're done.

As your target is a vector3 you will have to convert it into 2D space and scale the position relative to the origin of the terrain, but then you can just set pixels in the alpha maps around that point.

So lets address your issues.

  1. The way splat mapping works is by additively blending 4 textures based on the floats in the Red, Green, Blue and Alpha channels in a bitmap. So you should be able to get half alpha of texture 1 by setting Red to 0.5. You're going to have to do some math to smooth the alpha value in a radius from your target point.

  2. You're getting the pixels +4 in X and Z around your target point, try offsetting the point you index into the array by -half of the diameter you want the splat to be (make sure you clamp it).

I hope that solves your issues.

\$\endgroup\$
  • \$\begingroup\$ Thanks for your reply. I edited my original answer. I still have some problems, so any further advice would be greatly appreciated. \$\endgroup\$ – OwenAlexander Aug 6 '15 at 22:34
  • \$\begingroup\$ So lets address your issues. \$\endgroup\$ – cfehunter Aug 7 '15 at 8:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.