Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have a script to which I add a Terrain object (I drag and drop the terrain in the public Terrain field).

The Terrain is already setup in Unity to have 2 PaintTextures: 1 is a Square (set up with a tile size so that it forms a checkered pattern) and the 2nd one is a grass image:

Unity screenshot

Also the Target Strength of the first PaintTexture is lowered so that the checkered pattern also reveals some of the grass underneath.

Now I want, at run time, to change the Tile Size of the first PaintTexture, i.e. have more or less checkers depending on various run time conditions. I've looked through Unity's documentation and I've seen you have the Terrain.terrainData.SplatPrototype array which allows you to change this. Also there's a RefreshPrototypes() method on the terrainData object and a Flush() method on the Terrain object. So I made a script like this:

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

//...

Problem is, nothing gets changed, the checker map is not re-tiled. The console outputs correctly tell me that I've got the Terrain object with the right name, that it has the right number of splat prototypes and that I'm modifying the tileSize on the SplatPrototype object corresponding to the right texture. It also tells me the value has changed. But nothing gets updated in the actual graphical view.

So please, what am I missing?

share|improve this question
add comment

1 Answer

It seems you forgot to reassign the Splat texture back :

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

//...

Which by the way you could have done this way :

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

(And then refresh but i'm not even sure it is needed at this state)

EDIT :

There is some parameters in objects which cannot be referenced and i believe

splatPrototype.tileSize

is one of them so if you do :

SplatPrototype aStarCellSplat = splatPrototypes[0];

then aStarCellSplat is a clone of splatPrototypes[0] but does not references it. sometimes cloning to get the initial value and iterate from it is good especially when you modify complex structure, but in this case a simple parameter call is easyer.

And keep track of your clones, if you clone do not forget to assign back

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.