| | |—| | 重要: このページでは、入力マネージャーシステムの一部について説明します。入力マネージャーシステムは古い機能であり、新しいプロジェクトには推奨されません。新しいプロジェクトのモバイルデバイス入力には、Input System パッケージを使用する必要があります。 |
モバイルデバイスでは、Input クラスはタッチスクリーン、加速度センサー、地理的/位置入力へアクセスするための機能を付与します。
モバイルデバイスでキーボードにアクセスするための権限は、モバイルキーボードを経由して付与されます。
iPhone、iPad、iPod などのタッチデバイスは、最多で同時に 5 本の指がスクリーンをタッチしているのを追跡できます。最終フレームにおいてスクリーンにタッチしている各指の状態を取得するには、Input.touches プロパティ配列にアクセスします。
Android デバイスには、何本の指を追跡するかということに対して統一された制限はありません。制限はデバイス間で異なり、古いデバイスでの 2 本指対応から、新しいデバイスでの 5 本指対応まで考えられます。
それぞれの指のタッチは Input.Touch のデータ構造体に掲載してあります。
| プロパティ: | 説明: | |
|---|---|---|
| fingerId | タッチに対する唯一のインデックス | |
| position | タッチしたスクリーンの位置 | |
| deltaPosition | 直前のフレームから変わったスクリーンの位置 | |
| deltaTime | 最後に状態が変わってから経過した時間の合計 | |
| tapCount | iPhone/iPad の画面では、ユーザーが指で素早くタップしたかどうかを識別できます。このカウンターは、ユーザーが指を横に動かさずに画面をタップした回数を知らせます。Android デバイスはタップ数をカウントしません。このフィールドは常に 1 です。 | |
| phase | タッチの状態を示し、ユーザーがスクリーンをタッチし始めたばかりなのか、指を動かしたばかりなのか、指を上げたばかりなのかを判断するのに役立ちます。 | |
| Began | 指がスクリーンに触れた瞬間 | |
| Moved | 画面上で指が動いたとき | |
| Stationary | 指はスクリーンに触れているが直前のフレームから動いていない | |
| Ended | 画面から指が持ち上げられた。これはタッチの最終段階です。 | |
| Canceled | (例えば) ユーザーが顔にデバイスを押しつけた、または同時に 6 本以上の指でタッチした場合、システムはタッチのトラッキングをキャンセルします。これはタッチの最終段階です。 | |
以下は、 ユーザーが画面をタップするたびにレイを発するスクリプトの例です。
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 ではマウスシミュレーションを実施できます。標準入力クラスからマウス機能を使用できます。iOS/Android デバイスは、複数の指によるタッチをサポートするように設計されています。マウス機能を使用すると、1 本の指によるタッチのみがサポートされます。また、モバイルデバイスでの指によるタッチ操作によって、あるエリアから別のエリアへ移動できますが、それらのエリア間での移動はありません。モバイルデバイスでのマウスシミュレーションによって移動が発生するため、タッチ入力とは大きく異なります。開発の初期にはマウスシミュレーションを使用し、できるだけ早くタッチ入力を使用することをお勧めします。
モバイルデバイスの動きに応じて、ビルトインの加速度センサーは 3 次元空間内で主要な 3 つの軸に沿った線形加速度の変化を報告します。各軸に沿った加速が重力の値としてハードウェアにより直接報告されます。値が 1.0 の場合、与えられた軸に対する +1 G の力を示し、–1.0 の値は –1 G を示します。目の前にデバイスを垂直に持っている (ホームボタンが下にある状態) 場合、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 の値が大きいほど、フィルターを適用された値は現在の入力サンプル (およびその逆) に向かってゆっくりと収束します。
各フレームの継続期間中に加速度センサーによって実行されたすべての測定の結果にアクセスすることができます。以下のコードは、直前のフレームの期間内に収集されたすべての加速度センサーイベントの単純な平均を示すものです。
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;
}
}