Unity에서 Android GPS 구현하기
Unity를 활용하여 Android GPS를 구현하는 방법은 모바일 게임이나 위치 기반 서비스(LBS) 개발에서 매우 유용합니다. 이번 포스에서는 Unity에서 Android 플랫폼을 대상으로 GPS 데이터를 가져오는 방법을 단계별로 알아보고, 필요한 권한 요청과 구현 과정을 자세히 설명하겠습니다.
Android GPS와 Unity의 활용
GPS(Global Positioning System)는 사용자의 정확한 위치를 제공하는 기술로, Unity에서는 이를 활용해 다양한 위치 기반 콘텐츠를 제작할 수 있습니다. Unity의 Input.location API를 사용하면 간단히 GPS 데이터를 가져올 수 있으며, 이를 통해 다음과 같은 기능을 구현할 수 있습니다:
- 사용자의 위치 기반 맞춤형 콘텐츠 제공
- AR 게임에서 현실 세계와 상호작용 구현
- 위치 기반 게임이나 애플리케이션 개발
Android 위치 권한의 이해
Android에서 GPS 데이터를 사용하려면 필수 권한이 필요합니다. Unity에서 이를 처리하려면 AndroidManifest.xml 파일에 적절한 권한을 추가하고, 런타임 동안 권한 요청을 처리해야 합니다.
필수 권한
- ACCESS_FINE_LOCATION: GPS를 통해 높은 정확도의 위치 데이터 접근.
- ACCESS_COARSE_LOCATION: Wi-Fi 또는 셀룰러 네트워크 기반 위치 데이터 접근.
- ACCESS_BACKGROUND_LOCATION: Android 10(API 29) 이상에서 백그라운드 위치 데이터 접근.
Unity Android Platform 설정하기
플랫폼 변환 방법
유니티에서 Build Settings 창을 열기 위해 Ctrl + Shift + B를 누릅니다. 이후 플랫폼에서 Android를 선택하고 Switch Platform 버튼을 클릭하세요. 만약 Android 플랫폼이 활성화되어 있지 않다면, Unity Hub를 실행하여 왼쪽 패널의 설치 탭에서 사용 중인 유니티 버전을 선택한 후 설정 버튼을 클릭하세요. 이어서 모듈 추가 버튼을 눌러 Android Build Support 모듈을 설치하시면 됩니다.
AndroidManifest.xml 추가
Build Settings 창의 왼쪽 하단에 있는 Player Settings 버튼을 클릭하여 Player Settings 창을 엽니다. 이후 Player 섹션의 Publish Settings 탭으로 이동하여 Build 그룹에 있는 Custom Main Manifest 옵션을 체크합니다. 이 작업을 완료하면 Assets > Plugins > Android > AndroidManifest.xml 경로에 XML 파일이 생성됩니다.
AndroidManifest.xml 설정
Unity 프로젝트에서 AndroidManifest.xml 파일을 수정하려면, 아래 내용을 추가해주세요. 해당 내용은 <manifest> 블록 내부에 위치하며, <application> 블록 위에 추가해야 합니다.
<manifest>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<application>
<!-- 기존 내용 -->
</application>
</manifest>
Unity에서 GPS 구현 단계
1. 권한 확인 및 요청
Unity는 Permission.RequestUserPermission API를 제공하여 런타임 동안 권한을 요청할 수 있습니다. 사용자가 권한을 허용했는지 확인한 뒤에만 위치 데이터를 가져오는 로직을 실행해야 합니다.
2. 위치 서비스 활성화 확인
GPS 데이터를 가져오려면 사용자의 디바이스에서 위치 서비스가 활성화되어 있어야 합니다. 이를 Input.location.isEnabledByUser로 확인하고, 비활성화된 경우 Android 설정 화면으로 유도합니다.
3. 위치 데이터 가져오기
Unity의 Input.location API를 사용하여 위치 데이터를 가져옵니다. 위치 서비스 초기화에는 약간의 시간이 소요되므로 코루틴을 사용하여 처리합니다.
Unity에서 GPS 구현 로직
Unity에서 GPS를 구현하려면 Android 권한 요청, 위치 데이터 가져오기, 그리고 데이터 표시를 포함한 전체적인 흐름을 이해해야 합니다. 아래는 전체 코드를 제시한 뒤, 각 코드 스니펫과 Unity에서 해야 할 작업을 단계별로 설명하겠습니다.
전체 코드
using UnityEngine;
using System.Collections;
using UnityEngine.Android;
using TMPro;
public class LocationManager : MonoBehaviour
{
// TextMeshPro UI 컴포넌트를 SerializeField로 연결하여 데이터를 출력
[SerializeField] TextMeshProUGUI txt_Latitude; // 위도 출력
[SerializeField] TextMeshProUGUI txt_Longitude; // 경도 출력
[SerializeField] TextMeshProUGUI txt_Altitude; // 고도 출력
[SerializeField] TextMeshProUGUI txt_Accuracy; // GPS 데이터 정확도 출력
void Start()
{
// 위치 데이터를 가져오는 메서드를 호출
GetMyLocation();
}
public void GetMyLocation()
{
// 권한 확인 및 요청을 처리하는 코루틴 실행
StartCoroutine(CheckAndRequestPermission());
}
IEnumerator CheckAndRequestPermission()
{
// 위치 권한이 허용되지 않았는지 확인
if (!Permission.HasUserAuthorizedPermission(Permission.FineLocation))
{
// 위치 권한 요청
Permission.RequestUserPermission(Permission.FineLocation);
// 사용자가 권한을 허용하거나 거부할 때까지 대기
while (!Permission.HasUserAuthorizedPermission(Permission.FineLocation))
{
yield return null; // 다음 프레임까지 대기
}
}
// 권한이 허용되었을 경우 위치 데이터를 가져오는 코루틴 실행
StartCoroutine(GetLocation());
}
IEnumerator GetLocation()
{
// 위치 서비스가 활성화되어 있는지 확인
if (!Input.location.isEnabledByUser)
{
// 위치 서비스가 비활성화된 경우 로그 출력 및 설정 화면으로 이동
Debug.Log("========== LOCATION SERVICE DISABLED ==========");
OpenLocationSettings();
yield break; // 코루틴 종료
}
// 위치 서비스 시작
Input.location.Start();
// 위치 서비스 초기화 대기
int maxWait = 20; // 최대 대기 시간(초)
while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0)
{
yield return new WaitForSeconds(1); // 1초 대기
maxWait--; // 대기 시간 감소
}
// 초기화 타임아웃 처리
if (maxWait <= 0)
{
Debug.Log("========== LOCATION SERVICE INITIALIZATION TIMEOUT ==========");
yield break; // 코루틴 종료
}
// 위치 서비스 초기화 실패 처리
if (Input.location.status == LocationServiceStatus.Failed)
{
Debug.Log("========== FAILED TO GET LOCATION ==========");
yield break; // 코루틴 종료
}
else
{
// 위치 데이터가 정상적으로 수신된 경우
Debug.Log("========== LOCATION DATA ==========");
Debug.Log($"Latitude: {Input.location.lastData.latitude}"); // 위도 로그
Debug.Log($"Longitude: {Input.location.lastData.longitude}"); // 경도 로그
Debug.Log($"Altitude: {Input.location.lastData.altitude}"); // 고도 로그
Debug.Log($"Accuracy: {Input.location.lastData.horizontalAccuracy}"); // 정확도 로그
// 위치 데이터를 UI에 출력
txt_Latitude.text = $"Latitude: {Input.location.lastData.latitude}";
txt_Longitude.text = $"Longitude: {Input.location.lastData.longitude}";
txt_Altitude.text = $"Altitude: {Input.location.lastData.altitude}";
txt_Accuracy.text = $"Accuracy: {Input.location.lastData.horizontalAccuracy}";
Debug.Log("========== END OF LOCATION DATA ==========");
}
// 위치 서비스 중지 (필요하지 않을 경우)
Input.location.Stop();
}
void OpenLocationSettings()
{
// 위치 서비스가 비활성화된 경우 Android 설정 화면으로 이동
Debug.Log("Opening location settings...");
Application.OpenURL("package:" + Application.identifier); // 앱 설정 화면
}
}
주요 코드 설명
권한 확인 및 요청
if (!Permission.HasUserAuthorizedPermission(Permission.FineLocation))
{
Permission.RequestUserPermission(Permission.FineLocation);
// 권한 요청 후 결과 대기
while (!Permission.HasUserAuthorizedPermission(Permission.FineLocation))
{
yield return null; // 다음 프레임까지 대기
}
}
- Permission.HasUserAuthorizedPermission으로 위치 권한(FINE_LOCATION)이 허용되었는지 확인.
- 권한이 없으면 Permission.RequestUserPermission으로 요청.
- Start에서 사용되므로, 시작 직후에 권한이 없으면 에러가 날 수 있음. 때문에 사용자가 선택할 때까지 대기.
위치 서비스 활성화 확인
if (!Input.location.isEnabledByUser)
{
Debug.Log("========== LOCATION SERVICE DISABLED ==========");
OpenLocationSettings();
yield break;
}
- 사용자가 디바이스의 위치 서비스를 활성화했는지 확인.
- 비활성화 상태라면, Android 설정 화면으로 유도.
위치 데이터 가져오기
Input.location.Start();
int maxWait = 20;
while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0)
{
yield return new WaitForSeconds(1);
maxWait--;
}
- Input.location.Start()를 호출하여 위치 서비스 시작.
- 서비스 초기화에 시간이 걸릴 수 있으므로 최대 20초 대기.
위치 데이터 출력
txt_Latitude.text = $"Latitude: {Input.location.lastData.latitude}";
txt_Longitude.text = $"Longitude: {Input.location.lastData.longitude}";
txt_Altitude.text = $"Altitude: {Input.location.lastData.altitude}";
txt_Accuracy.text = $"Accuracy: {Input.location.lastData.horizontalAccuracy}";
- GPS 데이터를 Input.location.lastData로 가져와 UI(TextMeshPro)에 출력.
- 위도(Latitude), 경도(Longitude), 고도(Altitude), 정확도(Accuracy)를 사용자에게 표시.
설정 화면 이동
void OpenLocationSettings()
{
Debug.Log("Opening location settings...");
Application.OpenURL("package:" + Application.identifier);
}
- 위치 서비스가 꺼져 있을 경우, Android 설정 화면으로 이동하여 사용자가 권한을 부여할 수 있도록 도움.
Unity에서의 구현
이 포스트는 안드로이드 기반 작업에 대한 설명을 다루고 있으며, 저는 Z Flip 3의 해상도에 맞춰 진행하겠습니다. 사용하시는 기기의 해상도는 다를 수 있으니, 각자 자신의 기기 해상도에 맞게 작업해 주시길 권장드립니다.
UI 배치

우리는 위치 정보를 활용하기 위해 위도(Latitude)와 경도(Longitude)를 반드시 확인해야 합니다. 이 두 정보는 필수적으로 필요합니다. 추가적으로, 고도(Altitude)와 정확성(Accuracy, 오차 범위(m))은 정보의 존재 여부를 파악하기 위해 함께 확인하도록 작성하였습니다.
UI 배치는 자유롭게 하셔도 괜찮습니다. 다만, 각 요소가 명확하게 구분되어 잘 보일 수 있도록 배치해 주시길 권장드립니다. 간단한 테스트형 프로젝트라 하더라도 가독성과 사용자 편의를 고려하여 구성하는 연습이 가장 중요합니다.
LocationManager 구현
Hierarchy에서 빈 오브젝트를 생성한 후 이름을 LocationManager로 설정합니다. 이후 이 오브젝트에 LocationManager 스크립트를 추가하고, 각 텍스트 항목에 맞게 Text Object를 연결합니다.
버튼 클릭 이벤트 추가
앱 실행 시 내 위치가 바로 표시되도록 구현되어 있으며, 이후 다른 위치로 이동한 후 갱신된 위치 정보를 확인할 수 있도록 버튼을 추가했습니다. Check My Location 버튼을 누르면 GetMyLocation 함수가 실행되어, 갱신된 위치 정보가 UI에 업데이트되도록 설계되었습니다.
내 위치 정보가 맞는지 확인하기
위 포스트를 잘 따라오셨다면, 앱을 빌드하고 실행할 때 위치 정보 권한 요청 팝업이 표시됩니다. 권한을 허용하면 내 위도, 경도, 고도, 정확도(오차 범위)가 화면에 나타납니다. 이후 위치를 이동한 뒤 버튼을 누르면 갱신된 위치 정보가 업데이트되어 표시됩니다.
앱에서 제공하는 위치 정보의 정확성을 확인하려면, 표시된 위도(Latitude)와 경도(Longitude) 값을 복사하여 Google 지도에서 검색해보세요. 이를 통해 해당 좌표가 실제로 올바른 위치를 나타내는지 확인할 수 있습니다. 검색 형식은 Latitude, Longitude 입니다. 예를 들어 위도가 37.56566이고 경도가 126.9780 이라면, 37.56566, 126.9780 형식으로 검색하시면 됩니다.
GitHub Project URL
'Unity' 카테고리의 다른 글
[Unity] Unity Remote: 빌드 없이 모바일 환경 테스트 시작하기 (1) | 2025.06.08 |
---|---|
[Unity] 스크립터블 오브젝트(Scriptable Object) : 게임 데이터를 효율적으로 관리하는 방법 (0) | 2025.06.08 |
[Unity] 네이버 지도 Dynamic Map API로 마커와 정보 창 구현하기 (2) | 2025.06.08 |
[Unity] 중력 시스템 기초와 응용: 맞바람과 블랙홀 물리 효과 구현 (0) | 2025.06.08 |
[Unity] NavMesh를 활용한 AI 캐릭터 경로 탐색 구현 가이드 (2) | 2025.06.08 |