Unidad: ¿cómo aplicar cambios programáticos al Terrain SplatPrototype?


8

Tengo un script al que agrego un objeto Terrain (arrastro y suelto el terreno en el campo público Terrain).

El terreno ya está configurado en Unity para tener 2 PaintTextures: 1 es un cuadrado (configurado con un tamaño de mosaico para que forme un patrón a cuadros) y el segundo es una imagen de hierba:

Captura de pantalla de Unity

También se reduce la fuerza objetivo de la primera PaintTexture para que el patrón a cuadros también revele algo de la hierba debajo.

Ahora quiero, en tiempo de ejecución, cambiar el tamaño de mosaico de la primera PaintTexture, es decir, tener más o menos correctores dependiendo de varias condiciones de tiempo de ejecución. He revisado la documentación de Unity y he visto que tienes la Terrain.terrainData.SplatPrototypematriz que te permite cambiar esto. También hay un RefreshPrototypes()método en el terrainDataobjeto y un Flush()método en el Terrainobjeto. Entonces hice un guión como este:

public class AStarTerrain : MonoBehaviour {

    public int aStarCellColumns, aStarCellRows; 

    public GameObject aStarCellHighlightPrefab;
    public GameObject aStarPathMarkerPrefab;
    public GameObject utilityRobotPrefab;
    public Terrain aStarTerrain;

    void Start () {
            //I've also tried NOT drag and dropping the Terrain on the public field 
            //and instead just using the commented line below, but I get the same results
        //aStarTerrain = this.GetComponents<Terrain>()[0];
        Debug.Log ("Got terrain "+aStarTerrain.name);

        SplatPrototype[] splatPrototypes = aStarTerrain.terrainData.splatPrototypes;
        Debug.Log("Terrain has "+splatPrototypes.Length+" splat prototypes");
        SplatPrototype aStarCellSplat = splatPrototypes[0];
        Debug.Log("Re-tyling splat prototype "+aStarCellSplat.texture.name);
        aStarCellSplat.tileSize = new Vector2(2000,2000);
        Debug.Log("Tyling is now "+aStarCellSplat.tileSize.x+"/"+aStarCellSplat.tileSize.y);
        aStarTerrain.terrainData.RefreshPrototypes();
        aStarTerrain.Flush();
    }

//...

El problema es que nada cambia, el mapa del corrector no se vuelve a colocar en mosaico. Las salidas de la consola me dicen correctamente que tengo el objeto Terrain con el nombre correcto, que tiene el número correcto de prototipos splat y que estoy modificando el tileSize en el objeto SplatPrototype correspondiente a la textura correcta. También me dice que el valor ha cambiado. Pero nada se actualiza en la vista gráfica real.

Entonces, ¿qué me estoy perdiendo?


Si tiene un sombreador personalizado y desea hacer una cuadrícula de líneas azules en el mapa con diferentes valores, la forma más económica es hacerlo en el sombreador ... las líneas azules son: redondo (frac (x * .1) ... diablos mal ponerlo en una respuesta
com.prehensible

Respuestas:


1

Parece que olvidaste reasignar la textura Splat:

public class AStarTerrain : MonoBehaviour {

public int aStarCellColumns, aStarCellRows; 

public GameObject aStarCellHighlightPrefab;
public GameObject aStarPathMarkerPrefab;
public GameObject utilityRobotPrefab;
public Terrain aStarTerrain;

void Start () {
        //I've also tried NOT drag and dropping the Terrain on the public field 
        //and instead just using the commented line below, but I get the same results
    //aStarTerrain = this.GetComponents<Terrain>()[0];
    Debug.Log ("Got terrain "+aStarTerrain.name);

    SplatPrototype[] splatPrototypes = aStarTerrain.terrainData.splatPrototypes;
    Debug.Log("Terrain has "+splatPrototypes.Length+" splat prototypes");
    SplatPrototype aStarCellSplat = splatPrototypes[0];
    Debug.Log("Re-tyling splat prototype "+aStarCellSplat.texture.name);
    aStarCellSplat.tileSize = new Vector2(2000,2000);
    splatPrototypes[0] = aStarCellSplat; // <- here
    Debug.Log("Tyling is now "+aStarCellSplat.tileSize.x+"/"+aStarCellSplat.tileSize.y);
    aStarTerrain.terrainData.RefreshPrototypes();
    aStarTerrain.Flush();
}

//...

Lo cual por cierto podría haber hecho de esta manera:

splatPrototypes[0].tileSize = new Vector2(2000,2000); //No referencing issue this way

(Y luego actualizar, pero ni siquiera estoy seguro de que sea necesario en este estado)

EDITAR:

Hay algunos parámetros en los objetos que no pueden ser referenciados y creo

splatPrototype.tileSize

es uno de ellos, así que si lo haces:

SplatPrototype aStarCellSplat = splatPrototypes[0];

entonces aStarCellSplat es un clon de splatPrototypes [0] pero no hace referencia a él. a veces, la clonación para obtener el valor inicial e iterar a partir de él es bueno, especialmente cuando modifica una estructura compleja, pero en este caso una llamada de parámetro simple es más fácil.

Y haga un seguimiento de sus clones, si clona no olvide asignar de nuevo


-1

para hacer líneas azules a través del sombreador, necesitas tener texture_uv en la función de superficie, o en la función de fracturas ...

para hacer líneas de cuadrícula azul / gris en shaderlab, debe agregar un total de 4-5 líneas al sombreador, dentro de la función de navegación:

xline = ceil (frac (uv.x * .1) -. 75); yline = igual para y

grid = max (xline, yline);

o.albedo.blueval = cuadrícula.

entonces puede cambiar el tamaño de su cuadrícula usando 1 llamada al sombreador, para cambiar el valor del sombreador, .l crea una cuadrícula de 10 metros, cambie ese valor para ajustar el tamaño de la cuadrícula, .75 hace una cuadrícula 3/4 del área de la pantalla .

luego modifique el color agregando matemáticas al mismo que se usó en la versión anterior / splatmap.


Si bien proporciona información útil, en realidad esto no responde a la pregunta formulada directamente. Si el OP realmente quisiera saber cómo hacer esto a través del sombreador, lo habría preguntado.
Pip
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.