Unity 6.3
0 онлайн 72 гостей 3 в системе
Вход
Вводимые ресурсы Шаг 7 из 8

Ввод мобильного устройства

Важная: На этой странице документирована часть системы 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;
    }
}