Unity engine, using kd tree to search for nearest transform is not returning any value

140 Views Asked by At

I'm trying to build an A.I. script that can find cover by hiding behind nearby trees placed on a piece of terrain. Currently, I have a function that creates a kd tree using a script I found online (link: https://gist.github.com/ditzel/194ec800053ce7083b73faa1be9101b0) and fills it with all the correct transforms. However, for some reason the function nearestCover(); does not return anything. It was working perfectly fine in an earlier version of the exact same script where I simply searched for the different empty game objects using GameObject.Find via for loop with pre made nodes around the map.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class coverScript : MonoBehaviour
{
    [SerializeField] KdTree<Transform> coverTree = new KdTree<Transform>();

    [SerializeField] int coverCount;

    private void addToCover(Transform newPoint)//simply taking the newly created game object and adding its transform to the kd tree
    {
        coverTree.Add(newPoint);
        newPoint.parent = transform;
    }

    private void spawnTrees()
    {
        var terrain = Terrain.activeTerrain;//getting the current terrain and trees placed on it
        var trees = terrain.terrainData.treeInstances;
        var count = terrain.terrainData.treeInstanceCount;

        for (int i = 0; i < count; i++)
        {
            TreeInstance tree = trees[i];//getting the tree instances one by one
            var treeInstancePos = tree.position;
            var localPos = new Vector3(treeInstancePos.x * terrain.terrainData.size.x, treeInstancePos.y * terrain.terrainData.size.y, treeInstancePos.z * terrain.terrainData.size.z);
            var worldPos = Terrain.activeTerrain.transform.TransformPoint(localPos);
            GameObject newCoverPoint = new GameObject("tree cover point (" + i + ")");
            newCoverPoint.transform.position = worldPos;//this set of math I had to do does in fact return the correct locations of the individual trees as the gameobjects appear correctly in place in my scene
            addToCover(newCoverPoint.transform);
        }
    }

    public Vector3 nearestCover(Vector3 targ)
    {
        Vector3 newTarg = coverTree.FindClosest(targ).position;
        
        return newTarg;
    }

    private void Start()
    {
        spawnTrees();
        Debug.Log(coverTree.Count);
    }
}

Debug.Log(coverTree.Count); is working completely fine, and the game objects are being created with the correct names and everything in the exact location I want them to, yet for some reason now trying to search for the nearest one via FindClosest does not seem to return anything whenever it is called, yet I am also not receiving any error message.

This is incredibly frustrating for me, as earlier on the code worked perfectly fine and my navmeshagent was able to dash from cover to cover engaging me between points. Can anyone tell me if there is maybe something wrong with the script I found or maybe if I am making some incredibly simple oversight?

I've been stuck on this going back and forth between potential problems for a couple hours today so I would really appreciate if someone could show me what I'm doing wrong.

1

There are 1 best solutions below

0
Marcus On

Resolved. In the end the issue was that I needed to first spawn all the tree nodes and then call a second function where I would add them all to the kd tree.

Solution here:

[SerializeField] KdTree<Transform> testTree = new KdTree<Transform>();

[SerializeField] int coverCount;

[SerializeField] bool treesDone;

[SerializeField] bool coverDone;

int count;

private void spawnTreeNodes()
{
    var terrain = Terrain.activeTerrain;//getting the current terrain and trees placed on it
    var trees = terrain.terrainData.treeInstances;
    count = terrain.terrainData.treeInstanceCount;

    for (int i = 0; i < count; i++)
    {
        TreeInstance tree = trees[i];
        var treeInstancePos = tree.position;
        var localPos = new Vector3(treeInstancePos.x * terrain.terrainData.size.x, treeInstancePos.y * terrain.terrainData.size.y, treeInstancePos.z * terrain.terrainData.size.z);
        var worldPos = Terrain.activeTerrain.transform.TransformPoint(localPos);
        GameObject newCoverPoint = new GameObject("treeCoverPoint (" + i + ")");
        newCoverPoint.transform.position = worldPos;
        newCoverPoint.transform.parent = transform;
    }
    treesDone = true;
}

private void addToTree()
{
    for(int i = 0; i < count; i++)
    {
        testTree.Add(GameObject.Find("treeCoverPoint (" + i + ")").transform);
    }
}

public Vector3 nearestCover(Vector3 targ)
{
    Vector3 newTarg = testTree.FindClosest(targ).position;

    return newTarg;
}

private void Start()
{
    spawnTreeNodes();
}

private void Update()
{
    if (treesDone)
    {
        if (!coverDone)
        {
            coverDone = true;
            addToTree();
        }
    }
}