codesuxxx

6 ноября, 2012

Одна анимация для нескольких объектов в Unity3D

Filed under: Uncategorized — Метки: , , — codesuxxx @ 10:32 пп

Допустим, у нас есть несколько объектов на сцене, и мы хотим сделать так, чтобы по щелчку мыши на объекте он совершал некоторое перемещение. Если траектория перемещения прямолинейная, то можно обойтись модификацией положения объекта в его скрипте. Однако, если это что-то сложное и нелинейное, то для этого гораздо правильнее и легче использовать анимацию. Приступим. Создаем новый проект и создаем на сцене пол(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.

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

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

RSS feed for comments on this post. TrackBack URI

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

Блог на WordPress.com.