一般的なゲーム入力
モバイルキーボード

Mobile device input

モバイル端末では、Input クラスはタッチスクリーン、加速度センサー、地理的/位置入力へアクセスする機能を提供します。

モバイル端末でキーボードにアクセスする権限は モバイルキーボード を経由して与えられます。

Multi-touch screen

The iPhone, iPad and iPod Touch devices are capable of tracking up to five fingers touching the screen simultaneously. You can retrieve the status of each finger touching the screen during the last frame by accessing the Input.touches property array.

Android 端末には、どれだけの指を追跡するかということに対して統一された制限はありません。その代わりに、端末によって違いますし、古い端末での 2 本指対応から、新しい端末での 5 本指対応までありえます。

それぞれの指のタッチは Input.Touch のデータ構造体に掲載してあります。

Property: Description:
fingerId The unique index for a touch.
position The screen position of the touch.
deltaPosition The screen position change since the last frame.
deltaTime Amount of time that has passed since the last state change.
tapCount The iPhone/iPad screen is able to distinguish quick finger taps by the user. This counter will let you know how many times the user has tapped the screen without moving a finger to the sides. Android devices do not count number of taps, this field is always 1.
phase Describes the state of the touch, which can help you determine whether the user has just started to touch screen, just moved their finger or just lifted their finger.
Began A finger just touched the screen.
Moved A finger moved on the screen.
Stationary A finger is touching the screen but hasn’t moved since the last frame.
Ended A finger was lifted from the screen. This is the final phase of a touch.
Canceled The system cancelled tracking for the touch, as when (for example) the user puts the device to their face or more than five touches happened simultaneously. This is the final phase of a touch.

Here’s an example script that shoots a ray whenever the user taps on the screen:

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);
                }
            }
        }
    }
}

Mouse simulation

Unity iOS/Android 固有のタッチサポートの最上位に、マウスシミュレーションがあります。標準の Input クラスからマウス機能を使用できます。iOS/Android 機器はマルチタッチに対応するようデザインされていることに注意してください。マウス機能を使用すると、つまり、1本指のタッチだけに対応します。また、モバイル端末でのタッチは、移動なしに 1点からもう1点へと動きます。モバイル端末でのマウスシミュレーションは移動を提供します。そのため、タッチ入力と非常に異なります。開発の早期にはマウスシミュレーションを使用してもかまいませんが、できるだけ早くタッチ入力を使用することを推奨します。

加速度センサー

モバイル端末の動きに応じて、ビルトインの加速度センサーは 三次元空間内で主要な 3 つの軸に沿った線形加速度の変化を報告します。 それぞれの軸に沿った加速度は重力の値としてハードウェアによって直接報告されます。 1.0 という値は対象の軸に関して +1 の重力値を表しており、 –1.0 という値は –1 の重力値を表しています。 もし端末を(ホームバタンは下にある)直立状態で持っているなら、X 軸は右に沿って正の値を取り、 Y 軸は上向きがそのまま正の値を取り、X 軸は手前に向かって指している方が正の値を取ります。

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 が過負荷状態にあるならば、加速度センサーのサンプリングは決まった間隔では行われないということです。結果として、システムは 1 フレームの間に 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;
    }
}
一般的なゲーム入力
モバイルキーボード