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

モバイル端末の入力

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

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

マルチタッチスクリーン

iPhone と iPod タッチは 5 本の指がスクリーンを同時にタッチしているのを追跡する能力があります。配列プロパティーである Input.touches へ直前のフレームにアクセスしている間は、それぞれの指のスクリーンタッチ状況を感知することができます。

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

Note: Touch API is also supported in Windows Standalone and Windows Editor (game view window) when running on the device with touch screen.

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

プロパティー 機能
fingerId タッチに対する唯一のインデックス
position タッチしたスクリーンの位置
deltaPosition 直前のフレームから変わったスクリーンの位置
deltaTime 最後に状態が変わってから経過した時間の合計
tapCount iPhone と iPad のスクリーンはユーザーによる素早いタップを感じ取ることができます。このカウンターは指を動かさずにスクリーンを何回タップしたかを知らせてくれます。Android 端末はタップの回数を数えません。常に 1 になります。
phase Phase と呼ばれるタッチの状態を述べます。タッチが始まったばかりなのか、指が動いているのか、指が離れたところなのかを判断するのに役立ちます。

phase は以下の内の一つになります。

Began 指がスクリーンに触れた瞬間
Moved 画面上で指が動いたとき
Stationary 指はスクリーンに触れているが直前のフレームから動いていない
Ended 画面から指が離れたとき
Canceled システムがタッチの追跡を止めたとき。(例えば)ユーザーが顔を押しつけたり、同時に 5 本以上の指でタッチした時などです。これがタッチの最後の phase になります。

以下のものはユーザーがスクリーンをタップした場所にレイを発射するスクリプトの例です:

var particle : GameObject;
function Update () {
    for (var touch : Touch in Input.touches) {
        if (touch.phase == TouchPhase.Began) {
            // 現在タッチしているところにレイを作成します
            var ray = Camera.main.ScreenPointToRay (touch.position);
            if (Physics.Raycast (ray)) {
                // ヒットしたらパーティクルを作成します
                Instantiate (particle, transform.position, transform.rotation);
            }
        }
    }
}


マウスシミュレーション

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

加速度センサー

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

Input.acceleration プロパティーにアクセスすることで加速度センサーの値を取り出すことができます。

以下は、加速度センサーを用いてオブジェクトを動かすサンプルスクリプトです:

var speed = 10.0;
function Update () {
    var dir : Vector3 = Vector3.zero;

    // デバイスは地面に平行に固定され、
    // ホームボタンは右手にあるものと仮定します。

    // デバイスの加速軸をゲーム座標に再マッピングします
    // 1) デバイスの XY 平面は XZ 平面上にマッピングします
    // 2)  Y 軸の周りに90度回転します
    dir.x = -Input.acceleration.y;
    dir.z = Input.acceleration.x;

    // 加速ベクトルを ユニットのスフィアに固定します
    if (dir.sqrMagnitude > 1)
        dir.Normalize();

    // 10 メートル/フレーム でなく、10 メートル/秒 で移動します 
    dir *= Time.deltaTime;

    // オブジェクトを移動します
    transform.Translate (dir * speed);
}


ローパスフィルター

加速度センサーの読み取りは途切れ途切れでノイズ混じりになり得ます。信号に対するローパスフィルターはそれを滑らかにして、高周波数のノイズを取りぞきます。

以下は、加速度センサーの読み取りにローパスフィルターを適用するためのスクリプトです:

var AccelerometerUpdateInterval : float = 1.0 / 60.0;
var LowPassKernelWidthInSeconds : float = 1.0;

private var LowPassFilterFactor : float = AccelerometerUpdateInterval / LowPassKernelWidthInSeconds; // 微調整可能
private var lowPassValue : Vector3 = Vector3.zero;
function Start () {
    lowPassValue = Input.acceleration;
}

function LowPassFilterAccelerometer() : Vector3 {
    lowPassValue = Vector3.Lerp(lowPassValue, Input.acceleration, LowPassFilterFactor);
    return lowPassValue;
}


LowPassKernelWidthInSeconds の値が大きいほど、フィルターをかけられた値は現在の入力サンプル(及びその逆)に向かって遅く収束します。

加速度センサーの読み取りはできる限り高精度で行いたい。何をしたらいいですか?

Input.acceleration 変数を読み取ることは、ハードウェアをサンプリングすることとは一致しません。簡単に言えば、Unity は周波数が 60 ヘルツのときにハードウェアをサンプリングし、変数に結果を保存します。実際はもう少しだけ複雑です。どういうことかというと、CPU が過負荷状態にあるならば、加速度センサーのサンプリングは決まった間隔では行われないということです。結果として、システムは 1 フレームの間に 2 回サンプルを報告し、次のフレームでは 1 サンプルを報告するかもしれないのです。

各フレームの加速度センサーによるすべての測定結果にアクセスすることができます。以下のコードは直前のフレームで収集されたすべての加速度センサーイベントの平均を説明するものです。

var period : float = 0.0;
var acc : Vector3 = Vector3.zero;
for (var evnt : iPhoneAccelerationEvent in iPhoneInput.accelerationEvents) {
    acc += evnt.acceleration * evnt.deltaTime;
    period += evnt.deltaTime;
}
if (period > 0)
    acc *= 1.0/period;
return acc;


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