Ввод мобильного устройства
Важная: На этой странице документирована часть системы Input Manager, которая является устаревшей функцией и не рекомендуется для новых проектов. Для ввода с мобильного устройства в новых проектах используйте Input System Пакет.
На мобильных устройствах, Input класс даёт доступ к вводу с сенсорного экрана, акселерометра и данных о географическом положении.
Доступ к клавиатуре на мобильных устройствах обеспечивается через Мобильная клавиатура.
Мульти-сенсорный экран
Касательные устройства iPhone, iPad и iPod могут отслеживать одновременное прикосновение к экрану пяти пальцев. Вы можете получить статус каждого пальца, прикоснувшегося к экрану в течение последнего кадра, используя массив свойств Input.touches.
Android устройства не имеют единого ограничения на количество пальцев, которые они отслеживают. Вместо этого, это варьируется от устройства к устройству и может быть что-то от двух-касания на старых устройствах до пяти пальцев на некоторых более новых устройств.
Каждое прикосновение пальца представляется структурой данных Input.Touch
Следующий пример скрипта стреляет луч, когда пользователь нажимает на экран:
using UnityEngine;
public class TouchInput : MonoBehaviour
{
GameObject particle;
void Update()
{
foreach(Touch touch in Input.touches)
{
if (touch.phase == TouchPhase.Began)
{
// Construct a ray from the current touch coordinates
Ray ray = Camera.main.ScreenPointToRay(touch.position);
if (Physics.Raycast(ray))
{
// Create a particle if hit
Instantiate(particle, transform.position, transform.rotation);
}
}
}
}
}
Симуляция мыши
В дополнение к поддержке сенсорного экрана Unity iOS/Android обеспечивает симуляцию мыши. Вы можете использовать функции мыши из стандартного Input класс. Учтите, что устройства iOS и Android рассчитаны на множественные касания. Функциональность мыши поддерживает только одно касание. Кроме того, касание пальцем на мобильных устройствах может переместиться из одной области в другую без движения между ними. Имитация мыши на мобильных устройствах даёт движение, поэтому сильно отличается от сенсорного ввода. Рекомендуется пользоваться имитацией мыши на ранних этапах разработки и как можно скорее переходить на сенсорный ввод.
Акселерометр
По мере движения мобильного устройства, встроенный акселерометр сообщает изменения линейного ускорения вдоль трех основных осей в трехмерном пространстве. Ускорение вдоль каждой оси сообщается непосредственно аппаратным обеспечением как значения силы G. Значение 1.0 представляет нагрузку около +1g вдоль данной оси, а значение -1.0 представляет -1g. Если вы держите устройство вертикально (с кнопкой дома внизу) перед собой, ось X положительная вдоль правой, ось Y положительная прямо вверх, а ось Z положительная, указывающая на вас.
Вы можете получить значение акселерометра, получив доступ к свойству Input.acceleration.
Ниже приведен пример скрипта, который будет перемещать объект с помощью акселерометра:
using UnityEngine;
public class Accelerometer : MonoBehaviour
{
float speed = 10.0f;
void Update()
{
Vector3 dir = Vector3.zero;
// we assume that the device is held parallel to the ground
// and the Home button is in the right hand
// remap the device acceleration axis to game coordinates:
// 1) XY plane of the device is mapped onto XZ plane
// 2) rotated 90 degrees around Y axis
dir.x = -Input.acceleration.y;
dir.z = Input.acceleration.x;
// clamp acceleration vector to the unit sphere
if (dir.sqrMagnitude > 1)
dir.Normalize();
// Make it move 10 meters per second instead of 10 meters per frame...
dir *= Time.deltaTime;
// Move object
transform.Translate(dir * speed);
}
}
Низкочастотный фильтр
Показатели акселерометра могут быть резкими и шумными. Применение низкочастотной фильтрации к сигналу позволяет сгладить его и избавиться от высокочастотного шума.
Следующий скрипт показывает, как применить низкочастотную фильтрацию к показаниям акселерометра:
using UnityEngine;
public class LowPassFilterExample : MonoBehaviour
{
float accelerometerUpdateInterval = 1.0f / 60.0f;
float lowPassKernelWidthInSeconds = 1.0f;
private float lowPassFilterFactor;
private Vector3 lowPassValue = Vector3.zero;
void Start()
{
lowPassFilterFactor = accelerometerUpdateInterval / lowPassKernelWidthInSeconds;
lowPassValue = Input.acceleration;
}
private void Update()
{
lowPassValue = LowPassFilterAccelerometer(lowPassValue);
}
Vector3 LowPassFilterAccelerometer(Vector3 prevValue)
{
Vector3 newValue = Vector3.Lerp(prevValue, Input.acceleration, lowPassFilterFactor);
return newValue;
}
}
Чем больше значение LowPassKernelWidthInSeconds, тем медленнее фильтруемое значение будет сближаться с текущей входной выборкой (и наоборот).
Я хотел бы как можно больше точности при считывании акселерометра. Что мне делать?
Чтение переменных Input.acceleration не означает дискретизацию аппаратуры. Проще говоря, Unity дискретизирует аппаратуру на частоте 60 Гц и сохраняет результат в переменной. На самом деле все немного сложнее – дискретизация акселерометра не происходит с постоянными интервалами, если под значительными нагрузками CPU. В результате система может сообщить 2 дискретизации в течение одного кадра, а затем 1 дискретизацию в течение следующего кадра.
Вы можете получить доступ ко всем измерениям, выполненным акселерометром в течение кадра. Следующий код проиллюстрирует простое среднее всех событий акселерометра, которые были собраны в течение последнего кадра:
public class AccelerationEvents : MonoBehaviour
{
void Update()
{
GetAccelerometerValue();
}
Vector3 GetAccelerometerValue()
{
Vector3 acc = Vector3.zero;
float period = 0.0f;
foreach(AccelerationEvent evnt in Input.accelerationEvents)
{
acc += evnt.acceleration * evnt.deltaTime;
period += evnt.deltaTime;
}
if (period > 0)
{
acc *= 1.0f / period;
}
return acc;
}
}