Допустим, у нас есть несколько объектов на сцене, и мы хотим сделать так, чтобы по щелчку мыши на объекте он совершал некоторое перемещение. Если траектория перемещения прямолинейная, то можно обойтись модификацией положения объекта в его скрипте. Однако, если это что-то сложное и нелинейное, то для этого гораздо правильнее и легче использовать анимацию. Приступим. Создаем новый проект и создаем на сцене пол(Plane):
и три, например, кубика (добавим источник освещения, чтобы лучше все было видно):
Теперь создадим скрипт, который будет перехватывать щелчки мыши на кубиках, и перетащим этот скрипт на каждый кубик. У каждого кубика в инспекторе появится этот скрипт:
Двойной щелчек по скрипту — и мы в редакторе. Добавим в класс открытую переменную string Name (открытой переменную сделаем для того, чтобы ее значение можно было установить в инспекторе), и добавим метод void OnMouseDown(), в котором выведем в лог информацию о имени кубика, по которому щелкнули мышью:
Код скрипта:
using UnityEngine; using System.Collections; public class CubeBehaviourScript : MonoBehaviour { public string Name; // Use this for initialization void Start () { } // Update is called once per frame void Update () { } void OnMouseDown() { Debug.Log("Cube " + Name + " clicked!"); } }
Нажимаем кнопку Play и щелкаем по кубикам. Внизу окна появится полоска с логом. Щелкнув по этой полоске, окно лога распахнется:
Все приготовления сделаны, теперь за дело! Создаем объект анимации. Вкладка Project->Create->Animation. Перетаскиваем анимацию на кубики. Выбираем кубик и открываем окно настройки анимации из меню Window->Animation:
Добавляем ключевые кадры и в них устанавливаем значения для положения кубика. Я установил изменение положения только по оси Y — оно самое наглядное:
Теперь если нажать на кнопку проигрывания в окне анимации, то кубик начнет двигаться. Затем можно выделить два других кубика и тоже посмотреть на их анимацию. Но что это? Какой кошмар! Второй и третий кубики двигаются не из своей позиции, а из позиции первого кубика!
Это совсем не то, что мы ожидали. Дело в том, что анимация проигрывается в локальных координатах, и поэтому каждый кубик в начале проигрывания анимации устанавливается в позицию, заданную в первом ключевом кадре. Подробнее об этом можно посмотреть здесь:
Лечится это довольно просто. Для каждого кубика мы создадим пустой(Empty) родительский объект, относительно которого у каждого кубика будут координаты (0, 0, 0), а для того, чтобы расположить кубик на сцене, мы будем перемещать родительский объект. Из меню GameObject->Create Empty создаем три пустых объекта и в каждый из них перетаскиваем кубик:
Затем у каждого кубика устанавливаем координаты (0, 0, 0), а по сцене двигаем родительские объекты. Затем исправляем анимацию. Выделяем кубик. В первом ключевом кадре устанавливаем координаты (0, 0, 0), а затем добавляем еще несколько ключевых кадров и делаем ДЕЙСТВИТЕЛЬНО сложную анимацию:
Теперь можно запустить анимацию для каждого кубика и убедиться, что каждый кубик скачет от своего положения.
А теперь самое вкусное, ради чего, собственно, я и потратил время на написание этой статьи. Моей исходной задачей было сделать так, чтобы по щелчку мыши объекты перемещались по хитрой траектории в новое положение, то есть анимация должна проигрываться каждый раз из нового положения. С нашими знаниями о том, что анимация проигрывается в локальной системе координат, сделать это будет проще простого. В конце проигрывания анимации у объекта изменяются его локальные координаты, а координаты родителя остаются теми же. Значит, при очередном проигрывании анимации, нужно родителя сместить на расстояние, равное координатам кубика внутри родителя, а анимация сама в первом ключевом кадре установит у кубика координаты (0, 0, 0). Поскольку теперь проигрыванием анимации мы будем управлять из скрипта, то в инспекторе у каждого кубика в разделе Animation нужно убрать галочку Play Automatically. В первой итерации код скрипта выглядит так:
using UnityEngine; using System.Collections; public class CubeBehaviourScript : MonoBehaviour { public string Name; private string animationName = "CubeAnimation"; // Use this for initialization void Start () { } // Update is called once per frame void Update () { } void OnMouseDown() { if(!animation.IsPlaying(animationName)){ animation.Play(animationName); } Debug.Log("Cube " + Name + " clicked!"); } }
Можно нажать кнопку Play и убедиться, что кубики прыгают, если по ним щелкнуть кнопкой мыши.
Исправим анимацию. Пусть кубики двигаются также по осям X и Z:
Обратите внимание, мне нужно, чтобы кубик двигался только по оси Z, поэтому в последнем ключевом кадре значения для осей X и Y равны 0, а для оси Z нет. Добавим в скрипт переменную Vector3 delta. Это расстояние, которое прошел кубик за предыдущее проигрывание анимации. Перед каждым проигрыванием анимации мы будем смещать на это расстояние родителя кубика:
using UnityEngine; using System.Collections; public class CubeBehaviourScript : MonoBehaviour { public string Name; private string animationName = "CubeAnimation"; private Vector3 delta; // Use this for initialization void Start () { } // Update is called once per frame void Update () { } void OnMouseDown() { if(!animation.IsPlaying(animationName)){ delta = transform.position - transform.parent.position; transform.parent.Translate(delta); animation.Play(animationName); } Debug.Log("Cube " + Name + " clicked!"); } }
Ну, собственно и все 🙂 Теперь наш объект перемещается по замысловатой кривой на заданное расстояние при каждом щелчке мыши.
English tags: Unity3D single animation object for multiply objects, Unity3D move objects using animation, Unity3D local animation.
Оставьте комментарий