版本:Unity 6 (6000.0)
语言 : 英语
输入管理器
用户界面 (UI)

移动设备输入

重要:本页记录了 输入管理器设置您可以在其中定义项目的所有不同输入轴、按钮和控件。 更多信息
查看 词汇表
系统的一部分,它是一个传统功能,不建议用于新项目。对于新项目中的移动设备输入,您应该使用 输入系统包

在移动设备上,Input 类提供对触摸屏、加速度计和地理/位置输入的访问。

通过 移动键盘 提供对移动设备上键盘的访问。

多点触控屏幕

iPhone、iPad 和 iPod Touch 设备能够同时跟踪最多五个手指触摸屏幕。您可以通过访问 Input.touches 属性数组来检索在上一个帧中触摸屏幕的每个手指的状态。

Android 设备没有对它们跟踪的手指数量的统一限制。相反,它因设备而异,可以是旧设备上的两点触控,也可以是某些新设备上的五指触控。

每个手指触控都由一个 Input.Touch 数据结构表示

属性 描述
fingerId 触控的唯一索引。
position 触控的屏幕位置。
deltaPosition 自上一帧以来的屏幕位置变化。
deltaTime 自上次状态更改以来的经过时间。
tapCount iPhone/iPad 屏幕能够区分用户快速点击手指。此计数器将让您知道用户在没有将手指移到侧面时点击了屏幕多少次。Android 设备不会计算点击次数,此字段始终为 1。
phase 描述触控的状态,这可以帮助您确定用户是否刚开始触摸屏幕、刚移动手指或刚抬起手指。
Began 手指刚触摸屏幕。
Moved 手指在屏幕上移动。
Stationary 手指正在触摸屏幕,但自上一帧以来没有移动。
Ended 手指从屏幕上抬起。这是触控的最后阶段。
Canceled 系统取消了对触控的跟踪,例如当用户将设备放到脸上或同时发生超过五个触控时。这是触控的最后阶段。

以下是一个脚本示例,它在用户点击屏幕时发射射线

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 以 60Hz 的频率采样硬件并将结果存储到变量中。实际上,事情要复杂一些 - 加速度计采样不会以一致的时间间隔发生,如果在显着的 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;
    }
}
输入管理器
用户界面 (UI)