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 /
  • Help Room /
avatar image
0
Question by DehLeprechaun · Nov 21, 2020 at 06:21 AM · scripting problemterraineditor-scripting

Custom Object2Terrain script creates "curtains" on the edges.

Howdy,

I'm working on a custom version of the Object2Terrain.cs script that's posted on the unify wiki. I've got a large number of terrain chunks I want to generate, so I'm adjusting it to accept a parent object and make a terrain object for each child of that object. However, both my version and the original create these strange artifacts at the edges of the terrain I want to generate.

alt text

I've attempted adjusting the bounds that determines where the rays get cast from, but that hasn't fixed the issue. My only guess is that I'm somehow running into a floating point precision issue and the rays are being cast off the side of the mesh, which is why I tried to shrink that box just a little so it would grab the height from just inside the bounds of the mesh. The meshes are only 250 sq. m so I'm not sure how correct this is.

Could anyone help me figure out how to prevent this?

 public class Objects2Terrain : EditorWindow
 {
     [MenuItem("Terrain/Objects to Terrain", false, 2002)]
     static void OpenWindow()
     {
         EditorWindow.GetWindow<Objects2Terrain>();
     }
 
     private string PrefabDataAddress = "Assets/Terrain/Prefabs/";
     private string TerrainDataAddress = "Assets/Terrain/Prefabs/TerrainData/";
     private Object worldMap;
     private int TerrainResolution = 512;
 
     private float ChunkProgress;
 
     private void OnGUI()
     {
         PrefabDataAddress = EditorGUILayout.TextField("PrefabDataAddress", PrefabDataAddress);
         TerrainDataAddress = EditorGUILayout.TextField("Terrain Data Address", TerrainDataAddress);
 
         worldMap = EditorGUILayout.ObjectField(worldMap, typeof(GameObject), true);
         TerrainResolution = EditorGUILayout.IntField("Terrain Resolution", TerrainResolution );
 
         EditorGUILayout.HelpBox("explanation text here.", MessageType.Info);
 
         if (GUILayout.Button("Make Terrains"))
         {
             float start = Time.realtimeSinceStartup;
 
             List<GameObject> Chunks = MakeTerrainObjects((GameObject)worldMap, TerrainResolution, TerrainDataAddress);
 
             Debug.Log("Terrain Time: " + (Time.realtimeSinceStartup - start) + " ms");
         }
     }
 
     List<GameObject> MakeTerrainObjects(GameObject ParentObject, int resolution, string TerrainAddress)
     {
         List<GameObject> Chunks = new List<GameObject>();
         int childCount = ParentObject.transform.childCount;
         
         ChunkProgress = ((1/childCount));
         
         for (int i = 0; i < childCount; i++)
         {
             GameObject child = ParentObject.transform.GetChild(i).gameObject;
             string ChunkName = child.name;
             GameObject Chunk = CreateTerrain(child, resolution, TerrainAddress);
 
             Chunk.name = ChunkName;
             MeshCollider collider = child.AddComponent<MeshCollider>();
             Bounds bounds = collider.bounds;
             DestroyImmediate(collider);
             Chunk.transform.position = child.transform.position - new Vector3(bounds.extents.x, 
                 child.transform.position.y - bounds.min.y, bounds.extents.z);
 
             Chunks.Add(Chunk);
 
             ChunkProgress = ((i + 1) / childCount);
             //Debug.Log(ChunkProgress);
         }
 
         return Chunks;
     }
 
     delegate void CleanUp();
 
     GameObject CreateTerrain(GameObject meshObject, int resolution, string Address)
     {
         ShowProgressBar(0.01f, ChunkProgress);
 
         TerrainData terrain = new TerrainData();
         terrain.heightmapResolution = resolution;
         GameObject terrainObject = Terrain.CreateTerrainGameObject(terrain);
 
         //Set TerrainObject name
         string oName = meshObject.name;
         terrainObject.name = oName;
 
         Undo.RegisterCreatedObjectUndo(terrainObject, "Object to Terrain");
 
         MeshCollider collider = meshObject.GetComponent<MeshCollider>();
         CleanUp cleanUp = null;
 
         //Add a collider to the source object if it doesn't exist
         //needed for raycasting
         if (!collider)
         {
             collider = meshObject.AddComponent<MeshCollider>();
             cleanUp = () => DestroyImmediate(collider);
         }
 
         Bounds bounds = collider.bounds;
         terrain.size = collider.bounds.size;// + new Vector3(-0.0001f, 0f, -0.0001f);

         //Adjust bounds size to attempt to fix curtain
         bounds.size = new Vector3(terrain.size.x - 0.0002f, collider.bounds.size.y, terrain.size.z - 0.0002f);
 
         // Do raycasting samples over the object to see what terrain heights should be
         float[,] heights = new float[terrain.heightmapResolution, terrain.heightmapResolution];
         Ray ray = new Ray(new Vector3(bounds.min.x, bounds.max.y + bounds.size.y, bounds.min.z), -Vector3.up);
         RaycastHit hit = new RaycastHit();
         float meshHeightInverse = 1 / bounds.size.y;
         Vector3 rayOrigin = ray.origin;
 
         Vector2 stepXZ = new Vector2(bounds.size.x / resolution, bounds.size.z / resolution);
 
         for (int zCount = 0; zCount < terrain.heightmapResolution; zCount++)
         {
             ShowProgressBar((zCount/ terrain.heightmapResolution), ChunkProgress);
 
             for (int xCount = 0; xCount < terrain.heightmapResolution; xCount++)
             {
                 float height = 0;
 
                 if (collider.Raycast(ray, out hit, bounds.size.y * 3))
                 {
 
                     height = (hit.point.y - bounds.min.y) * meshHeightInverse;
 
                     //clamp
                     if (height < 0)
                     {
                         height = 0;
                     }
                 }
 
                     heights[zCount, xCount] = height;
                     rayOrigin.x += stepXZ[0];
                     ray.origin = rayOrigin;
             }
 
                 rayOrigin.z += stepXZ[1];
                 rayOrigin.x = bounds.min.x;
                 ray.origin = rayOrigin;
         }
 
         terrain.SetHeights(0, 0, heights);
 
         //Create asset file
         string fName = Address + oName + ".asset";
         string[] searchin = new string[1];
         searchin[0] = TerrainDataAddress.Remove(TerrainDataAddress.Length - 1);
         //Debug.Log("looking in " + searchin[0]);
         var existingFile = AssetDatabase.FindAssets(fName, searchin);
         if (existingFile.Length > 0)
         {
             Debug.LogWarning("The file already exists @ " + existingFile[0]);
             string existingaddress = AssetDatabase.GUIDToAssetPath(existingFile[0]);
             AssetDatabase.DeleteAsset(existingaddress);
         }
         AssetDatabase.CreateAsset(terrain, fName);
 
         EditorUtility.ClearProgressBar();
 
         if (cleanUp != null)
         {
             cleanUp();
         }
 
         return terrainObject;
     }


capture.png (158.9 kB)
Comment
Add comment
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

0 Replies

· Add your reply
  • Sort: 

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

126 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image 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

How can I add functions via a scriptswizzard variable? 0 Answers

Editing generic list through editorwindow 0 Answers

unity run editor function everytime I save a script 0 Answers

EditorObjExporter.cs script saves outside correct folder 0 Answers

Incremental terrain height increase limited by float size 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