Как покрасить объект в юнити
Перейти к содержимому

Как покрасить объект в юнити

  • автор:

Practical use of Unity3d engine

В этой статье рассмотрим следующую задачу: необходимо реализовать выбор объектов левой клавишей мыши, причем при выборе объекта необходимо его подсветить. Эта статья является продолжением второй статьи (http://denis-potapenko.blogspot.com/2013/03/2-unity3d.html). Поэтому перед началом чтения этой статьи желательно прочесть вторую часть. Результат, который мы хотим получить представлен на рисунке В:

Рисунок. В. – Результирующая сцена

Выбор объекта

Для начала создадим переменную – член класса, которая будет хранить выбранный объект.

// selected GameObject private GameObject mSelectedObject;

Также создадим свойство на этот объект.

/// /// Gets or sets selected GameObject /// public GameObject SelectedObject < get < return mSelectedObject; >set < … // assign new game object mSelectedObject = value; … >>

Работу сеттера этого свойства рассмотрим ниже.

Теперь создадим метод, который будет выбирать объект. Определим объект, находящийся под мышкой. Алгоритм выбора объекта следующий:

  • Перевести позицию мышки из пространства окна (2д координаты) в трехмерные координаты (А);
  • Построить луч, идущий от позиции мышки в 3д координатах в сторону «от камеры» (Б);
  • Найти пересечение луча с любым объектом в сцене;
  • Первый объект, попавшийся на пересечении, является выбранным;

Преобразуем позицию мыши в луч исходящий от камеры (Объединим пункты А и Б) используя метод «ScreenPointToRay».

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

Теперь найдем пересечение луча с любым объектом в сцене. Для этого используем метод «Physics.Raycast».

RaycastHit hit; if (Physics.Raycast(ray, out hit, Constants.cMaxRayCastDistance))

Хочу сразу заметить, что на каждый объект, с которым мы хотим посчитать пересечение, должен быть назначен так называемый «Collider». «Collider» используется в основном для работы с физикой и в частности для определения пересечений. Для того чтоб назначить «Collider» на GameObject, необходимо выделить объект в сцене, и выбрать пункт меню «Component / Physics / Box Collider». В дальнейших статьях мы более подробно изучим эти компоненты.

В случае если пересечение найдено метод «Physics.Raycast» возвращает «true» и заполняет переменную «hit». Теперь определим GameObject, который соответствует найденному объекту типа «RaycastHit».

// get game object GameObject rayCastedGO = hit.collider.gameObject;

И наконец, установим найденный объект, как выделенный.

// select object this.SelectedObject = rayCastedGO;

А теперь нужно вызвать метод “SelectObjectByMousePos” в методе «Update». Причем вызывать мы его будет, только при нажатии левой клавиши мыши.

// process object selection if (Input.GetMouseButtonDown(0))
Теперь давайте подробно рассмотрим, как работает сеттер свойства «SelectedObject».

Подсветка объекта

С начала немного теории. Дело в том, что подсветку объектов можно сделать множеством способов. Я расскажу способ, который можно добиться, не используя никакие дополнения к движку Unity3d. После описания теории и практики я расскажу Вам, на мой взгляд, более совершенный способ реализации подсветки.

И так алгоритм реализации подсветки объектов следующий:

  • Создать 2 материала: первый обычный материал, второй материал подсветки;
  • Передать эти материалы в скрипт;
  • При выделении объекта, установить «подсвеченный» материал на выделенный объект;
  • На объект, который был выделен ранее, установить обычный материал ;

Теперь рассмотрим реализацию этого метода. В редакторе Unity3d создадим папку с материалами, и назовём ее «Materials». В этой папке создадим 2 материала – обычный “SimpleMat”, и подсвеченный “HighlightedMat”. Получившая иерархия папок и файлов показана на рисунке 2.1

Рис. 2.1 — Структура файлов и папок с материалами

Хочу отметить, что у обоих материалов установлен стандартный шейдер “Diffuse”. Материалы настроены идентично, за исключением того что у материала «HighlightedMat» диффузный цвет установлен в красный. На рис. 2.2 показаны настройки материала «HighlightedMat».

Рисунок 2.2 – Настройки материала «HighlightedMat»

Теперь создадим 2 публичных переменных – члена класса “AppRoot”, которые будут хранить созданные материалы.

// materials for highlight public Material SimpleMat; public Material HighlightedMat;

Теперь присвоим этим переменным значение. Сделаем это прямо в редакторе. Процесс назначения материалов в скрипт показан на рис. 2.3.

Рисунок 2.3 – Назначение материалов в скрипт “AppRoot”
Теперь наконец-то реализация сеттера свойства “SelectedObject”.
Получим «старый» выбранный объект.

// get old game object GameObject goOld = mSelectedObject;

Установим новый выбранный объект.

// assign new game object mSelectedObject = value;

Если выбранный объект не поменялся, просто выходим с метода.
// if this object is the same — just not process this if (goOld == mSelectedObject)
Установим материал на старый выбранный объект.
// set material to non-selected object if (goOld != null)
Установим материал на выбранный объект.
// set material to selected object if (mSelectedObject != null)

В результате мы получили в сцену, в которой пользователь, с помощью левой клавиши мыши, может выбирать объекты, и они будут окрашиваться в красный цвет.

Замечания

Как я уже писал выше, я не считаю выше описанный алгоритм подсветки объектов самым эффективным. Я считаю, что более эффективный метод будет использовать шейдер с компонентом «Emissive». Этот компонент умножается особым способ на результирующий цвет, таким образом, выделенный объект получает «окраску» например красного цвета, а не полностью закрашивается. Вы вполне можете создать такой шейдер своими руками. В последующих статьях я расскажу как это сделать. Из существующих стандартных шейдеров в Unity3d, я нашел шейдер «Reflective/Diffuse», который в некоторых случаях очень подходит для целей подсветки объектов. Можете попробовать использовать этот шейдер и его поле “Reflection Color” вместе “Emissive”.

как изменить цвет объекта в unity 5.6.1

GameObject[] pu = GameObject.FindGameObjectsWithTag («Pick Up»);
for (int i = 0; i < pu.Length; i++)
pu [i].GetComponent < MeshRenderer >().materials [0].color = new Color(Random.Range(0, 255)/100, Random.Range(0, 255)/100, Random.Range(0, 255)/100, 1);

Олег ОлеговичПросветленный (22716) 6 лет назад

Мне тут скучно было, интересную штуку намутил.

int i = 0;
void Update () this.GetComponent < MeshRenderer >().materials [0].color =
new Color(Mathf.PingPong(i++, 100f)/100f,Mathf.PingPong(i + 50, 100f)/100f,Mathf.PingPong(i + 100, 100f)/100f);
>

Остальные ответы

А не renderer случаем надо получать?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *