Version: 2021.3
언어: 한국어
입력 관리자
모바일 키보드

모바일 디바이스 입력

모바일 디바이스의 경우, Input 클래스를 통해 터치스크린, 가속 센서, 지리/위치정보 입력 등에 액세스할 수 있습니다.

모바일 디바이스에서의 키보드 액세스는 iOS 키보드를 통해 제공됩니다.

멀티터치 스크린

iPhone, iPad 및 iPod Touch 기기에서 동시에 최대 5점 터치 동작을 인식할 수 있습니다. Input.touches 프로퍼티 배열에 접근하여 마지막 프레임 동안 각 손가락이 화면을 터치한 상태를 인지할 수 있습니다.

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.

다음은 사용자가 화면을 터치할 때마다 광선을 방사하는 예제 스크립트입니다.

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 디바이스는 멀티 터치를 지원하게 설계되었다는 점에 유의해야 합니다. 마우스 기능을 사용하면 단일 터치만 지원합니다. 또한, 모바일 디바이스에서 터치 입력 시에는 한 지점을 터치했다가 다른 지점을 터치하더라도 두 지점 사이를 이동한 것으로 처리되지 않지만, 마우스를 시뮬레이션할 경우에는 두 지점에서 일어난 터치를 이동한 것으로 처리해야 하므로 터치 입력과는 매우 다릅니다. 개발 초기에는 마우스 시뮬레이션을 사용하고, 최대한 빨리 터치 입력으로 전환할 것을 추천합니다.

가속 센서(Accelerometer)

모바일 디바이스가 움직이면 빌트인 가속 센서가 3차원 공간에서 세 개의 주축에 대한 선형 가속도 변화를 알려 줍니다. 각 축에 대한 가속도는 G-force의 값으로 하드웨어에서 직접 통보됩니다. 값이 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);
    }
}

로우 패스 필터(Low-Pass Filter)

가속 센서 조회값이 요동치거나 노이즈가 있을 수 있습니다. 신호에 로우 패스 필터링을 적용하면 하이 프리퀀시 노이즈를 제거하고 좀 더 부드럽게 만들 수 있습니다.

다음 스크립트는 가속 센서를 읽을 때 로우 패스 필터링을 적용하는 방법을 보여 줍니다.

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 부하가 클 경우 일정한 시간 간격으로 일어나지 않습니다. 따라서 시스템에서는 한 프레임 동안 두 개의 샘플을 보낼 수도 있으며, 그다음 프레임 동안에는 한 개의 샘플만 보낼 수도 있습니다.

해당 프레임 동안 가속 센서가 측정한 모든 측정치에 액세스할 수 있습니다. 다음 코드는 마지막 프레임에서 수집된 모든 가속도 센서 이벤트의 단순 평균을 나타냅니다.

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;
    }
}
입력 관리자
모바일 키보드