Search Unity

Easily add many trees to your terrain

Discussion in 'Assets and Asset Store' started by JeffAU, Jan 31, 2014.

  1. JeffAU

    JeffAU

    Joined:
    Mar 22, 2009
    Posts:
    387
    Does anyone know of a Unity Asset (or trick) for importing multiple trees onto a Unity Terrain without having to place them one at a time using the Place Tree terrain tool?

    We do want them imported into the Terrain in the same way as using the Place Tree tool but without the time consuming process of adding them individually with multiple clicks etc.

    Any thoughts?

    Thanks
     
    llnk7 likes this.
  2. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    I am working on a tool to place trees and details procedurally on several occasions such as the underneath texture type, steepness, inbetween certain heights...etc which will be added to my "Aubergines Editor Tools" soon.

    Meanwhile, you can use mass place trees option in the inspector, it does take steepness in consideration(i guess).
     
  3. JeffAU

    JeffAU

    Joined:
    Mar 22, 2009
    Posts:
    387
    That tool does sound great - I don't want to place the trees on the terrain though, just load them into the Place Trees part of the Terrain in the Inspector.
     
  4. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    Oh i see, well then check the TerrainData.treePrototypes and TreePrototype.prefab documents. You can add treeprototypes through scripting.
     
  5. JeffAU

    JeffAU

    Joined:
    Mar 22, 2009
    Posts:
    387
    Ok great - so I need to convert this type of script into an Editor Script which loads a folder full of trees (prefabs) from the Assets folder into the TreePrototypes for the active terrain after a button click. It would be great to be able to hard code the path to the tree folder so no config is required other than having the trees in the correct folder before clicking the button.

    If anyone has a few mins to assist I'd be happy to return the favor with a PayPal payment for your time.

    We would need an editor script which adds an "Add Trees" Menu Item to the Game Object>Create Other menu - when selected it auto loads all trees in a specific folder within the Assets folder into the tree prototypes palette. We don't want them added to the actual terrain in the scene - just in the Terrain/Inspector.

    Although I'd be happy to pay, please feel free to post the code for everyone to use here.

    Please let me know cost before spending too much time incase we need to discuss price.

    Thanks
     
    llnk7 likes this.
  6. JeffAU

    JeffAU

    Joined:
    Mar 22, 2009
    Posts:
    387
    I have an ongoing number of small jobs like this ... if anyone wants to give this small editor script a try ( and receive payment for it ) we could potentially do more work together.
     
  7. llnk7

    llnk7

    Joined:
    Mar 20, 2014
    Posts:
    1
    Hello! I wrote a script that reads the prefabs inside the Assets folder and then places them into the terrain as trees. So you only indicate the folder (which have to be inside the Assets) and that's all, you can use the trees in the terrain. The menu option is in Terrain, and you can clear too the current trees in the editor!

    Here is the code for everyone! Good luck!

    Code (CSharp):
    1. [MenuItem ("Terrain/Add Folder Tree")]
    2.     static void AddFolderTrees()
    3.     {
    4.         string folder = EditorUtility.OpenFolderPanel("Select the folder containing the tree", "Assets/", "");
    5.         if(folder != "")
    6.         {
    7.             if(folder.IndexOf(Application.dataPath) == -1)
    8.             {
    9.                 Debug.LogWarning("The folder must be in this project anywhere inside the Assets folder!");
    10.                 return;
    11.             }
    12.             string[] files = Directory.GetFiles(folder);
    13.             if(files.Length > 0)
    14.             {
    15.                 TerrainData currentTerrainData = Selection.activeGameObject.GetComponent<Terrain>().terrainData;
    16.                 List<TreePrototype> treePrototypesList = new List<TreePrototype>(currentTerrainData.treePrototypes);
    17.                 for(int i = 0; i < files.Length; i++)
    18.                 {
    19.  
    20.                     TreePrototype treePrototype = new TreePrototype();
    21.                     string relativePath = files[i].Substring(files[i].IndexOf("Assets/"));
    22.                     GameObject prefab = Resources.LoadAssetAtPath<GameObject>(relativePath);
    23.                     if(prefab != null)
    24.                     {
    25.                         treePrototype.prefab = prefab;
    26.                         treePrototypesList.Add(treePrototype);
    27.                     }
    28.                 }
    29.                 currentTerrainData.treePrototypes = treePrototypesList.ToArray();
    30.                 Selection.activeGameObject.GetComponent<Terrain>().Flush();
    31.                 currentTerrainData.RefreshPrototypes();
    32.                 EditorUtility.SetDirty(Selection.activeGameObject.GetComponent<Terrain>());
    33.             }
    34.         }
    35.     }
    36.  
    37.     [MenuItem ("Terrain/Clear Tree Editor")]
    38.     static void ClearTreeEditor()
    39.     {
    40.         TerrainData currentTerrainData = Selection.activeGameObject.GetComponent<Terrain>().terrainData;
    41.         currentTerrainData.treePrototypes = null;
    42.         Selection.activeGameObject.GetComponent<Terrain>().Flush();
    43.         currentTerrainData.RefreshPrototypes();
    44.         EditorUtility.SetDirty(Selection.activeGameObject.GetComponent<Terrain>());
    45.     }
    46.  
    47.     [MenuItem ("Terrain/Add Folder Tree", true)]
    48.     static bool ValidateAddFolderTrees()
    49.     {
    50.         if(Selection.activeGameObject == null || Selection.activeGameObject.GetComponent<Terrain>() == null)
    51.         {
    52.             Debug.LogWarning("You must have a Terrain selected to perform this action!");
    53.             return false;
    54.         }
    55.         return true;
    56.     }
    57.  
    58.     [MenuItem ("Terrain/Clear Tree Editor", true)]
    59.     static bool ValidateClearTreeEditor()
    60.     {
    61.         if(Selection.activeGameObject == null || Selection.activeGameObject.GetComponent<Terrain>() == null)
    62.         {
    63.             Debug.LogWarning("You must have a Terrain selected to perform this action!");
    64.             return false;
    65.         }
    66.         return true;
    67.     }
    See you!
     
    Last edited: Aug 27, 2014
  8. ElectricMonk

    ElectricMonk

    Joined:
    Sep 3, 2014
    Posts:
    5
    Thanks this worked great! Just had to import some libraries and it worked like a charm, saved me a few hours of work!
     
    llnk7 likes this.
  9. ccvannorman

    ccvannorman

    Joined:
    Jan 20, 2013
    Posts:
    13
    Works perfectly on Unity 2021 (after "updating" the c# script) Thank you @link7!
     
  10. MichaelEGA

    MichaelEGA

    Joined:
    Oct 11, 2019
    Posts:
    40
    This is great, thanks. I could only figure out how to replace assets not load them from scratch, but this works perfectly.

     
  11. hheimbuerger

    hheimbuerger

    Joined:
    Aug 14, 2017
    Posts:
    1
    Thank you for providing this! I needed this too, and expanded it to also support layers and detail meshes/textures. I also moved the submenu to `Tools > Terrain Folder Tools`.

    Source is here: https://github.com/hheimbuerger/unity-terrain-folder-tools

    Thanks for making this possible, llnk7!
     
    EfremenkovAlex likes this.
  12. EfremenkovAlex

    EfremenkovAlex

    Joined:
    Mar 13, 2017
    Posts:
    4
    Works like a charm! Thanks for sharing!

    llnk7, thanks!