Unity: как применить программные изменения к Terrain SplatPrototype?

8

У меня есть скрипт, к которому я добавляю объект Terrain (я перетаскиваю ландшафт в открытом поле Terrain).

Terrain уже настроен в Unity, чтобы иметь 2 PaintTextures: 1 - квадрат (установлен с размером плитки, чтобы он формировал клетчатый рисунок), а второй - изображение травы:

Скриншот Unity

Также целевая сила первой PaintTexture понижена, так что клетчатый узор также показывает часть травы под ним.

Теперь я хочу, чтобы во время выполнения изменить размер плитки первой PaintTexture, т.е. иметь больше или меньше контролеров в зависимости от различных условий выполнения. Я просмотрел документацию Unity и увидел, что у вас есть Terrain.terrainData.SplatPrototypeмассив, который позволяет вам это изменить. Также есть RefreshPrototypes()метод на terrainDataобъекте и Flush()метод на Terrainобъекте. Поэтому я сделал такой скрипт:

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

//...

Проблема в том, что ничего не меняется, карта проверки не перебирается. Выводы консоли правильно сообщают мне, что у меня есть объект Terrain с правильным именем, что у него правильное количество прототипов splat и что я изменяю tileSize объекта SplatPrototype, соответствующего правильной текстуре. Это также говорит мне, что значение изменилось. Но ничто не обновляется в реальном графическом представлении.

Так что, пожалуйста, чего мне не хватает?

Дракон Шиван
источник
если у вас есть обычный шейдер и вы хотите сделать сетку синих линий на карте с разными значениями, самый дешевый способ - это сделать это в шейдере ... синие линии: round (frac (x * .1) ... черт
побери, вставь

Ответы:

1

Кажется, вы забыли переназначить текстуру 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();
}

//...

Что, кстати, вы могли бы сделать так:

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

(А потом обновить, но я даже не уверен, что это нужно в этом состоянии)

РЕДАКТИРОВАТЬ :

В объектах есть некоторые параметры, на которые нельзя ссылаться, и я верю

splatPrototype.tileSize

является одним из них, так что если вы делаете:

SplatPrototype aStarCellSplat = splatPrototypes[0];

тогда aStarCellSplat является клоном splatPrototypes [0], но не ссылается на него. иногда клонирование для получения начального значения и повторения его полезно, особенно когда вы изменяете сложную структуру, но в этом случае простой вызов параметра проще.

И следите за своими клонами, если вы клонируете, не забудьте назначить обратно

Джери Ардуино
источник
-1

чтобы сделать синие линии через шейдер, вам нужно иметь texture_uv в функции Surface или в функции fract ...

чтобы сделать синие / серые линии сетки в шейдерлабе, вы должны добавить всего 4-5 линий в шейдер внутри функции серфинга:

xline = ceil (frac (uv.x * .1) -. 75); yline = то же самое для y

сетка = max (xline, yline);

o.albedo.blueval = сетка.

затем вы можете изменить размер сетки, используя 1 вызов шейдера, чтобы изменить значение шейдера. l делает 10-метровую сетку, изменяет это значение на размер сетки, 0,75 делает сетку на 3/4 площади экрана ,

затем настройте цвет, добавив математику к тому же, который использовался в предыдущей версии / splatmap.

com.prehensible
источник
Предоставляя некоторую полезную информацию, это на самом деле не отвечает непосредственно на заданный вопрос. Если бы ОП действительно хотел узнать, как это сделать с помощью шейдера, он бы спросил.
Пип