본문 바로가기
[Unity]

[Unity] GPS 기능으로 위도와 경도 불러오기

by 김기승 2023. 8. 20.

유니티에서 제공하는 LocationService 클래스로 간단히 GPS 기능을 구현해보자.

이번 글에서는 사진은 없고, 소스 코드를 위주로 진행해보겠다.


일단, 전체 소스를 먼저 보도록 하자.

using UnityEngine;
using UnityEngine.Android; //네임스페이스 추가

public class GPSModule : MonoBehaviour
{
    [Header("Setting")]
    public bool startGPSOnStart; //Start문에서 GPS를 실행할 것인지 여부
    public float desiredAccuracyInMeters; //현재 위치로부터의 최대 오차를 지정하는 변수 (정확도)
    public float updateDistanceInMeters; //특정 거리 이상 이동하면 갱신되도록 지정하는 변수 (갱신 빈도)

    [Header("Cache")]
    private LocationService locationService; //핵심 클래스

    private void Awake()
    {
        locationService = Input.location; //계속 참조할 것이므로 캐싱
    }
    private void Start()
    {
        if (startGPSOnStart) //Start문에서 GPS를 실행하고자 하면
            StartGPS(); //실행
    }

    public void StartGPS(string permissionName = null) //GPS를 실행하는 함수
    {
        if (Permission.HasUserAuthorizedPermission(Permission.FineLocation)) //이미 위치 권한을 획득했으면
        {
            locationService.Start(desiredAccuracyInMeters, updateDistanceInMeters); //서비스 시작
        }
        else //아직 위치 권한을 획득하지 못했으면
        {
            PermissionCallbacks callbacks = new(); //콜백 함수 생성 후
            callbacks.PermissionGranted += StartGPS; //현재 함수를 재귀로 들어오도록
            Permission.RequestUserPermission(Permission.FineLocation, callbacks); //권한 요청 후, 다시 GPS를 시작하도록 함수 실행
        }
    }
    public void StopGPS() //GPS를 정지하는 함수
    {
        locationService.Stop(); //서비스 정지
    }
    public bool GetLocation(out LocationServiceStatus status, out float latitude, out float longitude, out float altitude) //위치 정보를 얻는 함수
    {
        latitude = 0f; //위도
        longitude = 0f; //경도
        altitude = 0f; //고도
        status = locationService.status; //서비스 상태

        if (!locationService.isEnabledByUser) //만약, 사용자가 스마트폰의 GPS 기능을 껐다면
            return false;

        switch (status)
        {
            case LocationServiceStatus.Stopped: //GPS를 시작하지 않음
            case LocationServiceStatus.Failed: //GPS 정보를 가져올 수 없음
            case LocationServiceStatus.Initializing: //GPS 기능 시작 후 초기화 중
                return false; //false를 반환해서 정상적으로 정보를 주지 못했음을 알림 (그 원인은 status에 담김)

            default: //GPS 기능이 정상적임 (Running)
                LocationInfo locationInfo = locationService.lastData; //마지막 GPS 정보를 담고
                latitude = locationInfo.latitude; //위도 지정
                longitude = locationInfo.longitude; //경도 지정
                altitude = locationInfo.altitude; //고도 지정
                return true; //true를 반환해서 정상적으로 정보를 줬음을 알림
        }
    }
}

아래에서부터 분석하도록 하겠다.


① 변수 선언 및 초기화

[Header("Setting")]
public bool startGPSOnStart; //Start문에서 GPS를 실행할 것인지 여부
public float desiredAccuracyInMeters; //현재 위치로부터의 최대 오차를 지정하는 변수 (정확도)
public float updateDistanceInMeters; //특정 거리 이상 이동하면 갱신되도록 지정하는 변수 (갱신 빈도)

[Header("Cache")]
private LocationService locationService; //핵심 클래스

private void Awake()
{
    locationService = Input.location; //계속 참조할 것이므로 캐싱
}
private void Start()
{
    if (startGPSOnStart) //Start문에서 GPS를 실행하고자 하면
        StartGPS(); //실행
}

Start문에서 GPS를 시작할 수 있도록 구성했다.

desiredAccuracyInMeters가 최대 오차를 지정하는 변수이고,
updateDistanceInMeters는 현재 위치에서 몇 미터이상 멀어지면 갱신할 것인지를 지정하는 변수이다.

※ 사실 최대 오차를 지정했다고 해서, 완벽히 현재 위치를 찾는 것이라 볼 수는 없다.

여러 요인에 의한 오차는 반드시 존재한다.

 

② GPS 시작 / 정지 함수

public void StartGPS(string permissionName = null) //GPS를 실행하는 함수
{
    if (Permission.HasUserAuthorizedPermission(Permission.FineLocation)) //이미 위치 권한을 획득했으면
    {
        locationService.Start(desiredAccuracyInMeters, updateDistanceInMeters); //서비스 시작
    }
    else //아직 위치 권한을 획득하지 못했으면
    {
        PermissionCallbacks callbacks = new(); //콜백 함수 생성 후
        callbacks.PermissionGranted += StartGPS; //현재 함수를 재귀로 들어오도록
        Permission.RequestUserPermission(Permission.FineLocation, callbacks); //권한 요청 후, 다시 GPS를 시작하도록 함수 실행
    }
}
public void StopGPS() //GPS를 정지하는 함수
{
    locationService.Stop(); //서비스 정지
}

위치 권한의 여부에 따라 GPS를 시작하는 방식이 달라진다.

이미 권한을 획득했다면, LocationService를 바로 시작하면 되는 것이고,

그게 아니라면 권한을 받고 다시 시작할 수 있도록 콜백 함수를 지정해주면 된다.

콜백 함수는 재귀 형태로 지정해주었는데, 다시 StartGPS 함수가 실행되었을 시점에는

권한을 획득했기 때문에 무한 루프에 빠지지 않는다.

 

③ 위치 정보 함수

public bool GetLocation(out LocationServiceStatus status, out float latitude, out float longitude, out float altitude) //위치 정보를 얻는 함수
{
    latitude = 0f; //위도
    longitude = 0f; //경도
    altitude = 0f; //고도
    status = locationService.status; //서비스 상태

    if (!locationService.isEnabledByUser) //만약, 사용자가 스마트폰의 GPS 기능을 껐다면
        return false;

    switch (status)
    {
        case LocationServiceStatus.Stopped: //GPS를 시작하지 않음
        case LocationServiceStatus.Failed: //GPS 정보를 가져올 수 없음
        case LocationServiceStatus.Initializing: //GPS 기능 시작 후 초기화 중
            return false; //false를 반환해서 정상적으로 정보를 주지 못했음을 알림 (그 원인은 status에 담김)

        default: //GPS 기능이 정상적임 (Running)
            LocationInfo locationInfo = locationService.lastData; //마지막 GPS 정보를 담고
            latitude = locationInfo.latitude; //위도 지정
            longitude = locationInfo.longitude; //경도 지정
            altitude = locationInfo.altitude; //고도 지정
            return true; //true를 반환해서 정상적으로 정보를 줬음을 알림
    }
}

핵심 함수이다. 위치 정보를 가져오는데에 성공할 수도 있고, 실패할 수도 있기 때문에 bool 형태를 반환한다.

대신, out 키워드를 사용하여 외부 변수에 값을 할당한다.

만약, 위치 정보를 가져오는 데에 실패했다면 그 원인을 status 변수로 확인할 수 있는 것이다.


여기까지 GPS 정보를 받아오는 방법에 대해 알아보았다.

GPS는 배터리 소모가 많은 기능이므로 적절히 변수 값들을 조절해서 사용했으면 한다.

댓글