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?

Shivan Dragon
fuente
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

Géry Arduino
fuente
-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.

comprensible
fuente
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