Установка
У нас в магазине есть несколько проектов, которые мы поддерживаем уже довольно давно. Один из этих проектов недавно пришлось обновить с Unity 4.x до Unity 5.x. И, как это обычно бывает при обновлении основной версии проекта Unity, все прошло гладко. Ни одной проблемы не было. Мы обменялись приветствиями, похлопали по плечу, незнакомцы заходили поздравить нас с очередным безболезненным обновлением проекта.
Хорошо, значит, это не совсем так.
Зависание
На самом деле возникли обычные проблемы. Плагины требовали обновления, а код требовал обновления, чтобы соответствовать измененным API. Это было ожидаемо, ничего страшного. Однако была одна неожиданная проблема, с которой мы столкнулись: множество пурпурных материалов. Обычно указывает на то, что у материалов отсутствуют шейдеры.
Как это должно было выглядеть (слева) и как оно появилось на самом деле (справа).
Как оказалось, у всех наших розовых проблем была одна общая черта: наборы активов. Все материалы, которые загружались в наше приложение из наборов ресурсов, имели эту проблему. Мы также заметили, что в режиме воспроизведения внутри редактора Unity при выборе одного из материалов-нарушителей мы видели в инспекторе, что для шейдера установлено правильное значение. Однако при открытии раскрывающегося списка шейдеров и повторном выборе того же шейдера розовый исчез. Все выглядело так, как было до апгрейда.
Исправление (вверх?)
Поскольку мы обнаружили, что повторное применение одного и того же шейдера с помощью панели «Инспектор» работает в режиме воспроизведения, мы решили попробовать сделать это программно. Итак, в вызове Awake мы просто взяли имя шейдера из материала, выполнили его поиск и применили значение обратно к материалу, например:
Material mat = GetComponent<Renderer>().sharedMaterial; mat.shader = Shader.Find(mat.shader.name);
Так что это сработало. Но если вы будете часто вызывать что-то подобное (как мы), вам захочется оптимизировать. Мы решили внедрить ленивый поиск, чтобы сократить объем работы, которую приложение должно было выполнять каждый раз, например, при загрузке нового пользовательского интерфейса.
private static Dictionary<string, Shader> sz_ShaderLookup = new Dictionary<string, Shader>(); public static Shader GetShader(string _shaderName) { Shader shader; if (sz_ShaderLookup.ContainsKey(_shaderName)) { shader = sz_ShaderLookup[_shaderName]; } else { shader = Shader.Find(_shaderName); sz_ShaderLookup.Add (_shaderName, shader); } return shader; }
Насколько я могу судить, эта проблема существует с момента выпуска Unity 5. Также стоит отметить, что проблема, по-видимому, ограничена только редактором. Мы не видели, чтобы это происходило в наших сборках Android или iOS. Этот факт может объяснить, почему проблема все еще существует, поскольку она не является полностью остановкой шоу.
Вы столкнулись с той же проблемой? Сообщите нам, помогло ли это или вы выбрали другой подход.
Обновление: эта проблема была исправлена в Unity 5.4.0.
Первоначально опубликовано в предыдущей версии нашего сайта 12 ноября 2015 г.