Unity: comment appliquer des modifications programmatiques au Terrain SplatPrototype?


8

J'ai un script auquel j'ajoute un objet Terrain (je fais glisser et déposez le terrain dans le champ Terrain public).

Le Terrain est déjà configuré dans Unity pour avoir 2 PaintTextures: 1 est un carré (configuré avec une taille de tuile de sorte qu'il forme un motif à damier) et le 2ème est une image d'herbe:

Capture d'écran de Unity

La force cible du premier PaintTexture est également abaissée de sorte que le motif en damier révèle également une partie de l'herbe en dessous.

Maintenant, je veux, au moment de l'exécution, changer la taille des carreaux du premier PaintTexture, c'est-à-dire avoir plus ou moins de vérificateurs en fonction des différentes conditions d'exécution. J'ai parcouru la documentation d'Unity et j'ai vu que vous disposiez du Terrain.terrainData.SplatPrototypetableau qui vous permet de changer cela. Il y a aussi une RefreshPrototypes()méthode sur l' terrainDataobjet et une Flush()méthode sur l' Terrainobjet. J'ai donc fait un script comme celui-ci:

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

//...

Le problème est que rien n'est changé, la carte du vérificateur n'est pas re-carrelée. Les sorties de la console me disent correctement que j'ai l'objet Terrain avec le bon nom, qu'il a le bon nombre de prototypes splat et que je modifie le tileSize sur l'objet SplatPrototype correspondant à la bonne texture. Il me dit également que la valeur a changé. Mais rien n'est mis à jour dans la vue graphique réelle.

Alors, que me manque-t-il?


si vous avez un shader personnalisé et que vous voulez faire une grille de lignes bleues sur la carte avec des valeurs différentes, le moyen le moins cher est de le faire dans le shader ... les lignes bleues sont: rondes (frac (x * .1) ... diable le mettre dans une réponse
com.prehensible

Réponses:


1

Il semble que vous ayez oublié de réaffecter la texture 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();
}

//...

Ce que vous auriez pu faire de cette façon:

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

(Et puis rafraîchir mais je ne suis même pas sûr que cela soit nécessaire dans cet état)

ÉDITER :

Il y a des paramètres dans les objets qui ne peuvent pas être référencés et je crois

splatPrototype.tileSize

est l'un d'eux, donc si vous le faites:

SplatPrototype aStarCellSplat = splatPrototypes[0];

alors aStarCellSplat est un clone de splatPrototypes [0] mais ne le référence pas. Parfois, le clonage pour obtenir la valeur initiale et en itérer est bon, surtout lorsque vous modifiez une structure complexe, mais dans ce cas, un simple appel de paramètre est plus facile.

Et gardez une trace de vos clones, si vous clonez n'oubliez pas de les attribuer en retour


-1

pour faire des lignes bleues via un shader, vous devez avoir la texture_uv dans la fonction de surface, ou dans la fonction fract ...

pour faire des lignes de grille bleu / gris dans shaderlab, vous devez ajouter un total de 4-5 lignes au shader, à l'intérieur de la fonction de surf:

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

grille = max (xline, yline);

o.albedo.blueval = grille.

alors vous pouvez changer la taille de votre grille en utilisant 1 appel au shader, pour changer la valeur du shader, .l fait une grille de 10 mètres, changez cette valeur pour ajuster la taille de la grille, .75 fait une grille 3/4 de la zone de l'écran .

puis ajustez la couleur en ajoutant des mathématiques à la même que celle utilisée dans la version précédente / splatmap.


Tout en fournissant des informations utiles, cela ne répond pas réellement à la question directement posée. Si le PO voulait réellement savoir comment faire cela via le shader, il aurait demandé.
Pip
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.