개발 기록/[CTSG] 25.06.01-

[디지털 트윈] OSM 데이터를 Unity 3D에 불러오기

Dachaes 2025. 6. 9. 10:32
728x90

OSM 데이터를 Unity 3D에 불러오기 

디지털 트윈 프로젝트를 위해 OSM2World를 활용하여 OpenStreetMap(OSM) 데이터를 가져와 Unity 상에서 3D 환경으로 구현해보고자 했습니다.

개발 환경

  • Node v22.16.0
  • React v19.1.0 (TypeScript) + Vite
  • Unity 6000.0.50f1 (LTS)
  • OSM2World (Java 기반 도구)
    • JDK 21.0.7
    • Apache Maven

개발 순서

  1. OSM 파일 다운로드하기
  2. Maven 설치하기
  3. OSM2World 프로젝트 다운로드하기
  4. OSM2World 으로 .osm 파일을 .obj 파일과 .obj.mtl 파일로 변환하기
  5. 유니티 프로젝트 생성하기
  6. 유니티에 변환한 파일을 불러오기
  7. 유니티 프로젝트 빌드하기
  8. WebGL로 웹 프로젝트에 띄우기

참고 사이트

 


1. OSM 파일 다운로드하기

OSM 데이터란?

OpenStreetMap은 전 세계 지도 데이터를 담고 있는 오픈소스 프로젝트입니다. .osm 확장자 파일은 XML 구조로 도로, 빌딩, 공원, 나무 등의 정보를 담고 있습니다.

OSM 파일 다운로드

OSM 공식 사이트 https://www.openstreetmap.org/ 에서 관심 지역으로 이동한 후, 내보내기(Export)합니다.

 


2.  Maven 설치하기 (Windows 기준)

OSM2World를 빌드하려면 Maven이 필요합니다. Java 프로젝트의 패키징 도구로, mvn package 명령을 쓸 수 있게 해줍니다.

Maven 다운로드

압축 해제

  • 예: C:\dev\maven\apache-maven-3.9.10 등
  • 디렉토리 안에 bin\mvn.cmd 파일이 있는지 확인

환경 변수 설정

  1. Win + S → "시스템 환경 변수 편집" 검색 → 실행
  2. 환경 변수 > 시스템 변수 > Path 편집 > 새로 만들기
  3. C:\Users\User\Desktop\maven\mvn\bin
  4. 확인 후 cmd 새로 열기

 


3.  OSM2World 사용하기

Java 기반의 오픈소스 OSM2World를 사용하면 .osm → .obj 변환이 가능합니다.

설치 (프로젝트 클론 및 빌드)

git clone https://github.com/tordanik/OSM2World.git
cd OSM2World
mvn clean package -DskipTests
OSM2World/desktop/target/osm2world.jar 이 생성됩니다.

변환

다운 받았던 osm파일을 해당 폴더(OSM2World/desktop/target/)에 이동한 후, 아래의 명령어를 실행합니다.
java -jar osm2world-desktop-0.5.0-SNAPSHOT.jar convert -i map.osm -o map.obj

map.obj, map.mtl 등이 생성됩니다.

 


4.  Unity에서 .obj 불러오기

유니티 프로젝트 생성

Unity 프로젝트의 /Assets/Models/ 폴더에 .obj 파일, .mtl 파일 복사

Unity 에디터에서 해당 .obj 파일 드래그 & 드롭

참고

  • 머티리얼이 핑크색일 경우 → Shader나 텍스처 연결 확인
  • 렌더링 이상할 경우 → Directional Light와 Skybox 설정

빌드

 

File > Build Profiles 에서 Platforms > Web 이 Active 인지 확인하고, 아니면 Switch Platform 을 합니다.

Active 상태라면 Build 합니다.

 


5.  WebGL로 웹 프로젝트에 띄우기

유니티에서 빌드한 파일들을 React 의 public/ 폴더에 복사 

React에서 컴포넌트 작성

import { useEffect } from "react";
import { Unity, useUnityContext } from "react-unity-webgl";
import styles from "./UnitySimulation.module.scss"

const UnitySimulation = ({
  unityId,
  buildPath,
  onUnityLoaded,  
}: {
  unityId: string;
  buildPath: string;
  onUnityLoaded: (id: string, sendMessage: Function) => void;  
}) => {

  // ✅ 시뮬레이션할 유니티 빌드 파일 경로 지정
  const { unityProvider, sendMessage, isLoaded } = useUnityContext({
    loaderUrl: `${buildPath}/Build/build.loader.js`,
    dataUrl: `${buildPath}/Build/build.data.br`,
    frameworkUrl: `${buildPath}/Build/build.framework.js.br`,
    codeUrl: `${buildPath}/Build/build.wasm.br`,
  });

  // ✅ 해당 유니티 시뮬레이션 로딩 완료 시, ResultPage 의 unitymap 에 전달
  useEffect(() => {
    if (isLoaded) {
      onUnityLoaded(unityId, sendMessage);
    }
  }, [isLoaded]);

  return (
    <div>
      {!isLoaded && 
      <div className={styles.container}>
        <img src="/loading/loading.png" className={styles.loading} />
      </div>
      }
      <Unity
        unityProvider={unityProvider}
        style={{ width: "100%", height: "100%", borderRadius: "8px" }}
      />
    </div>
  );
};

export default UnitySimulation;

확인

npm run dev

 


 

728x90