es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Solo generar árboles en terreno plano.

Lo que estoy intentando hacer
Estoy tratando de generar un árbol solo en terreno plano, pero GetSteepness() no está funcionando y GetInterpolatedNormal() tampoco parece estar funcionando.

El problema
Los árboles siempre parecen generarse en lugares donde no quiero, como en colinas muy empinadas, aunque también se generan en terreno plano, preferiría que no se generaran en colinas en absoluto.

También me gustaría eventualmente
usar este método cuando se resuelva para colocar césped solo en terrenos planos,
pero no sé cómo generar césped y no creo que “instantiate” sea bueno en términos de rendimiento. Usaría un césped en forma de cartel por razones de rendimiento.

Lo que he intentado
El sistema de GetInterpolatedNormal no funciona. He intentado jugar con Value.x/y/z y cambiar el Steepness.x/y/z > Value.x/y/z por Steepness.x/y/z < Value.x/y/z

void PopulateTrees(TerrainData terrainData) {
    var ray = new Ray(new Vector3(Random.Range(-100, 100), 1000 f, Random.Range(-100, 100)), -this.transform.up);
    RaycastHit hit;
    if (Physics.Raycast(ray, out hit)) {
        Vector3 terrainSize = Terrain.activeTerrain.terrainData.size;
        Steepness = Terrain.activeTerrain.terrainData.GetInterpolatedNormal(hit.point.x / terrainSize.x, hit.point.y / terrainSize.z);
        if (Steepness.x < Value.x && Steepness.y < Value.y && Steepness.z < Value.z) {
            Instantiate(PineTree, new Vector3(hit.point.x, hit.point.y - .1 f, hit.point.z), transform.rotation = new Quaternion(0, Random.Range(-1000, 1000), 0, 100));
        }
    }
}

}

Método GetSteepness(). No sé qué sistema será más eficiente, de esta manera parece que solo pone árboles en áreas extrañas.

void PopulateTrees(TerrainData terrainData) {
    var ray = new Ray(new Vector3(Random.Range(-100, 100), 1000 f, Random.Range(-100, 100)), -this.transform.up);
    RaycastHit hit;
    if (Physics.Raycast(ray, out hit)) {
        Steepness = terrainData.GetSteepness(hit.point.x, hit.point.z);
        if (Steepness > Value) {
            Instantiate(PineTree, new Vector3(hit.point.x, hit.point.y - .1f, hit.point.z), transform.rotation = new Quaternion(0, Random.Range(-1000, 1000), 0, 100));
        }
    }
}

Esta es una foto del problema

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Solución propuesta

    Parece que el problema está en cómo estás utilizando los métodos GetInterpolatedNormal y GetSteepness. En lugar de verificar la pendiente o la normal interpolada en el punto de generación, deberías verificarlo en el punto más cercano en el terreno. Así es cómo puedes modificar tu método PopulateTrees:

    void PopulateTrees(TerrainData terrainData) {
        // Obtén un punto aleatorio dentro de los límites del terreno
        Vector3 randomPoint = new Vector3(Random.Range(0f, terrainData.size.x), 0f, Random.Range(0f, terrainData.size.z));
        // Obtén el punto más cercano en el terreno al punto aleatorio
        Vector3 nearestPoint = terrainData.GetClosestPoint(randomPoint);
        // Calcula la pendiente en el punto más cercano
        float steepness = terrainData.GetSteepness(nearestPoint.x / terrainData.size.x, nearestPoint.z / terrainData.size.z);
        // Solo genera un árbol si el terreno es lo suficientemente plano
        if (steepness < Valor) {
            Instantiate(PineTree, nearestPoint + Vector3.up * 0.1f, Quaternion.identity);
        }
    }
    

    Esto asegurará que los árboles solo se generen en terrenos planos.

    En cuanto a la generación de césped, podrías utilizar un enfoque similar generando una serie de puntos aleatorios en el terreno y verificando su pendiente para determinar dónde generar el césped. Luego podrías utilizar césped “billboard” por razones de rendimiento. Aquí tienes un ejemplo de cómo podrías modificar el método PopulateTrees para generar césped:

    void PopulateGrass(TerrainData terrainData) {
        // El número de objetos de césped a generar
        int count = 1000;
        // El radio dentro del cual generar césped
        float radius = 20f;
        // Genera puntos aleatorios en el terreno
        for (int i = 0; i < count; i++) {
            Vector3 randomPoint = new Vector3(Random.Range(0f, terrainData.size.x), 0f, Random.Range(0f, terrainData.size.z));
            // Solo genera césped dentro del radio especificado
            if (randomPoint.magnitude > radius) continue;
            // Obtén el punto más cercano en el terreno al punto aleatorio
            Vector3 nearestPoint = terrainData.GetClosestPoint(randomPoint);
            // Calcula la pendiente en el punto más cercano
            float steepness = terrainData.GetSteepness(nearestPoint.x / terrainData.size.x, nearestPoint.z / terrainData.size.z);
            // Solo genera césped si el terreno es lo suficientemente plano
            if (steepness < Valor) {
                // Genera un objeto de césped "billboard"
                Instantiate(GrassObject, nearestPoint + Vector3.up * 0.1f, Quaternion.identity);
            }
        }
    }
    

    Esto generará césped solo en terrenos planos dentro de un radio especificado. Puedes ajustar los parámetros count y radius para controlar cuántos objetos de césped se generan y qué tan denso es el césped.

Comments are closed.