Version: 2019.2
Cache Server
Расширение редактора

Изменение исходных ассетов из кода

Автоматическое создание экземпляров

Обычно, когда вы желаете изменить какой-нибудь игровой ассет, вы хотите, чтобы это случилось во время выполнения и вы также хотите, чтобы эти изменения были временными. Например, если ваш персонаж подбирает бонус неуязвимости, вы вероятно захотите поменять шейдер of the материала персонажа игрока, чтобы визуально продемонстрировать его неуязвимое состояние. Это действие подразумевает изменение используемого материала. Это изменение не является постоянным, т.к. мы не хотим, чтобы материал имел другой шейдер, когда мы выйдем из режима проигрывания (Play Mode).

Однако в Unity можно писать код, который будет перманентно изменять исходный ассет. Давайте отталкиваться от описанного выше примера с материалами.

Для временного изменения шейдера материала, мы меняем свойство shader компонента Material.

private var invincibleShader = Shader.Find ("Specular");

function StartInvincibility {
    renderer.material.shader = invincibleShader;
}

При использовании этого скрипта и выходе из Play Mode, состояние материала будет сброшено на то, которое у него было изначально до входа в Play Mode. Это происходит, т.к. при доступе к renderer.material, материал автоматически дублируется и возвращается его экземпляр. Этот экземпляр при этом автоматически применяется к рендереру. Так что вы можете менять его так, как пожелаете без страха перманентного применения этих изменений.

Прямое изменение

ОЧЕНЬ ВАЖНО

Представленный ниже метод изменит используемые в Unity исходные файлы ассета. Эти изменения необратимы. Используйте с особой осторожностью.

Теперь предположим, что мы не хотим, чтобы материал возвращался к исходному состоянию при выходе из Play Mode. Для этого мы можем использовать renderer.sharedMaterial. Свойство sharedMaterial вернёт ссылку на исходный ассет, используемый в этом рендерере (и, возможно, в других рендерерах тоже).

Представленный ниже код перманентно изменит материал так, чтобы он использовал Specular шейдер. Материал не вернётся к тому состоянию, что у него было до входа в Play Mode.

private var invincibleShader = Shader.Find ("Specular");

function StartInvincibility {
    renderer.sharedMaterial.shader = invincibleShader;
}

Как вы можете видеть, внесение каких-либо изменений в sharedMaterial могут быть как полезны, так и рискованны. Любое изменение, сделанное для sharedMaterial будет перманентно и необратимо.

Применяемые члены классов

Формула, аналогичная той, что была описана выше, может применяться не только к материалам. Вот полный список ассетов, которые следуют этому соглашению:

  • Материалы: renderer.material и renderer.sharedMaterial
  • Меши: meshFilter.mesh и meshFilter.sharedMesh
  • Физические материалы: collider.material и collider.sharedMaterial

Прямое назначение

Если вы объявите публичную переменную одного из перечисленных выше типов: Material, Mesh, или Physic Material и примените изменения к ассету с помощью этой переменной вместо использования соответствующего члена класса, вы не получите выгоду от автоматической генерации экземпляров до того, как будут применены изменения.

Ассеты, для которых не создаются автоматические экземпляры

Существует два типа ассетов, экземпляры которых никогда не создаются при их изменении.

Любые изменения, сделанные у этих ассетов через код всегда перманентны и необратимы. Так что, если вы меняете карту высот своего террейна из кода, вам следует учесть момент с созданием экземпляров и менять значения самостоятельно. То же касается текстур. Если вы измените пиксели файла текстуры, это изменение будет перманентно.

iOS and Android Notes

Ассеты Texture2D никогда не генерируют экземпляры при их изменении в iOS и Android проектах. Любые изменения, применяемые к этим ассетам через код всегда перманентны и необратимы. Так что, если вы измените пиксели файла текстуры, то это изменение будет перманентно.

Cache Server
Расширение редактора