Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by justin35f · Jan 19, 2013 at 02:05 AM · textureterrain

SetAlphamaps with multiple terrains at runtime

I'm trying to use the SetAlphamaps function on multiple terrains at run-time, but I'm running into an issue. Here's a rundown of what I have;

I'm generating 4 terrain tiles at run-time, and generating heightmaps via perlin noise. After this I am setting the splatmaps based off of height and slope.

This all works perfectly fine when I do it for one terrain. Now that I am using multiple terrain tiles, when I use SetAlphamaps it sets the the alphamap for all the terrains to the same one. It seems as if the terrainData is static or something.

Here is a relevant code snippet:

 void genTextures(TerrainData terrain)
     {
         int xRes = terrain.heightmapHeight;
         int zRes = terrain.heightmapHeight;
         float[,] heights = terrain.GetHeights(0, 0, xRes, zRes);
 
         float[, ,] splatmapData = new float[terrain.alphamapWidth, terrain.alphamapHeight, terrain.alphamapLayers];
         Vector4 peak = new Vector4 (1, 0, 0, 0);
         Vector4 grass = new Vector4 (0, 1, 0, 0);
         Vector4 dirt = new Vector4 (0, 0, 1, 0);
         Vector4 cliff = new Vector4 (0, 0, 0, 1);
         Vector4 splat = dirt;
 
         int maxHeight = 600;
         int layer1 = 250;
         int layer2 = 175;
         for (int i = 0; i < terrain.alphamapHeight; i++)
         {
             for (int j = 0; j < terrain.alphamapWidth; j++)
             {
                 Vector2 normalizedPos = new Vector2(Mathf.InverseLerp(0.0f, terrain.alphamapHeight, j), Mathf.InverseLerp(0.0f, terrain.alphamapWidth, i));
                 Vector3 angle = terrain.GetInterpolatedNormal(normalizedPos.x, normalizedPos.y);
                 float cliffAngle = Vector3.Angle(Vector3.up, angle);
                 float slope1 = 67f;
                 float slope2 = 63f;
                 if(heights[i, j] > layer1)
                 {
                     Vector3 temp = Vector4.Lerp (grass, peak, (heights[i, j] - layer1) / (maxHeight - layer1));
                     if(cliffAngle > slope2)
                     {
                         splat = Vector4.Lerp (temp, cliff, (cliffAngle - slope2) / (3 * (slope1 - slope2)));
                     }
                     else
                     {
                         splat = temp;
                     }
                 }
                 else if(heights[i, j] > layer2)
                 {
                     Vector3 temp = Vector4.Lerp (dirt, grass, (heights[i, j] - layer2) / (layer1 - layer2));
                     if(cliffAngle > slope2)
                     {
                         splat = Vector4.Lerp (temp, cliff, (cliffAngle - slope2) / (3 * (slope1 - slope2)));
                     }
                     else
                     {
                         splat = temp;
                     }
                 }
                 else
                 {
                     if(cliffAngle > slope2)
                     {
                         splat = Vector4.Lerp (dirt, cliff, (cliffAngle - slope2) / (3 * (slope1 - slope2)));
                     }
                     else
                     {
                         splat = Vector4.Lerp (dirt, dirt, (heights[i, j] - layer1) / (maxHeight - layer1));
                     }
                 }
                 
                 splat.Normalize();
                 splatmapData [i, j, 0] = splat.x;
                 splatmapData [i, j, 1] = splat.y;
                 splatmapData [i, j, 2] = splat.z;
                 splatmapData [i, j, 3] = splat.w;
             }
         }
         terrain.SetAlphamaps(0, 0, splatmapData);
     }

This function is called in a for loop that cycles through each terrain object, passing in the relevant TerrainData object. This is exactly the same way I set my heightmap for each Terrain, so I'm confused as to why the alphamaps would not work the same.

Any help is appreciated. If I need to explain further, please let me know. Here is a screenshot showing that the alphamap is the same across 4 terrain tiles.

alt text

EDIT

Ok, as per my last comment, here is some additional code that may be involved.

 TerrainData terdata;
         terdata = Resources.Load("template") as TerrainData;
         int terRes = 2000;
         int terrainArraySize = 2;
         for(int i = 0; i < terrainArraySize; i++)
         {
             for(int j = 0; j < terrainArraySize; j++)
             {    
                 file = file + (j + (i * terrainArraySize));
                 terrainsdataArray[i, j] = (TerrainData) Object.Instantiate(terdata);
                 terrainArray[i, j] = Terrain.CreateTerrainGameObject(terrainsdataArray[i, j]);
                 terrainArray[i, j].transform.Translate((((j) * terRes) + terrainArray[i, j].transform.position.x),
                                                       (terrainArray[i,j].transform.position.y),
                                                       (((i) * terRes) + terrainArray[i, j].transform.position.z),
                                                       Space.World);
                 terrainArray[i, j].GetComponent<Terrain>().basemapDistance = 1000;
                 genTerrainHeightmap(terrainsdataArray[i,j], j, i);
             }
         }



Basically I have an empty terrain asset saved in the resources folder. I load that in ('template') and then go through an a nested for loop, instantiating copies of it that I then change at runtime. It appears to me that the problem is with the saved terrain. A child of that asset is called SplatAlpha0. This is an image with RGBA channels. I'm pretty sure that this is where the splats are saved, and helps to make the baseMap. The issue I believe is that when I use the SetAlphamaps function, it is writing to this one file, but all the terrain objects use this file.

My idea is to create multiple image files, and somehow tell the terrain to use these files rather than the default. If this is not possible, or if there is a better idea someone has, please let me know. The end goal is to make endless terrain, but for initial release, I may need to limit the number of terrain tiles.

texture_issue.png (311.3 kB)
Comment
Add comment · Show 6
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image justin35f · Jan 19, 2013 at 05:24 AM 0
Share

I'm still at a loss on this one, any help or suggestions would be appreciated. I've considered looking into writing custom shaders to handle all terrain textures, but I've never written shaders, so this would be a huge roadblock in development if I need to write my own custom terrain shaders.

avatar image justin35f · Jan 20, 2013 at 11:56 PM 0
Share

Ok, I've been looking into this one further, and believe that I've at least deter$$anonymous$$ed the initial problem. I'll edit the question so I can include some additional code that I think is involved.

avatar image justin35f · Jan 21, 2013 at 09:07 PM 0
Share

As a workaround I just created several terrain objects manually, then edit those at runtime, as they all have their own SplatAlpha0. Unfortunately this is only a temporary workaround, as it will not allow 'endless' terrain. Any help at all on this one would be greatly appreciated. Thanks!

avatar image Sir Hoder · Jan 23, 2013 at 10:31 PM 0
Share

I've found that I need to manually copy my "prefab" terraindata to a new terraindata for each terrain.

// Hand build our terrain data for each chunk, otherwise all terrain chunks reference the same terraindata unityTerrainChunkData = new TerrainData();

     unityTerrainChunkData.SetDetailResolution(terrainChunkDataPrefab.detailResolution, 8);
     unityTerrainChunkData.heightmapResolution = terrainChunkDataPrefab.heightmapResolution;
     unityTerrainChunkData.alphamapResolution = terrainChunkDataPrefab.alphamapResolution;
     unityTerrainChunkData.base$$anonymous$$apResolution = terrainChunkDataPrefab.base$$anonymous$$apResolution;
     unityTerrainChunkData.size = terrainChunkDataPrefab.size;
     
     // Copy texture assignments
     unityTerrainChunkData.splatPrototypes = terrainChunkDataPrefab.splatPrototypes;
     
     // Copy Tree prototypes
     unityTerrainChunkData.treePrototypes = terrainChunkDataPrefab.treePrototypes;
     //unityTerrainChunkData.treeInstances = terrainChunkDataPrefab.treeInstances;

     // Copy detail prototypes
     unityTerrainChunkData.detailPrototypes = terrainChunkDataPrefab.detailPrototypes;

// Create the new terrain using the new terraindata unityTerrainChunk = Terrain.CreateTerrainGameObject(unityTerrainChunkData).GetComponent();

avatar image justin35f · Jan 24, 2013 at 12:11 AM 0
Share

This is only partially true. You can create multiple terrains with different height values all based off of one Terrain object. Unfortunately, I've found, when it comes to the textures, all the terrains will use the same SplatAlpha0 image. Unless there is someway to force the terrain to use a different alphamap...

Show more comments

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by Logopolis · Mar 03, 2015 at 09:11 AM

I just faced this same problem, and while this question was asked long ago, I thought I'd post how I solved it here in case anyone else runs into the same problem.

Instantiating a new TerrainData wasn't enough, in my case. Doing that allowed me to set different height values for the different domains, but they still all used the same splat maps. To have them use different splat maps, I had to create an individual SplatPrototypes array for each individual TerrainData, and fill it with the SplatPrototype textures. Here's the code that I wrote to do this:

             terrainPatches[x,z] = (Terrain) Instantiate(terrainPrefab, new Vector3(0, 0, 0), Quaternion.identity);
             
             terrainPatches[x,z].terrainData = new TerrainData();
             terrainPatches[x,z].terrainData.heightmapResolution = 129;
             terrainPatches[x,z].terrainData.size = new Vector3(200,80,200);
             terrainPatches[x,z].terrainData.alphamapResolution = 128;
             terrainPatches[x,z].terrainData.baseMapResolution = 256;
             terrainPatches[x,z].terrainData.SetDetailResolution(256, 8);
             SplatPrototype[] splatPrototypes = new SplatPrototype[10];
             for (int i = 0; i < 10; i++) {
                 splatPrototypes[i] = new SplatPrototype();
                 splatPrototypes[i].tileOffset = new Vector2(0,0);
                 splatPrototypes[i].tileSize = new Vector2(20,20);
                 switch (i) {
                 case 0: splatPrototypes[i].texture = terrainTexture0; splatPrototypes[i].normalMap = rockNormalMap; break;
                 case 1: splatPrototypes[i].texture = terrainTexture1; break;
                 case 2: splatPrototypes[i].texture = terrainTexture2; break;
                 case 3: splatPrototypes[i].texture = terrainTexture3; splatPrototypes[i].normalMap = grassNormalMap; break;
                 case 4: splatPrototypes[i].texture = terrainTexture4; splatPrototypes[i].normalMap = rockNormalMap; break;
                 case 5: splatPrototypes[i].texture = terrainTexture5; splatPrototypes[i].normalMap = rockNormalMap; break;
                 case 6: splatPrototypes[i].texture = terrainTexture6; break;
                 case 7: splatPrototypes[i].texture = terrainTexture7; break;
                 case 8: splatPrototypes[i].texture = terrainTexture8; break;
                 case 9: splatPrototypes[i].texture = terrainTexture9; break;
                 }
             }
             terrainPatches[x,z].terrainData.splatPrototypes = splatPrototypes;

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

12 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Generate Alpha Map Procedurally... 1 Answer

A question for someone who understands alphamaps. 0 Answers

Terrain texture low quality 0 Answers

Blob Shadow and Trees Using Terrain Cause Issues 0 Answers

create terrain using script 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges