quot;Created folder: {folder}"); } } AssetDatabase.Refresh(); Debug.Log("Project structure created successfully!"); } } ``` --- ## 3️⃣ 필수 패키지 설치 ### Package Manager 설정 ```json // Packages/manifest.json { "dependencies": { "com.cysharp.unitask": "2.5.4", "com.cysharp.messagepipe": "1.8.1", "jp.hadashikick.vcontainer": "1.15.4", "com.google.protobuf": "3.21.12", "com.unity.inputsystem": "1.7.0", "com.unity.addressables": "1.21.19", "com.unity.test-framework": "1.3.9" }, "scopedRegistries": [ { "name": "Cysharp", "url": "https://package.openupm.com", "scopes": [ "com.cysharp" ] }, { "name": "VContainer", "url": "https://package.openupm.com", "scopes": [ "jp.hadashikick" ] } ] } ``` ### R3 (UniRx) 설치 ```bash # Git Package로 설치 Window → Package Manager → + → Add package from git URL https://github.com/Cysharp/R3.git?path=src/R3.Unity#2.4.0 ``` ### 패키지 설치 확인 스크립트 ```csharp // Editor/PackageValidator.cs using UnityEngine; using UnityEditor; public class PackageValidator : EditorWindow { [MenuItem("Tools/Validate Packages")] public static void ValidatePackages() { string[] requiredPackages = { "com.cysharp.unitask", "com.cysharp.messagepipe", "jp.hadashikick.vcontainer", "com.google.protobuf", "com.unity.inputsystem" }; bool allInstalled = true; foreach (string package in requiredPackages) { if (!HasPackage(package)) { Debug.LogError(quot;Missing package: {package}"); allInstalled = false; } else { Debug.Log(quot;✓ Package installed: {package}"); } } if (allInstalled) { Debug.Log("All required packages are installed!"); } else { Debug.LogError("Some packages are missing. Please install them."); } } private static bool HasPackage(string packageName) { var request = UnityEditor.PackageManager.Client.List(); while (!request.IsCompleted) { } foreach (var package in request.Result) { if (package.name == packageName) return true; } return false; } } ``` --- ## 4️⃣ 기본 아키텍처 설정 ### VContainer DI 설정 ```csharp // Core/DI/GameLifetimeScope.cs using VContainer; using VContainer.Unity; using UnityEngine; public class GameLifetimeScope : LifetimeScope { [SerializeField] private GameSettings _gameSettings; [SerializeField] private PlayerModel _playerModel; protected override void Configure(IContainerBuilder builder) { // Settings builder.RegisterInstance(_gameSettings); // Models builder.RegisterInstance(_playerModel).As<IPlayerModel>(); // Services builder.Register<GameManager>(Lifetime.Singleton); builder.Register<AudioManager>(Lifetime.Singleton); builder.Register<InputManager>(Lifetime.Singleton); // MessagePipe builder.AddMessagePipe(); Debug.Log("DI Container configured successfully!"); } } ``` ### 기본 ScriptableObject 생성 ```csharp // ScriptableObjects/GameSettings.cs using UnityEngine; [CreateAssetMenu(fileName = "GameSettings", menuName = "Game/Settings")] public class GameSettings : ScriptableObject { [Header("Audio Settings")] public float masterVolume = 1.0f; public float musicVolume = 0.8f; public float sfxVolume = 1.0f; [Header("Graphics Settings")] public bool vSyncEnabled = true; public int targetFrameRate = 60; [Header("Debug Settings")] public bool showDebugInfo = false; public LogLevel logLevel = LogLevel.Info; } public enum LogLevel { None = 0, Error = 1, Warning = 2, Info = 3, Debug = 4 } ``` ### Bootstrap Scene 설정 ```csharp // Core/Bootstrap.cs using UnityEngine; using UnityEngine.SceneManagement; using VContainer.Unity; using Cysharp.Threading.Tasks; public class Bootstrap : MonoBehaviour { [SerializeField] private string nextSceneName = "MainMenu"; private async void Start() { await InitializeGame(); await LoadNextScene(); } private async UniTask InitializeGame() { Debug.Log("Initializing game systems..."); // 기본 Unity 설정 Application.targetFrameRate = 60; Screen.sleepTimeout = SleepTimeout.NeverSleep; // DI Container 초기화는 GameLifetimeScope에서 자동으로 처리 await UniTask.Delay(1000); // 초기화 시뮬레이션 Debug.Log("Game systems initialized!"); } private async UniTask LoadNextScene() { Debug.Log(quot;Loading scene: {nextSceneName}"); await SceneManager.LoadSceneAsync(nextSceneName); } } ``` --- ## 5️⃣ IDE 설정 ### Visual Studio 설정 ```xml <!-- .editorconfig --> root = true [*.cs] indent_style = space indent_size = 4 end_of_line = crlf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true # Unity naming conventions dotnet_naming_rule.unity_serialized_field_rule.severity = warning dotnet_naming_rule.unity_serialized_field_rule.symbols = unity_serialized_field dotnet_naming_rule.unity_serialized_field_rule.style = camel_case_underscore_prefix dotnet_naming_symbols.unity_serialized_field.applicable_kinds = field dotnet_naming_symbols.unity_serialized_field.applicable_accessibilities = private dotnet_naming_symbols.unity_serialized_field.required_modifiers = dotnet_naming_style.camel_case_underscore_prefix.required_prefix = _ dotnet_naming_style.camel_case_underscore_prefix.capitalization = camel_case ``` ### Rider 설정 ```json // .idea/codeStyleSettings.xml { "unity_naming_conventions": { "serialized_fields": { "prefix": "_", "style": "camelCase" }, "public_fields": { "style": "PascalCase" }, "methods": { "style": "PascalCase" } } } ``` --- ## 6️⃣ 첫 번째 기능 구현 ### 간단한 MVVM 예제 - HelloWorld ```csharp // Features/Common/Models/HelloWorldModel.cs using R3; [CreateAssetMenu(fileName = "HelloWorldModel", menuName = "Game/HelloWorld")] public class HelloWorldModel : ScriptableObject { private ReactiveProperty<string> _message = new("Hello, Unity MVVM!"); public ReadOnlyReactiveProperty<string> Message => _message; public void UpdateMessage(string newMessage) { _message.Value = newMessage; } } ``` ```csharp // Features/Common/ViewModels/HelloWorldViewModel.cs using R3; using VContainer; public class HelloWorldViewModel : System.IDisposable { [Inject] private HelloWorldModel _model; public ReadOnlyReactiveProperty<string> DisplayMessage { get; private set; } public ReactiveCommand UpdateMessageCommand { get; private set; } private readonly CompositeDisposable _disposables = new(); public void Initialize() { DisplayMessage = _model.Message.ToReadOnlyReactiveProperty().AddTo(_disposables); UpdateMessageCommand = new ReactiveCommand().AddTo(_disposables); UpdateMessageCommand.Subscribe(_ => _model.UpdateMessage("Updated!")).AddTo(_disposables); } public void Dispose() { _disposables?.Dispose(); } } ``` ```csharp // Features/Common/Views/HelloWorldView.cs using UnityEngine; using UnityEngine.UI; using R3; using VContainer; public class HelloWorldView : MonoBehaviour { [SerializeField] private Text _messageText; [SerializeField] private Button _updateButton; [Inject] private HelloWorldViewModel _viewModel; private readonly CompositeDisposable _disposables = new(); private void Start() { _viewModel.Initialize(); // Data Binding _viewModel.DisplayMessage .Subscribe(message => _messageText.text = message) .AddTo(_disposables); // Command Binding _updateButton.onClick.AsObservable() .Subscribe(_ => _viewModel.UpdateMessageCommand.Execute()) .AddTo(_disposables); } private void OnDestroy() { _disposables?.Dispose(); } } ``` --- ## 7️⃣ 검증 및 테스트 ### 설정 검증 체크리스트 - [ ] Unity 2022.3 LTS 이상으로 프로젝트 생성 - [ ] 폴더 구조가 모듈화 구조로 생성됨 - [ ] 모든 필수 패키지 설치 완료 - [ ] VContainer DI 컨테이너 동작 확인 - [ ] Bootstrap 씬에서 초기화 성공 - [ ] HelloWorld MVVM 예제 동작 확인 ### 기본 테스트 실행 ```csharp // Tests/EditMode/ArchitectureTests.cs using NUnit.Framework; using VContainer; public class ArchitectureTests { [Test] public void DI_Container_Should_Be_Configured() { var builder = new ContainerBuilder(); var scope = new GameLifetimeScope(); Assert.DoesNotThrow(() => scope.Configure(builder)); } [Test] public void MVVM_Components_Should_Be_Available() { Assert.IsNotNull(typeof(HelloWorldModel)); Assert.IsNotNull(typeof(HelloWorldViewModel)); Assert.IsNotNull(typeof(HelloWorldView)); } } ``` --- ## 🚀 다음 단계 ### 즉시 시작 가능한 개발 1. **새로운 기능 모듈 추가**: Features 폴더에 기능별 모듈 생성 2. **UI 시스템 확장**: UGUI 기반 MVVM UI 컴포넌트 개발 3. **데이터 시스템 구축**: ScriptableObject 기반 게임 데이터 관리 4. **네트워크 통신**: Protobuf 기반 서버 통신 구현 ### 권장 학습 순서 1. [Code Architecture Guide](Code_Architecture_Guide.md) - MVVM 패턴 심화 2. [Data Architecture](Data_Architecture.md) - 데이터 관리 전략 3. [Protobuf Integration Guide](Protobuf_Integration_Guide.md) - 네트워크 통신 --- **🎉 축하합니다! Unity MVVM 프로젝트 기본 설정이 완료되었습니다.** 이제 체계적이고 확장 가능한 Unity 게임 개발을 시작할 수 있습니다! --- *최종 업데이트: 2024-01-03* *작성자: Unity Setup Team*