Einheit: Wie werden programmatische Änderungen auf den Terrain SplatPrototype angewendet?


8

Ich habe ein Skript, zu dem ich ein Terrain-Objekt hinzufüge (ich ziehe das Terrain per Drag & Drop in das öffentliche Terrain-Feld).

Das Terrain ist bereits in Unity für 2 PaintTextures eingerichtet: 1 ist ein Quadrat (so eingerichtet, dass es ein Schachbrettmuster bildet) und das zweite ist ein Grasbild:

Unity-Screenshot

Außerdem wird die Zielstärke der ersten PaintTexture verringert, sodass das Schachbrettmuster auch einen Teil des darunter liegenden Grases freigibt.

Jetzt möchte ich zur Laufzeit die Kachelgröße der ersten PaintTexture ändern, dh je nach Laufzeitbedingungen mehr oder weniger Prüfer haben. Ich habe die Dokumentation von Unity durchgesehen und festgestellt, dass Sie über das Terrain.terrainData.SplatPrototypeArray verfügen, mit dem Sie dies ändern können. Es gibt auch eine RefreshPrototypes()Methode für das terrainDataObjekt und eine Flush()Methode für das TerrainObjekt. Also habe ich ein Skript wie dieses erstellt:

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();
    }

//...

Das Problem ist, dass nichts geändert wird und die Checker-Map nicht neu gekachelt wird. Die Konsolenausgaben sagen mir korrekt, dass ich das Terrain-Objekt mit dem richtigen Namen habe, dass es die richtige Anzahl von Splat-Prototypen hat und dass ich die tileSize für das SplatPrototype-Objekt entsprechend der richtigen Textur ändere. Es sagt mir auch, dass sich der Wert geändert hat. In der tatsächlichen grafischen Ansicht wird jedoch nichts aktualisiert.

Also bitte, was fehlt mir?


Wenn Sie einen Cusom-Shader haben und ein blaues Linienraster auf der Karte mit unterschiedlichen Werten erstellen möchten, ist es am billigsten, dies im Shader zu tun ... blaue Linien sind: rund (frac (x * .1) ... Ich werde es in eine Antwort
schreiben

Antworten:


1

Anscheinend haben Sie vergessen, die Splat-Textur wieder zuzuweisen:

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();
}

//...

Was Sie übrigens so hätten tun können:

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

(Und dann aktualisieren, aber ich bin nicht einmal sicher, ob es in diesem Zustand benötigt wird)

EDIT:

Es gibt einige Parameter in Objekten, auf die nicht verwiesen werden kann, und ich glaube

splatPrototype.tileSize

ist einer von ihnen, wenn Sie dies tun:

SplatPrototype aStarCellSplat = splatPrototypes[0];

dann ist aStarCellSplat ein Klon von splatPrototypes [0], verweist jedoch nicht darauf. Manchmal ist das Klonen, um den Anfangswert zu erhalten und daraus zu iterieren, gut, insbesondere wenn Sie komplexe Strukturen ändern. In diesem Fall ist ein einfacher Parameteraufruf jedoch einfacher.

Und behalten Sie den Überblick über Ihre Klone, wenn Sie den Klon vergessen, vergessen Sie nicht, ihn zurückzuweisen


-1

Um blaue Linien über den Shader zu erstellen, müssen Sie die Textur_uv in der Oberflächenfunktion oder in der Frakt-Funktion haben ...

Um blau / graue Gitterlinien in Shaderlab zu erstellen, müssen Sie dem Shader innerhalb der Surf-Funktion insgesamt 4-5 Linien hinzufügen:

xline = decken (frac (uv.x * .1) -. 75); yline = gleich für y

Gitter = max (xline, yline);

o.albedo.blueval = Gitter.

Dann können Sie Ihre Rastergröße ändern, indem Sie 1 Aufruf an den Shader senden, um den Shader-Wert zu ändern. .l erstellt ein 10-Meter-Raster. Ändern Sie diesen Wert in eine angepasste Rastergröße. .75 erstellt ein Raster 3/4 des Bildschirmbereichs .

Passen Sie dann die Farbe an und fügen Sie die Mathematik hinzu, die in der vorherigen Version / Splatmap verwendet wurde.


Dies liefert zwar einige nützliche Informationen, beantwortet jedoch nicht die direkt gestellte Frage. Wenn der OP tatsächlich wissen wollte, wie dies über den Shader zu tun ist, hätte er gefragt.
Pip
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.