Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question How to check tree distance and how to remove trees

Discussion in 'World Building' started by Rowlan, Apr 2, 2022.

  1. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    3,819
    I'd like to create my own editor for painting terrain details. What's the way to check the distance for overlapping and how can you remove trees?

    Neither getting the tree distance nor removal of trees are publicly accessible via code:

    CheckTreeDistance:
    Code (CSharp):
    1. namespace UnityEditor
    2. {
    3.     [NativeHeader("Editor/Mono/TerrainEditor/TerrainInspectorUtil.bindings.h")]
    4.     internal static class TerrainInspectorUtil
    5.     {
    6.         ...
    7.         public static extern bool CheckTreeDistance(TerrainData terrainData, Vector3 position, int prototypeIndex, float distanceBias);
    8.         ...
    9.     }
    10. }
    11.  
    RemoveTrees:
    Code (CSharp):
    1.         [NativeName(k_TreeDatabasePrefix + "RemoveTrees")]
    2.         extern internal int RemoveTrees(Vector2 position, float radius, int prototypeIndex);
    I coded my own by processing the terrainData array content of the trees, but I'd prefer internal mechanisms.
     
  2. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    3,819
    @wyattt_ got some pointers about that? I kinda do it manually now, but still hope there'd be an API for that.

    Looks like this:



    But with a 10000 trees my current solution gets slow when I e. g. want to change the scale of the trees.

    In case anyone has use for the code:

    https://github.com/Roland09/PrefabP...tions/UnityTerrain/UnityTerrainTreeManager.cs

    I have a slow and a fast method. The slow one iterates in a for-loop. The fast one uses linq & parallel like this, eg getting all trees within the brush radius:

    Code (CSharp):
    1. int[] prototypeIndexes = terrainData.treeInstances.AsParallel().Select((c, i) => new { TreeInstance = c, Index = i }).Where(x => (localPosition - x.TreeInstance.position).magnitude < localBrushRadius).Select(x => x.Index).ToArray();
    Although I'm not so sure about how much faster it is because of the overhead.
     
  3. Querke

    Querke

    Joined:
    Feb 21, 2013
    Posts:
    54
    Did you figure this out? I'm currently writing my own tree placement tool. And when checking Unity's source code, I quickly found out that the TerrainInspectorUtil code isn't publically accessible.
     
  4. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    1,863
    Checking every distance between every pair of objects would be an O(n^2) problem. If you can batch it into groups, say, only things within each 500 meter sector, you'd save a ton of cycles. The right solution would be something about octrees but that is usually overkill unless you do this weekly.