Теперь зададим режим отрисовки объектов (если в игре не будет ничего, кроме спрайтов):
Edit -> Project Settings -> Player -> Other settings -> Rendering -> Rendering Path = Vertex Lit
Нам нужно создать какой-то объект, который будет отображаться на экране, чтобы мы видели, как он двигается. Для этой цели могла бы подойти плоскость (Game Object ->Create Other -> Plane), но она состоит из 400 треугольников, что неоправданно много для отображения одного спрайта. Поэтому воспользуемся скриптом отсюда http://wiki.unity3d.com/index.php/CreatePlane
Создадим папку Editor в папке Assets и добавим туда новый файл CreatePlane.cs, текст которого можно найти по ссылке выше.
После этого в меню появится новый пункт GameObject -> Create Other -> Custom Plane... Создадим новую плоскость с такими параметрами:
На экране появится розовый квадрат - это наш нетекстурированный объект.
Добавим какую-нибудь картинку в папку Assets, создадим для него новый материал и установим для него текстурой только что добавленное изображение. Для материала поставим шейдер Unlit/Texture:
+ Показать
Перемещение
Сначала рассмотрим вариант с перемещением. Для него нам нужен:
а) 1 флаг drag типа boolean, который будет говорить, что мы находимся в режиме перемещения камеры
б) 1 точка касания initialTouchPosition, которая хранит начальные экранные координаты точки касания экрана пальцем
в) 1 мировые координаты камеры initialCameraPosition в момент первоначального касания пальцем экрана
Код для перемещения камеры одним пальцем очень прост. Для начала проверяем, что экрана касается только один палец:
if (Input.touchCount == 1)
{
...
}
Внутри первым делом отменяем операцию масштабирования, чтобы она не мешала коду перемещения, и получаем экранные координаты точки касания:
zoom = false;
Touch touch0 = Input.GetTouch(0);
Если это первый кадр, который инициирует перемещение, то устанавливаем соответствующий флаг и запоминаем координаты точки касания и текущих координаты камеры:
if (!drag)
{
initialTouchPosition = touch0.position;
initialCameraPosition = this.transform.position;
drag = true;
}
Если же это последующие после начала касания кадры, то мы определяем, насколько сместился палец относительно начальной точки касания и перемещаем камеру в обратную сторону, чтобы скомпенсировать это движение, и объект под пальцем остался в той же точке:
else
{
Vector2 delta = camera.ScreenToWorldPoint(touch0.position) -
camera.ScreenToWorldPoint(initialTouchPosition);
Vector3 newPos = initialCameraPosition;
newPos.x -= delta.x;
newPos.y -= delta.y;
this.transform.position = newPos;
}
Масштабирование
Код для двуточечного масштабирования немного сложнее. Как и в прошлый раз, сначала проверяем, что экрана касается 2 пальца:
if (Input.touchCount == 2)
{
...
}
Затем отменяем операцию перемещения и получаем экранные координаты обеих точек касания:
drag = false;
Touch touch0 = Input.GetTouch(0);
Touch touch1 = Input.GetTouch(1);
Для первого кадра, в котором экрана касаются оба пальца одновременно, нужно запомнить 5 переменных:
а) 2 точки касания initialTouch0Position и initialTouch1Position
б) 1 мировые координаты камеры initialCameraPosition в момент первоначального касания пальцев экрана
в) 1 размер половины видимого объёма камеры initialOrthographicSize
г) 1 координаты точки initialMidPointScreen посередине точек касания
Каждый последующий кадр сбрасываем координаты камеры и её "размер" к значениям на момент первоначального касания обеих пальцев экрана для того, чтобы каждый следующий кадр не накапливались изменения в положении/размере камеры.
this.transform.position = initialCameraPosition;
camera.orthographicSize = initialOrthographicSize;
Затем находим, во сколько раз увеличивать или уменьшать размер области вывода камеры. Это значение есть отношение длины отрезка, образованного расположением пальцев на текущем кадре, к длине отрезка, образованного расположением пальцев на первом кадре.
float scaleFactor = GetScaleFactor(touch0.position,
touch1.position,
initialTouch0Position,
initialTouch1Position);
Далее находим среднюю точку между двумя пальцами на текущем кадре:
Vector2 currentMidPoint = (touch0.position + touch1.position) / 2;
Следующие 4 строки вычисляют разницу в мировых координатах средней точки касания после изменения размера камеры, так как при изменении размера экранные координаты средней точки остаются неизменными, а мировые могут поменяться, так как масштабирование камеры всегда происходит относительно центра экрана:
Наконец, вычисляем между мировыми координатами средней точки на текущем и первом
кадре:
Vector2 oldAndNewMidPointDelta =
camera.ScreenToWorldPoint(currentMidPoint) -
camera.ScreenToWorldPoint(initialMidPointScreen);
и корректируем положение камеры, учитывая все поправки:
Vector3 newPos = initialCameraPosition;
newPos.x -= oldAndNewMidPointDelta.x - initialMidPointDelta.x;
newPos.y -= oldAndNewMidPointDelta.y - initialMidPointDelta.y;
this.transform.position = newPos;
В качестве побочного эффекта код двуточечного масштабирования отвечает так же и за перемещение камеры, и, если расстояние между пальцами не меняется, сводится к коду для перемещения камеры одним пальцем.
Хотя код прверялся только на Android, он должен работать без изменений и на iOS.
Исходный код можно скачать по адресу https://github.com/Skybladev2/Unity3D-pan-and-zoom-example
Готовое приложение для Android можно скачать отсюда: http://rghost.ru/41537997
#Android, #iOS, #touch
20 октября 2012
(Обновление: 29 ноя 2012)
Комментарии [2]