유니티 게임을 모딩하기에 앞서서 유니티 엔진으로 개발되어 빌드하고 배포된 게임들의 폴더 구조를 알아보고자 한다. 먼저 일반적인 유니티 폴더 구조를 시각화하고, 각각의 폴더와 파일이 무슨 역할을 하는지 설명한 다음, 모딩을 할 때 어떤 파일들을 보아야할지 정리하고자 한다.
유니티 게임 우리말화 도구 베타 버전을 공개하였습니다. 이에 관한 설명은 GitHub의 wiki에서 서술합니다. https://github.com/dmc31a42/UnityL10nTool/wiki
유니티 게임의 한글화와 패치 제작 – 서론 으로 돌아가기
본 강좌는 70~80% 완성되면 바로 공개되며, 잘못된 부분이 있으면 그때 그때 수정하는 것으로 하겠습니다. 아래의 강좌 내용은 언제든지 수정될 수 있습니다. 질문은 댓글로 달아주시거나 GitHub(https://github.com/dmc31a42/UnityGameL10nTools/)의 issue를 활용하여주시면 감사하겠습니다.
유니티 게임의 폴더 구조
.| {{Build Name}}.exe ⋯⋯⋯⋯ (1)
.| ︙
.| (etc)
.|
.\-{{Build Name}}_Data ⋯⋯⋯⋯ (2)
. | app.info ⋯⋯⋯⋯ (3)
. | globalgamemanagers ⋯⋯⋯⋯ (4)
. | globalgamemanagers.assets ⋯⋯⋯⋯ (5)
. | level0 ⋯⋯⋯⋯ (6)
. | (level0.resS) ⋯⋯⋯⋯ (7)
. | ︙
. | (level{{N}}) ⋯⋯⋯⋯ (6)
. | (level{{N}}.resS)
. | output_log.txt ⋯⋯⋯⋯ (8)
. | resources.assets ⋯⋯⋯⋯ (9)
. | (resources.assets.resS)
. | ︙
. | sharedassets0.assets ⋯⋯⋯⋯ (10)
. | (sharedassets0.assets.resS)
. | ︙
. | (sharedassets{{N}}.assets)
. | (sharedassets{{N}}.assets.resS)
. | ︙
. | (etc)
. |
. +-Managed ⋯⋯⋯⋯ (11)
. | Assembly-CSharp.dll ⋯⋯⋯⋯ (12)
. | Assembly-CSharp-firstpass.dll ⋯⋯⋯⋯ (12)
. | Assembly-UnityScript.dll ⋯⋯⋯⋯ (12)
. | Mono.Security.dll
. | mscorlib.dll
. | System.Core.dll
. | System.dll
. | UnityEngine.Analytics.dll
. | UnityEngine.dll
. | UnityEngine.dll.mdb
. | UnityEngine.Networking.dll
. | UnityEngine.UI.dll
. | ︙
. | ({{Plugins}}.dll) ⋯⋯⋯⋯ (13)
. | (etc)
. |
. +-Mono ⋯⋯⋯⋯ (14)
. | | mono.dll
. | | MonoPosixHelper.dll
. | |
. | \-etc
. | \-mono
. | | browscap.ini
. | | config
. | |
. | +-1.0
. | | DefaultWsdlHelpGenerator.aspx
. | | machine.config
. | |
. | +-2.0
. | | | DefaultWsdlHelpGenerator.aspx
. | | | machine.config
. | | | settings.map
. | | | web.config
. | | |
. | | \-Browsers
. | | Compat.browser
. | |
. | \-mconfig
. | config.xml
. \-(Plugins) ⋯⋯⋯⋯ (15)
. | ︙
. | (etc)
. \-Resources ⋯⋯⋯⋯ (16)
. | unity default resources
. | unity_builtin_extra
. | ︙
. \-(StreamingAssets) ⋯⋯⋯⋯ (17)
. | ︙
. | (etc)
. \-(etc) ⋯⋯⋯⋯ (18)
각 폴더/파일에 대한 설명
- {{Build Name}}.exe
게임 실행 진입점. {{Build Name}}은 게임을 빌드할 때 정해집니다. - {{Build Name}}_Data
게임 리소스, dll 파일들이 담겨있는 폴더. {{Build Name}}은 위의 실행 진입점과 동일하게 정해집니다. - app.info
게임의 이름과 제작사의 이름이 기록되어있습니다.
‘Application.persistentDataPath’ 폴더(개인 설정, 세이브 파일등이 존재. ‘C:\Users\{{User Name}}\AppData\LocalLow\{{Company Name}}\{{Game Name}}\’)와 Cache 폴더(StreamingAssets가 저장됨. ‘C:\Users\{{User Name}}\AppData\LocalLow\Unity\WebPlayer\Cache\{{Company Name}}_{{Game Name}}\’)의 위치를 정하는데 사용됩니다.
// globalgamemanagers의 PlayerSettings에도 companyName과 productName이 있어서 확인 필요. - globalgamemanagers
유니티 프로젝트의 대부분의 설정이 여기에 담겨있다.- PlayerSettings
‘Application.persistentDataPath’ 폴더(개인 설정, 세이브 파일등이 존재. ‘C:\Users\{{User Name}}\AppData\LocalLow\{{Company Name}}\{{Game Name}}\’)와 Cache 폴더(AssetBundle이 저장됨. ‘C:\Users\{{User Name}}\AppData\LocalLow\Unity\WebPlayer\Cache\{{Company Name}}_{{Game Name}}\’)의 위치를 정하는데 사용되는 변수(‘companyName’,’productName’)가 여기에 담겨있다. - InputManager
- TagManager
- AudioManager
- ScriptMapper
- MonoManager
- GraphicsSettings
- TimeManager
- DelayedCallManager
- PhysicsManager
- BuildSettings
- QualitySeetings
- ResourceManager
런타임 시점의 리소스 로드(Resources.Load(); https://docs.unity3d.com/kr/current/Manual/LoadingResourcesatRuntime.html)시에 리소스의 상대경로(폴더/파일 구조)와 FileID/PathID 경로의 관계가 이 에셋에 저장되어있다.
‘resources.assets’ 파일을 UABE를 통해서 열 때 ‘resources.assets’를 바로 여는 것이 아니라 globalgamemanager 을 열면 ‘resources.assets’도 의존성에 의해서 같이 불러와지고, ‘resources.assets ‘안의 에셋 중 상대 경로로 접근할 수 있는 에셋에 한해서 상대 경로가 ‘Container’ 열에 표시된다. - NetworkManager
- MasterServerInterface
- NavMeshProjectSettings
- Pysics2DSettings
- RuntimeInitializeOnLoadManager
- CloudWebServicesManager
- UnityAnalyticsManager
- UnityConnectSettings
- PerformanceReportingManager
- PlayerSettings
- globalgamemanagers.assets
위의 ‘globalgamemanagers와 다른 파일이다. Shader와 MonoScript에 관한 정보가 있다.
MonoScript에 관한 정보로는 스크립트의 이름, 스크립트의 클래스명, 네임스페이스명, 해당 스크립트가 어느 어셈블리(*.dll)에 있는지가 있다. - level0, level{{N}}
본 게임의 진입 Scene(level)이다. 유니티 엔진은 프로젝트를 빌드할 때 순서가 제일 위에 있는 scene 부터 시작하는 것으로 정해져있다.(https://docs.unity3d.com/kr/current/Manual/PublishingBuilds.html)
level{{N}}파일은 확장자가 *.assets이 아니지만 실제로는 *.assets 파일과 동일한 포멧이다.
{{N}}은 유니티 프로젝트를 빌드할 때 등록한 scene 순서대로 붙여진다. - *.resS
resS 파일은 이름이 동일한 assets 파일에서 Texture(이미지), Audio(음성), 동영상과 같이 상대적으로 용량이 큰 파일들을 assets 파일이 아닌 외부에서 불러올 때(streaming할 때) 사용되는 파일이다. 해당 파일 안에는 streaming할 파일의 원본이 들어가있으며(헤더는 일부 제거되어있을 수 있다), 어느 위치에 어느 파일이 있는지는 assets 파일에 있는 각 asset의 StreamingInfo에 기술되어있다. - output_log.txt
본 log 파일은 게임이 실행될 때 발생하는 로그들이 기록되는 장소이다. 에셋을 수정한 후 적용하고 게임을 실행할 때 정상적으로 실행되지 않는 경우 어느 시점에서 문제가 발생됬는지 대락적으로 확인해볼 수 있는 중요한 파일이다. - resources.assets
resources assets는 각 scene에 종속되지 않지만 유니티 게임 내에서 사용되는 asset들을 모아놓은 assets이다. 위에서 설명한 ‘런타임 시점의 리소스 로드’ 때 사용되는 에셋들이 주로 이 assets에 포함되어있다. 프로젝트의 설정에 따라서 게임 내에서 사용되지 않은 에셋또한 포함될 수 있다. - sharedassets0.assets, sharedassets{{N}}.assets
sharedassets{{N}} assets은 각 level{{N}}에서 사용하는 에셋들이 들어있다. {{N}}에 들어가는 숫자는 level의 {{N}}과 1:1 대응된다.
만약 level0에서도 쓰이고 level1에서 동일한 에셋이 사용된다면 sharedassets1.assets 는 sharedassets0.assets를 참조하게 된다.
level1에 존재하는 GameObject가 level0에 존재하는 GameObject의 Component를 참조하게된다면 sharedassets1.assets은 sharedassets0.assets를 참조하는 종속성을 가진다.(윗문장과 본문장은 정확히 확인해보지 못해서 일단 취소선처리) - Managed 폴더
유니티의 실행코드는 컴파일 후 managed code로 변환된다. 이러한 managed code들(*.dll 파일들)이 저장되어있는 장소가 ‘Managed’ 폴더이다. ‘Reflector’를 통해서 유니티 프로젝트에 사용된 MonoScript들의 원형을 어렴풋이 확인할 수 있다. 차후에 배울 UABE 2.2버전 이상, UABE.NET에서는 본 폴더를 불러와 MonoBehaviour 에셋을 확인할 수 있다. (본 강좌를 작성하기 전 스스로 공부할 시기에는 UABE가 2.1 버전일 때여서 MonoBehaviour를 UABE에서 확인할 수 없었지만, 강좌를 작성하고 있는 시점에서는 2.2로 업데이트되면서 MonoBehaviour 에셋을 확인할 수 있게됨.) - Assembly-CSharp-firstpass.dll, Assembly-CSharp.dll, Assembly-UnityScript.dll, Assembly-Boo-firstpass.dll …etc
=Assembly-{{Programming language}}(-firstpass).dll
Assembly 파일들은 유니티 프로젝트 안에 있는 스크립트들이 컴파일되어있는 파일들이다. 유니티에서 사용할 수 있는(그리고, 있었던) 언어들인 CSharp, UnityScript(JavaScript 기반), Boo 언어에 따라서 {{Programming language}}에 프로그래밍 언어가 각각 들어간 어셈블리 파일이 생성되고, ‘Standard Assets’ 폴더에 있어서 우선적으로 컴파일되고 실행시에도 우선적으로 불러와지는 스크립트는 끝에 ‘-firstpass’ 가 붙는 별도의 파일로 생성된다.(https://docs.unity3d.com/Manual/SpecialFolders.html)
플러그인(우리가 다루게 될 ‘TextMesh Pro’, ‘2D ToolKit’,‘NGUI’등)도 소스가 제공이 되는 플러그인의 경우 컴파일된 결과는 Assembly에 저장된다. - ({{Plugins}}.dll)
위의 Assembly와 달리 유니티 프로젝트에서 소스가 제공되지 않는 플러그인을 사용하였을 경우 해당 플러그인에서 제공하는 *.dll 파일이 Managed 폴더로 복사된다. - Mono 폴더
유니티가 사용하는 Mono 가상머신에 관련된 폴더. - (Plugins)
유니티 프로젝트 최상위 폴더에 Plugins 폴더에 있는 소스를 컴파일 한 결과물 또는 *.dll로 제공되는 플러그인들이 들어있는 폴더. 유니티 외부에서 제공되는 플러그인들들을 유니티 게임에 포함하고 싶을 때 사용. 자세한 사항은 https://docs.unity3d.com/kr/current/Manual/SpecialFolders.html 의 ‘플러그인(Plug-ins)’ 단락과 https://docs.unity3d.com/kr/current/Manual/Plugins.html 참고 - Resources
유니티에서 기본적으로 제공되는 Texture, Material, Font, Mesh, Sprite, Shader, MonoScript/MonoBehaviour 등이 들어있는 ‘unity default resources’ assets과 Shader가 들어있는 ‘unity_builtin_extra’ assets이 있다. - StreamingAssets
assets에 통합되지 않고 원래 포맷의 별도 파일로 사용하고 싶을 때 사용하는 폴더. 외부 언어 파일로 텍스트를 불러오는 경우 경우 이 폴더에 외부 언어 파일이 있을 가능성이 있다. 참고로 웹에서 받아오는 StreamingAssets의 경우, 이 폴더에 존재하는 것이 아닌 별도의 경로가 있으니 주의.
https://docs.unity3d.com/kr/current/Manual/SpecialFolders.html 의 ‘StreamingAssets’ 단락 및 https://docs.unity3d.com/kr/current/Manual/StreamingAssets.html 참고 - (etc); 그 외의 폴더
유니티 엔진은 assets 외에 StreamingAssets 처럼 별도의 파일을 사용할 때 임의의 폴더를 직접 접근할 수 있게 되어있다. 이를 통하여 특정한 파일들을 특정한 폴더에 담아두고 게임 내에서 동적으로 로드하여 개발된 게임도 존재한다. 외부 언어 파일로 텍스트를 불러오는 경우 이 폴더들 중 한 군데에 있을 가능성이 있다.
StreamingAssets
(별도의 문서에서 통합됨)
본래는 StreamingAssets이 어떻게 작동하는지 확인하기 확인하고 난 다음 작성하려했지만 대충 어느 폴더에 있는지는 알려주기 위하여 간단하게 작성한 후 나중에 보완하고자한다.
StreamingAssets에서 사용되는 모든 경로는 globalgamemanagers.assets 파일의 PlayerSettings 에셋에 있는 ‘companyName’, ‘productName’ 필드의 값 또는, app.info 파일의 첫줄(Company Name)과 둘째줄(Product Name)에 있는 정보를 바탕으로 설정된다. 만약 Company Name과 Product Name에 폴더명으로 사용할 수 없는 문자가 있다면 ‘_’로 대체된다.
그리고 User Name은 Windows 운영체제에 로그인한 사용자의 이름이다. 통상적으로는 C:\Users (한글 윈도우에서는 C:\사용자 로 표기되기도 함) 안에 Public(공용) 폴더외에 나머지 폴더이다.
Application.persistentDataPath
경로:
C:\Users\{{User Name}}\AppData\LocalLow\{{Company Name}}\{{Product Name}}\
Webplayer cache
경로:
C:\Users\{{User Name}}\AppData\LocalLow\Unity\WebPlayer\Cache\{{Company Name}}_{{Product Name}}\
종합
- 에셋형태로 존재하는 언어 파일은 resources.assets, sharedassets0.assets에서 찾아보면 대부분 찾을 수 있다.
- 외부에 존재하는 언어 파일은 위에 나와있는 폴더/파일 이외에 특이한 폴더/파일이 언어 파일일 가능성이 높다.
- 스크립트는 Managed 폴더에 있는 dll들을 ‘reflector’로 분석해보면 살펴볼 수 있다.
- 모딩할 때 게임 실행이 실패한다면 output_log.txt를 살펴보자.
- 위의 방법을 사용해봐도 언어 파일을 찾을 수 없다면 다음 절 ‘StreamingAssets’를 참조해보자.
완전 프로그래밍 문외한 수준인데 한번 시도해보려고 이것저것 뒤지다 찾게되었습니다. 너무 자세하게 잘 설명되어 있어서 큰 도움이 될거 같아요. 감사합니다. 다음글 너무 기다리고 있습니다. ㅠㅠ
좋아요좋아요
The elder scroll : legend 라는 카드게임의 한글화를 혼자서 그냥 막무가내로 도전해는 중입니다. 프로그래밍 지식이 전무한 상황이라 너무 막막하네요
좋아요좋아요
일단 본 강좌가 완전히 마무리될때까지 1개월이 걸릴것으로 예상되고, 바로 도움이 필요하시면 모두에게 참고가 될 수 있도록 https://github.com/dmc31a42/UnityGameL10nTools/ 에서 이슈를 만들어주시면 거기에서 답변을 드리겠습니다.
좋아요좋아요
중학생 때부터 게임과 번역에 관심이 많았습니다. 많은 사람들이 좋은 게임을 즐길 수 있도록 올해 대학교에 붙는다면 열씸히 공부하겠습니다. 이런 강의 공유해 주셔서 정말 감사하다는 말씀 꼭 드리고 싶습니다. 비록 지금은 안되지만 언젠가 꼭 하고 싶습니다. 아마 올해 겨울에 할머니 댁에서 시작 할 것 같습니다. 정말 감사합니다.
좋아요좋아요
맞춤법 틀린 것 지적해주세요.
좋아요좋아요
모바일 게임의 경우는 어떻게 할 수 있을까요?
좋아요좋아요
안드로이드는 https://github.com/dmc31a42/UnityL10nTool/issues/31 이 글을 참고해보시고,
iOS는 아직 파악한 것이 없습니다.
좋아요좋아요