Find position of nearest tree.

Hello

When using this function

 Vector3 findResource()
    {
        GameObject[] Array = new GameObject[0];
        if(Equipment == jobs.Woodsman)
        {
        //here we're trying to get the wood.
            Array = GameObject.FindGameObjectsWithTag ("Wood");
        }
        else if(Equipment == jobs.Miner)
        {
            Array = GameObject.FindGameObjectsWithTag ("Stone");
        }
        if (Array.Length > 0) {
            GameObject Nearest = Array[0];
            foreach (GameObject Location in Array) {
                if (Vector3.Distance (Location.transform.position, this.gameObject.transform.position) < Vector3.Distance (Nearest.transform.position, this.gameObject.transform.position)) {
                    Nearest = Location;
                }
            }
            return Nearest.transform.position;
        }
        else
        {
            return Vector3.zero;
        }
    }

The character doesn’t find wood. My question is how to make the character to find the nearest tree and. I need a way to find the nearest terrain tree.

need this answered also

GameObject[ ] Array=new GameObject[0];

You’re creating an array with no size. Try something like GameObject[ ] Array=newGameObject[100]; where 100 = maximum number of trees. Or better yet, include System.Collections.Generic and use a List instead (dynamic memory).

Also, in the future it’s best to describe the context of the script, and the output (any errors, what’s happening) then simply “The character doesn’t find wood.”

the script works for gameObjects with tag “Wood” but all the trees are terrain objects so it finds nothing, how can we find the nearest terrainTreeObject

https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=unity treeinstance

Last url (answers.unity3d.com) isn’t exactly what you want, but the answer to the original post shows an example of the TerrainData.treeInstances array in action. I think this should be what you’re looking for.

if(Equipment == jobs.Woodsman)
        {
            Terrain terrain = Terrain.activeTerrain;
            TreeInstance[] trees = terrain.terrainData.treeInstances;
            if(trees.Length > 0)
            {
                TreeInstance Nearest = trees[0];
                foreach (TreeInstance Location in trees) {
                    if (Vector3.Distance (Location.position, this.gameObject.transform.position) < Vector3.Distance (Nearest.position, this.gameObject.transform.position)) {
                        Nearest = Location;
                    }
                }
                Debug.Log (""+Nearest.position);
                return Nearest.position;
            }
        }

I am trying to do the following and am not getting a usable vector 3

Well, what is it giving you? In future posts, also post what the code is doing now, not just “it’s not working”, it makes my trying to help you more difficult.

First, in line 9 you use Location.position and Nearest.position although both Location/Nearest are of type TreeInstance, not Transform. While TreeInstance may contain a member ‘position’, I can’t be sure as the documentation on this object from Unity is incomplete. Maybe try Location.transform.position and Nearest.transform.position instead.

Have you tried just doing:

Terrain terrain = Terrain.activeTerrain;
TreeInstace[] trees = terrain.terrainData.treeInstances;

foreach( TreeInstance tree in trees )
   print( tree.transform.position );

or

Terrain terrain = Terrain.activeTerrain;
TreeInstace[] trees = terrain.terrainData.treeInstances;

print( trees.Length );

To see if there is any data in the array? Just a couple things to try, as again, I don’t know what the code is actually outputting (is the error semantic/syntactical).

tree.transform.position
is not a thing, it must be tree.position and it doesn’t really return a position

All of the coords are (0.6, 0.0, 0.8) something like this
so I think I need to convert terrain space to game space

Still isn’t working, I have this test class and it suffers to the same issue

using UnityEngine;
using System.Collections;

public class treefind : MonoBehaviour {

    // Use this for initialization
    void Start () {
            Terrain terrain = Terrain.activeTerrain;
            TerrainData data = terrain.terrainData;
            TreeInstance[] trees = data.treeInstances;
            if(trees.Length > 0)
            {
                TreeInstance Nearest = trees[0];
                float width = (float)data.heightmapWidth;
                float height = (float)data.heightmapHeight;
                Vector3 NearPosition = new Vector3(Nearest.position.x * width, Nearest.position.y, Nearest.position.z * height);
                foreach (TreeInstance Location in trees) {
                    Vector3 position = new Vector3(Location.position.x * width, Location.position.y, Location.position.z * height);
                    if (Vector3.Distance (position, this.gameObject.transform.position) < Vector3.Distance (NearPosition, this.gameObject.transform.position)) {
                        Nearest = Location;
                        NearPosition = position;
                    }
                }
                NearPosition.y = terrain.SampleHeight(NearPosition);
                Debug.Log(NearPosition);
                GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
                cube.transform.position = NearPosition;
            }
    }
}

My first thought was try this:

for your width and height, doc says these are in world units. Good idea on the test class though, I like! Would have done it the same way.

the cube is appearing in seemingly random locations though something is wrong here

Thanks so much for the help
for anyone who needs this answer in the future here is the fixed class with line 16 and 18 holding the answer

using UnityEngine;
using System.Collections;

public class treefind : MonoBehaviour {

    // Use this for initialization
    void Start () {
            Terrain terrain = Terrain.activeTerrain;
            TerrainData data = terrain.terrainData;
            TreeInstance[] trees = data.treeInstances;
            if(trees.Length > 0)
            {
                TreeInstance Nearest = trees[0];
                float width = (float)data.heightmapWidth;
                float height = (float)data.heightmapHeight;
                Vector3 NearPosition = Vector3.Scale(Nearest.position, data.size) + terrain.transform.position;
                foreach (TreeInstance Location in trees) {
                    Vector3 position = Vector3.Scale(Location.position, data.size) + terrain.transform.position;
                    if (Vector3.Distance (position, this.gameObject.transform.position) < Vector3.Distance (NearPosition, this.gameObject.transform.position)) {
                        Nearest = Location;
                        NearPosition = position;
                    }
                }
                NearPosition.y = terrain.SampleHeight(NearPosition);
                Debug.Log(NearPosition);
                GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
                cube.transform.position = NearPosition;
            }
    }
}
3 Likes

Awesome! Glad you got it working. And no problem.