Создаем часы.

Введение.

В этом уроке мы создадим простые часы и запрограммируем компонент, чтобы он отображал текущее время. Вам нужно только минимальное понимание редактора Unity. Если Вы работаете с ним в течение нескольких минут и знаете, как перемещаться по экрану сцены, тогда можете начинать.
В этом уроке предполагается, что вы используете хотя бы Unity 2017.1.0.

Создаем простые часы.

Откройте Unity и создайте новый 3D-проект. Вам не нужны дополнительные пакеты, и вам также не нужна аналитика. Если вы еще не настроили редактор, вы получите макет окна по умолчанию.
Я использую другой макет, 2 на 3 вкладки, который вы можете выбрать из выпадающего списка в правом верхнем углу редактора. Я настраиваю еще окно Project на One Column Layout, которое лучше соответствует его вертикальной ориентации. Вы можете изменить его с помощью небольшого раскрывающегося списка рядом с его значком блокировки в правом верхнем углу окна над его панелью инструментов. Я также отключил Show Grid в окне сцены, в раскрывающемся меню Gizmos.
Почему мое игровое окно маленькое с темной рамкой?read

Создаем игровой объект.

Сцена по умолчанию содержит два игровых объекта. Они перечислены в окне «Иерархия (Hierarchy)», и вы также можете увидеть их значки в окне «Сцена (Scene)». Первый - основная камера (Main Camera), которая используется для рендеринга сцены. Окно игры отображается с помощью этой камеры. Второй - Направленный Свет (Directional Light), который освещает сцену.
Чтобы создать собственный игровой объект, используйте параметр GameObject / Create Empty. Вы также можете сделать это через контекстное меню окна Hierachy. Это добавляет новый объект в сцену, которому вы можете сразу дать имя. Когда мы создадим часы, назовите его Clock.
Окно «Инспектор (Inspector)» показывает детали игровых объектов. Когда наш объект часов выбран, он будет содержать заголовок с именем объекта плюс несколько параметров конфигурации. По умолчанию объект включен, не является статичным, не имеет тега и принадлежит к слою по умолчанию. Эти настройки подходят для нас. Ниже он отображает список всех компонентов игрового объекта. Всегда есть компонент Transform.
Компонент Transform содержит положение, поворот и масштаб объекта в трехмерном пространстве. Убедитесь, что положение и вращение часов равны 0. Его масштаб должен быть 1.
Как насчет 2D-объектов?read

Создание циферблата.

Хотя у нас есть объект часов, мы пока ничего не видим. Нам нужно будет добавить 3D-модели, чтобы они были визуализированы. Unity содержит несколько примитивных объектов, которые мы можем использовать для создания простых часов. Начнем с добавления цилиндра в сцену через GameObject / 3D Object / Cylinder. Убедитесь, что он имеет те же значения Transform, что и наши часы.
Новый объект имеет дополнительные три компонента, кроме пустого игрового объекта. Во-первых, он имеет Mesh Filter (Сетка), который просто содержит ссылку на встроенную цилиндрическую сетку. Во-вторых, это коллайдер капсула, который предназначен для 3D-физики. В третьих, Mesh Renderer (Визуализатор сетки). Этот компонент предназначен для обеспечения рендеринга сетки объекта. Он также контролирует, какой материал используется для рендеринга. Сейчас он является встроенным материалом по умолчанию, если вы его не измените. Этот материал также показан в инспекторе ниже списка компонентов.
Хотя объект представляет собой цилиндр, он имеет коллайдер капсулы, потому что Unity не имеет примитивного цилиндрового коллайдера. Нам он не нужен, поэтому мы можем удалить этот компонент. Если вы хотите использовать физику с вашими часами, вам лучше использовать компонент Mesh Collider. Компоненты можно удалить в раскрывающемся меню с изображением шестеренки в правом верхнем углу.
Чтобы превратить цилиндр в циферблат, мы должны сделать его плоским. Это делается путем уменьшения Y-составляющей его масштаба (scale). Уменьшите его до 0,1. Поскольку цилиндрическая сетка имеет две единицы высоты, теперь ее эффективная высота составляет 0,2 единицы. Давайте также сделаем большие часы, поэтому увеличьте компоненты X и Z своего масштаба до 10.
Измените название объекта цилиндра на «Face», поскольку оно представляет собой циферблат. Это часть часов, поэтому сделайте это дочерним элементом объекта Clock. Вы можете сделать это, перетащив циферблат на часы в окне иерархии.
Дочерние объекты подвержены трансформации их родительского объекта. Это означает, что когда Clock изменяет положение, Face делает также. Это как если бы они были единым сущностью. То же самое касается вращения и масштаба. Вы можете использовать это, чтобы создавать сложные иерархии объектов.

Создаем периферию циферблата.

Внешнее кольцо циферблата часов обычно имеет отметки, которые помогают узнать, в какое время оно отображается. Это называется тактовой периферией. Давайте используем блоки, чтобы указать часы 12-часового часа.
Добавьте объект куба в сцену через GameObject / 3D Object / Cube. Измените его масштаб на (0,5, 0,2, 1), чтобы он стал узким плоским длинным блоком. Теперь он находится внутри циферблата часов. Установите его положение (0, 0,2, 4). Это помещает его поверх циферблата и в сторону, соответствующую 12-му часу. Назовите его индикатором часа (Hour Indicator).
Индикатор трудно увидеть, потому что он имеет тот же цвет, что и циферблат. Давайте создадим для него отдельный материал через Assets / Create / Material или через контекстное меню окна Project. Это дает нам новый материал, дублирующий материал по умолчанию. Измените его Альбедо на что-то более темное, например 73 для красного, зеленого и синего. Это приводит к темно-серому материалу. Дайте ему соответствующее имя, например Clock Dark.
Что такое альбедо?read
Нужно чтобы индикатор часа использовал этот материал. Вы можете сделать это, перетащив материал на объект в окно сцены или иерархии. Вы также можете перетащить его в нижнюю часть окна инспектора или изменить элемент «Элемент 0» массива «Материалы (Materials)» рендеринга сетки.
Наш индикатор правильно позиционируется на час 12, но что, если мы хотим указать час 1? Поскольку есть двенадцать часов, а полный круг - 360 °, нам придется вращать индикатор на 30 ° вокруг оси Y. Давайте попробуем.
Хотя это дает нам правильную ориентацию, индикатор все еще находится в положении в течение часа 12. Это происходит потому, что вращение объекта относительно его собственного местного происхождения, которое является его положением.
Нам нужно переместить индикатор по краю лица, чтобы выровнять его с часом 1. Вместо того, чтобы самостоятельно разобраться с этой позицией, мы можем использовать иерархию объектов, чтобы сделать это для нас. Сначала сбросьте поворот индикатора на 0. Затем создайте новый пустой объект с позицией и вращением 0 и масштабом 1. Сделайте индикатор дочерним элементом этого объекта.
Теперь установите родительский поворот Y на 30 °. Индикатор также будет вращаться, эффективно поворачивая его по происхождению родителя и заканчивая тем, где мы хотим.
Дублируйте временного родителя с помощью Control или Command D или через контекстное меню в иерархии. Увеличьте вращение Y дубликата на 30 °. Продолжайте делать это, пока не получите по одному индикатору в час.
Нам больше не нужны временные родители. Выберите один из индикаторов часа в иерархии и перетащите его на часы. Теперь он стал ребенком. Когда это произошло, Unity изменила трансформ индикатора, поэтому его положение и вращение не изменились в мировом пространстве. Повторите это для всех двенадцати индикаторов, а затем удалите временные родительские объекты. Вы можете ускорить это, выбрав несколько объектов одновременно, с помощью Control или Command клавиш.
Я вижу такие значения, как 90.00001. Это проблема?read

Создаем стрелки.

Мы можем использовать тот же подход, чтобы построить стрелки часов. Создайте еще один куб с именем Arm (стрелка) и дайте ему тот же темный материал, который используют индикаторы. Установите его масштаб (0,3, 0,2, 2,5), чтобы он был уже и длиннее, чем индикаторы. Установите его положение (0, 0.2, 0.75), чтобы он сидел поверх циферблата и указывал на час 12, но также был сдвинут немного в противоположном направлении. Это заставляет его выглядеть так, как будто у него небольшой противовес, когда он вращается.
Куда делась иконка света?read
Чтобы заставить стрелку поворачиваться вокруг центра часов, создайте для него родительский объект, как мы сделали, чтобы расположить индикаторы часа. Снова убедитесь, что его преобразование имеет значения по умолчанию 0 для положения и вращения и 1 для шкалы. Поскольку мы будем вращать стрелку позже, сделайте этого родителя ребенком часов и назовите его Hours Arm (часовая стрелка). Итак, стрелка теперь «внук» часов.
Дублируйте часовую стрелку дважды, чтобы создать стрелку минут (Minutes Arm) и секундную стрелку (Seconds Arm). Стрелка минут должна быть узкой и более длинной, чем часовая стрелка, поэтому установите масштаб его ребенка (Arm) на (0,2, 0,15, 4) и ее положение (0, 0,375, 1). Таким образом, она будет поверх циферблата.
Для ребенка секундной стрелки используйте масштаб (0.1, 0.1, 5) и позицию (0, 0.5, 1.25). Чтобы дифференцировать его дальше, я создал материал Clock Red (красный) с RGB-значениями его альбедо, установленным на (197, 0, 0), и назначил его ребенку стрелки (Arm).
Наши часы теперь построены. Если вы еще этого не сделали, это хороший момент, чтобы сохранить сцену. Он будет храниться в качестве актива в проекте.
Если вы застряли, хотите сравнить или хотите пропустить создание часов, вы можете скачать пакет, содержащий выполненную работу, в этом разделе. Вы можете импортировать эти пакеты в проект Unity через Assets / Import Package / Custom Package ..., перетащив его в окно Unity или дважды щелкнув его в своем браузере файлов.

Анимируем часы.

Наши часы в настоящее время не показывают времени. Это просто иерархия объектов, которая заставляет Unity отображать кучу сеток. Ничего более. Если бы существовал компонент часов по умолчанию, мы могли бы использовать это, чтобы сделать некоторое время. Поскольку их нет, нам нужно будет создать свои собственные. Компоненты определяются с помощью скриптов. Добавьте новый проект сценария в проект через Assets / Create / C # Script и назовите его Clock.
Когда сценарий будет выбран, инспектор покажет его содержимое и кнопку, чтобы открыть файл в редакторе кода. Вы также можете дважды щелкнуть объект, чтобы открыть редактор. Файл сценария будет содержать шаблон кода по умолчанию для компонента, показанный ниже.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Clock : MonoBehaviour {

 // Use this for initialization
 void Start () {
  
 }
 
 // Update is called once per frame
 void Update () {
  
 }
}
Это код C#. Это язык программирования, используемый для сценариев в Unity. Чтобы понять, как работает код, мы удалим его и начнем с нуля.
Как насчет JavaScript?read

Определяем тип компонента.

Пустой файл не является допустимым скриптом. Он должен содержать определение нашей составляющей часов. Мы не определяем один экземпляр компонента. Вместо этого мы определяем общий класс или тип, известный как Clock. Как только это будет установлено, мы можем создать несколько таких компонентов в Unity.
В C# мы определяем тип Clock, указав сначала, что мы определяем класс, а затем его имя. Поскольку мы начинаем с пустого файла, его содержимое должно буквально стать классом Clock и ничего другого, хотя вы могли бы добавлять пробелы и символы новой строки между словами по своему усмотрению.
class Clock
Что такое класс, технически?read
Классы могут также определять данные и функциональные возможности, которые не принадлежат объектам, а самому классу. Это часто используется для обеспечения доступности в глобальном масштабе. Поскольку мы не хотим ограничивать, какой код имеет доступ к нашим часам, нужно добавить префикс к нему – модификатор public.
public class Clock
Какой модификатор доступа по умолчанию для классов?read
На данный момент у нас еще нет синтаксиса C#. Мы указали, что мы определяем тип, поэтому мы должны фактически определить, что это такое. Это делается блоком кода, который следует за объявлением. Границы кодового блока обозначены фигурными скобками. Мы оставляем его пустым, так что просто используйте {}.
public class Clock {}
Наш код теперь действителен. Сохраните файл и вернитесь в Unity. Редактор Unity обнаружит, что ресурс скрипта изменился и вызывает повторную компиляцию. После этого выберите наш скрипт. Инспектор сообщит нам, что в активе нет сценария MonoBehaviour.
Это означает, что мы не можем использовать этот скрипт для создания компонента в Unity. На этом этапе наши часы определяют общий тип объекта C#. Unity может использовать подтипы MonoBehaviour для создания компонентов.
Что означает mono-behavior?read
Чтобы превратить Clock в подтип MonoBehaviour, мы должны изменить наше объявление типа, чтобы он расширил этот тип. Расширение типа делается с помощью двоеточия. Это заставляет Clock наследовать все функции MonoBehaviour.
public class Clock : MonoBehaviour {}
Однако это приведет к ошибке после компиляции. Компилятор жалуется, что он не может найти тип MonoBehaviour. Это происходит потому, что тип содержится в пространстве имен UnityEngine. Чтобы получить доступ к нему, мы должны использовать его полностью квалифицированное имя UnityEngine.MonoBehaviour.
public class Clock : UnityEngine.MonoBehaviour {}
Что такое пространство имен?read
Поскольку неудобно всегда использовать префикс UnityEngine при доступе к типам Unity, мы можем указать компилятору - искать это пространство имен, когда мы явно не упоминаем о нем. Это делается путем добавления using UnityEngine; в верхней части файла. Точка с запятой требуется для обозначения конца команды.
using UnityEngine;

public class Clock : MonoBehaviour {}
Теперь мы можем добавить наш компонент к нашему игровому объекту часов в Unity. Это можно сделать либо путем перетаскивания ресурса сценария на объект, либо с помощью кнопки «Добавить компонент» в нижней части инспектора объекта.

Теперь создан экземпляр объекта C#, используя наш класс Clock в качестве шаблона. Он добавлен в список компонентов игрового объекта Clock.

Получаем доступ к стрелкам

Чтобы вращать стрелки, объекты Clock должны знать о них. Начнем с часовой стрелки. Как и все игровые объекты, ее можно вращать, изменяя поворот его компонента Transform. Поэтому мы должны добавить знания о компоненте Transform часов в Clock. Это можно сделать, добавив поле данных внутри своего кодового блока, определенное как имя, за которым следует точка с запятой.
Hours transform будет подходящим именем. Однако имена должны быть однословными. Соглашение состоит в том, чтобы сделать первое слово имени поля в нижнем регистре а все остальные слова начать с большой буквы, а затем соединить их. Таким образом, он становится hoursTransform.
Куда делась инструкция using?read
Мы также должны определить тип поля, в этом случае UnityEngine.Transform. Он должен быть помещен перед полем имени.
Transform hoursTransform;
Наш класс теперь определяет поле, которое может содержать ссылку на другой объект, тип которого должен быть Transform. Мы должны убедиться, что он содержит ссылку на компонент Transform стрелки часов.
Поля являются закрытыми по умолчанию, а это значит, что к ним может обращаться только код, принадлежащий часам. Но класс не знает о нашей сцене Unity. Если мы сделаем поле публичным, любой может изменить его содержимое.
public Transform hoursTransform;
Не являются ли публичные поля плохими?read
Когда поле открыто, оно появится в окне инспектора. Это происходит потому, что инспектор автоматически делает доступными все общедоступные поля компонентов.
Чтобы назначить полю ссылку на стрелку, перетащите стрелку часов из иерархии в поле «Hours transform». В качестве альтернативы используйте круговую кнопку справа от поля и выполните поиск стрелки.
После перетаскивания или выбора объекта стрелки часов редактор Unity захватывает свой компонент Transform и помещает ссылку на него в нашем поле.

Получаем все три стрелки.

Мы должны сделать то же самое для стрелок минут и секунд. Поэтому добавьте еще два поля с соответствующим именем в Clock.
 public Transform hoursTransform;
 public Transform minutesTransform;
 public Transform secondsTransform;
Эти объявления полей можно сделать более краткими, поскольку они используют один и тот же модификатор доступа и тип. Они могут быть объединены в список имен полей, разделенных запятыми, после модификатора доступа и типа.
 public Transform hoursTransform, minutesTransform, secondsTransform;
// public Transform minutesTransform;
// public Transform secondsTransform;
Что делает //?read
Перетащите еще две стрелки в редакторе.

Узнаем время.

Теперь, когда мы можем получить стрелки в часах, следующим шагом будет выяснить текущее время. Чтобы сделать это, нам нужно сказать Clock - выполнить некоторый код. Это делается путем добавления блока кода к классу, известного как метод. Блок должен иметь префикс имени, которое капитализируется по соглашению. Мы назовем его Awake, предполагая, что код должен быть выполнен, когда компонент пробуждается.
public class Clock : MonoBehaviour {

 public Transform hoursTransform, minutesTransform, secondsTransform;

 Awake {}
}
Методы несколько напоминают математические функции, например f (x) = 2x + 3. Эта функция принимает число, удваивает его, затем добавляет три. Он работает с одним числом, и его результат также является одним числом. В случае метода это больше похоже на f (p) = c, где p представляет входные параметры, а c представляет выполнение кода. Как определить что является результатом такой функции? Если функция должна возвращать какой-то результат, это нужно указывать явно. В нашем случае мы просто хотим выполнить некоторый код без предоставления результирующего значения. Другими словами, результат метода пустой. Мы указали это с префиксом void.
void Awake {}
Нам также не нужны какие-либо входные данные. Однако нам все равно нужно определить параметры метода, как список, разделенный запятыми между круглыми скобками. В нашем случае этот список просто пустой.
void Awake () {}
Теперь у нас есть действительный метод, хотя он пока ничего не делает. Подобно тому, как Unity обнаружил наши поля, он также обнаруживает этот метод Awake. Когда компонент имеет метод Awake, Unity будет вызывать этот метод, когда компонент пробуждается. Это происходит после его создания или загрузки.
Должен ли Awake быть публичным?read
Чтобы проверить, работает ли это, давайте попробуем создать сообщение отладки. Класс UnityEngine.Debug содержит общедоступный метод Log для этой цели. Мы передадим ему простую строку текста для печати. Строки записываются между двойными кавычками. Опять же, точка с запятой требуется для обозначения конца выражения.
 void Awake () {
  Debug.Log("Test");
 }
Войдите в режим воспроизведения в редакторе Unity. Вы увидите, что тестовая строка отображается в строке состояния в нижней части редактора. Вы также можете увидеть его в окне консоли, которое можно открыть через Window / Console. Консоль предоставляет некоторую дополнительную информацию, например, какой код генерирует сообщение, когда вы выбираете отображенный текст.
Теперь, когда мы знаем, что наш метод работает, давайте выясним текущее время его вызова. Пространство имен UnityEngine содержит класс Time, который, в свою очередь, содержит свойство time. Кажется очевидным использовать это, поэтому давайте запишем его.
 void Awake () {
  Debug.Log(Time.time);
 }
Что есть свойство?read
Оказывается, всегда отображается значение 0. Это потому, что Time.time сообщает нам, сколько секунд прошло с момента ввода режима воспроизведения. Поскольку наш метод Awake вызывается немедленно, времени еще не прошло. Так что это не говорит нам о реальном времени.
Чтобы получить доступ к системному времени компьютера, на котором мы работаем, мы можем использовать структуру DateTime. Это не тип Unity, он находится в пространстве имен System. Это часть основных функциональных возможностей платформы .NET, что и использует Unity для поддержки сценариев.
Что есть структура?read
DateTime имеет общедоступное свойство Now. Он дает значение DateTime, которое содержит текущую системную дату и время. Давайте выведем его.
using System;
using UnityEngine;

public class Clock : MonoBehaviour {

 public Transform hoursTransform, minutesTransform, secondsTransform;

 void Awake () {
  Debug.Log(DateTime.Now);
 }
}
Теперь мы получаем временную метку каждый раз, когда мы входим в режим воспроизведения.

Вращаем стрелки.

Следующим шагом будет поворот стрелок часов в зависимости от текущего времени. Давайте снова начнем с часов. DateTime имеет свойство Hour, которое дает нам час значения DateTime. Получение его из текущей временной метки даст нам текущий час дня.
void Awake () {
  Debug.Log(DateTime.Now.Hour);
 }
Мы можем использовать это для построения вращения. Вращения хранятся в Unity как кватернионы. Мы можем создать его через общедоступный метод Quaternion.Euler. Он получает регулярные углы для оси X, Y и Z как параметры и создает соответствующий кватернион.
 void Awake () {
//  Debug.Log(DateTime.Now.Hour);
  Quaternion.Euler(0, DateTime.Now.Hour, 0);
 }
Что есть кватернион?read
Все три параметра являются действительными числами, которые представлены в C# значениями с плавающей запятой. Чтобы явным образом объявить, что мы поставляем методу такие числа, добавим суффикс f к обоим нулям.
Quaternion.Euler(0f, DateTime.Now.Hour, 0f);
На наших часах установлены 12-часовые индикаторы с интервалом 30 °. Чтобы заставить вращение соответствовать этому, мы должны умножить часы на 30. Умножение выполняется звездочкой.
Quaternion.Euler(0f, DateTime.Now.Hour * 30f, 0f);
Чтобы было ясно, что мы переходим от часов к градусам, мы можем определить поле с соответствующим именем для коэффициента преобразования. Поскольку это значение с плавающей запятой, это тип float. Поскольку мы уже знаем число, мы можем сразу назначить его как часть объявления поля.
 float degreesPerHour = 30f;

 public Transform hoursTransform, minutesTransform, secondsTransform;

 void Awake () {
  Quaternion.Euler(0f, DateTime.Now.Hour * degreesPerHour, 0f);
 }
Количество градусов в час не должно меняться. Мы можем обеспечить это, добавив префикс const к нашей декларации. Это превращает degreesPerHour в константу.
const float degreesPerHour = 30f;
Что особенного в константах?read
На данный момент у нас есть поворот, но мы ничего не делаем с ним, поэтому он просто отбрасывается. Чтобы применить его к часам, мы должны назначить его свойству localRotation его компонента Transform.
 void Awake () {
  hoursTransform.localRotation =
   Quaternion.Euler(0f, DateTime.Now.Hour * degreesPerHour, 0f);
 }
Что такое локальный поворот?read
Существует также свойство поворота. Это относится к окончательному вращению компонента Transform в мировом пространстве, принимая во внимание трансформации его родителей. Если бы мы использовали его, стрелки не вращались бы при вращении часов, так как его вращение будет компенсировано.
При входе в режим воспроизведения стрелка часов переходит в правильную ориентацию. Давайте дадим то же самое двум другим оружием. Обе минуты и секунды вращаются на шесть градусов.
 const float
  degreesPerHour = 30f,
  degreesPerMinute = 6f,
  degreesPerSecond = 6f;

 public Transform hoursTransform, minutesTransform, secondsTransform;

 void Awake () {
  hoursTransform.localRotation =
   Quaternion.Euler(0f, DateTime.Now.Hour * degreesPerHour, 0f);
  minutesTransform.localRotation =
   Quaternion.Euler(0f, DateTime.Now.Minute * degreesPerMinute, 0f);
  secondsTransform.localRotation =
   Quaternion.Euler(0f, DateTime.Now.Second * degreesPerSecond, 0f);
 }
Мы используем DateTime.Now три раза, чтобы получить час, минуту и секунду. Каждый раз, когда мы снова вызываем свойство, что требует некоторой работы, что теоретически может привести к разным значениям времени. Чтобы убедиться, что этого не происходит, мы должны получить время только один раз. Мы можем сделать это, объявив переменную внутри метода и назначив ей время, а затем используем это значение.
Что такое переменная?read
 void Awake () {
  DateTime time = DateTime.Now;
  hoursTransform.localRotation =
   Quaternion.Euler(0f, time.Hour * degreesPerHour, 0f);
  minutesTransform.localRotation =
   Quaternion.Euler(0f, time.Minute * degreesPerMinute, 0f);
  secondsTransform.localRotation =
   Quaternion.Euler(0f, time.Second * degreesPerSecond, 0f);
 }

Анимация стрелок.

Мы получаем текущее время при входе в режим воспроизведения, но после этого часы остаются неподвижными. Чтобы синхронизировать часы с текущим временем, измените имя нашего метода Awake на Update. Этот метод вызывается Unity для каждого кадра, а не только один раз, пока мы остаемся в режиме воспроизведения.
 void Update () {
  DateTime time = DateTime.Now;
  hoursTransform.localRotation =
   Quaternion.Euler(0f, time.Hour * degreesPerHour, 0f);
  minutesTransform.localRotation =
   Quaternion.Euler(0f, time.Minute * degreesPerMinute, 0f);
  secondsTransform.localRotation =
   Quaternion.Euler(0f, time.Second * degreesPerSecond, 0f);
 }
 Обратите внимание, что наш компонент также получил переключатель перед своим именем в инспекторе. Это позволяет отключить компонент, что не позволит Unity вызывать метод Update.

Непрерывное вращение.

Стрелки наших часов показывают точно текущий час, минуту или секунду. Часы ведут себя как цифровые, дискретные, но со стрелками. Многие часы имеют медленно вращающиеся стрелки, что обеспечивает аналоговое представление времени. Любой подход работает, поэтому давайте сделаем это настраиваемым, добавив переключатель к инспектору нашего компонента.
Добавьте еще одно публичное поле в «Часы», которое называется непрерывный (continuous). Он может быть включен или выключен. Для этого мы можем использовать логический тип, объявленный с помощью bool.
 public Transform hoursTransform, minutesTransform, secondsTransform;

 public bool continuous;
Булевы значения являются либо истинными, либо ложными, что соответствует включению и выключению в нашем случае. По умолчанию они ложны, поэтому включите его, как только поле появится в инспекторе.
Теперь у нас есть два варианта вращения. Чтобы подготовиться к этому, дублируйте наш метод обновления и переименуйте их в UpdateContinuous и UpdateDiscrete.
 void UpdateContinuous () {}
  DateTime time = DateTime.Now;
  hoursTransform.localRotation =
   Quaternion.Euler(0f, time.Hour * degreesPerHour, 0f);
  minutesTransform.localRotation =
   Quaternion.Euler(0f, time.Minute * degreesPerMinute, 0f);
  secondsTransform.localRotation =
   Quaternion.Euler(0f, time.Second * degreesPerSecond, 0f);
 }

 void UpdateDiscrete () {
  DateTime time = DateTime.Now;
  hoursTransform.localRotation =
   Quaternion.Euler(0f, time.Hour * degreesPerHour, 0f);
  minutesTransform.localRotation =
   Quaternion.Euler(0f, time.Minute * degreesPerMinute, 0f);
  secondsTransform.localRotation =
   Quaternion.Euler(0f, time.Second * degreesPerSecond, 0f);
 }
Создайте новый метод Update. Если continuous истинно, тогда оно должно вызывать UpdateContinuous. Это можно сделать с помощью оператора if. За ключевым словом if следует выражение в круглых скобках. Если это выражение оценивается как true, тогда выполняется блок кода, следующий за ним. В противном случае блок кода пропускается.
 void Update () {
  if (continuous) {
   UpdateContinuous();
  }
 }
Где должен быть определен новый метод Update?read
Также можно добавить альтернативный блок кода, который должен быть выполнен, когда выражение ложное. Это делается с помощью ключевого слова else. Мы можем использовать это для вызова нашего метода UpdateDiscrete.
 void Update () {
  if (continuous) {
   UpdateContinuous();
  }
  else {
   UpdateDiscrete();
  }
 }
Теперь мы можем переключаться между подходами, но оба по-прежнему делают то же самое. Мы должны настроить UpdateContinuous, чтобы отображать дробные часы, минуты и секунды. К сожалению, DateTime не содержит удобных дробных данных. К счастью, у него есть свойство TimeOfDay. Это дает нам значение TimeSpan, которое содержит данные в том формате, который нам нужен. В частности, TotalHours, TotalMinutes и TotalSeconds.
 void UpdateContinuous () {
  TimeSpan time = DateTime.Now.TimeOfDay;
  hoursTransform.localRotation =
   Quaternion.Euler(0f, time.TotalHours * degreesPerHour, 0f);
  minutesTransform.localRotation =
   Quaternion.Euler(0f, time.TotalMinutes * degreesPerMinute, 0f);
  secondsTransform.localRotation =
   Quaternion.Euler(0f, time.TotalSeconds * degreesPerSecond, 0f);
 }
Это приведет к ошибкам компиляции, потому что новые значения имеют неправильный тип. Они определяются как значения с плавающей запятой двойной точности, называемые double. Эти значения обеспечивают более высокую точность, чем значения float, но код Unity работает только с значениями с плавающей запятой с одинарной точностью.
Достаточно ли одинарной точности?read
Мы можем решить эту проблему путем преобразования из double в float. Это просто отбрасывает данные точности, которые нам не нужны. Этот процесс известен как casting и выполняется путем записи нового типа в круглых скобках перед значением, которое нужно преобразовать.
  hoursTransform.localRotation =
   Quaternion.Euler(0f, (float)time.TotalHours * degreesPerHour, 0f);
  minutesTransform.localRotation =
   Quaternion.Euler(0f, (float)time.TotalMinutes * degreesPerMinute, 0f);
  secondsTransform.localRotation =
   Quaternion.Euler(0f, (float)time.TotalSeconds * degreesPerSecond, 0f);

Теперь вы знаете основы создания объектов и скриптов в Unity. Следующим шагом будет построение графика.
Переводчик Беляев В.А. ака seaman.

Комментариев нет:

Отправить комментарий