유니티에서 큰 프로젝트를 하다가 보면
싱글톤패턴이 많아지게 되고 '어쩌다 개발하다보니' 싱글톤들끼리 이리저리 엮이고
그로인하여 분명 특정 기능만 하는 모듈로 만든 싱글톤인데 수정도 어렵고 여기저기
엮여있어서 코드가 뒤죽박죽이 되는 상황을 마주하게 된다.
또한 싱글톤이다보니 딱히 해당 기능을 사용하지도 않는 곳에서도 들고 있어서 마주하는 문제들도 분명 존재했다.
이러한 부분을 최소화하고 코드관리겸 씬에 필요한 기능들을 정리하는데 있어
Dependncy Injection이라고 불리우는 의존성 주입 이라는 툴 중에 가볍다는 VContainer의 가벼운 사용방법을 알아보자.
(한글로 된 사용법이 거의 없어서 ㅜㅜ)
참고로 나는 Zenject도 사용을 해보았고 사용성에 있어서는 둘이 비슷한거 같기도 하고, 뭐가 더 편하다고 하기는 어렵다.
어쩌면 젠젝트쪽이 레퍼런스가 많아서 좀 더 쉬울지도..?
하지만 Vcontainer가 더 가볍다고 하니 하나의 리소스라도 줄여야하는 유니티 입장에서는 더 나을지도...
VContainer의 설치부터 보자.
Unity의 PackageManager -> Install Package from git URL 에다가
https://github.com/hadashiA/VContainer.git?path=VContainer/Assets/VContainer#1.16.8
VContainer/VContainer/Assets/VContainer at master · hadashiA/VContainer
The extra fast, minimum code size, GC-free DI (Dependency Injection) library running on Unity Game Engine. - hadashiA/VContainer
github.com
를 입력한다.
자 그럼 설치가 되었고
나는 시작씬 A가 있는데 B씬으로 넘어가도 의존성을 주입받아 마치 싱글톤패턴을 쓴것같이 사용할 것이다.
자주 사용하는 모듈인 RestAPIManager.cs 를 그렇게 해보도록 하겠다.
우리에게 필요한 스크립트는 다음과 같다.
일단 난 RestAPIManager.cs 를 의존성 주입을 시켜주고 싶기 때문에 MonoBahaviour를 상속받은 클래스 하나를 만들겠다.
그리고 일반 클래스인 AccountManager도 만들어주었다.
//AccountManager.cs
using UnityEngine;
public class AccoutManager
{
private string _id = "";
public void SetID(string id)
{
Debug.Log("SetID: " + id);
_id = id;
}
}
using UnityEngine;
public class RestAPIManager : MonoBehaviour
{
public void SayHello()
{
Debug.Log("Hello from RestAPIManager!");
}
}
A씬에서 사용할 BaseLifetimeInstaller다. Installer는 DI를 사용하려면 어느씬에서나 다 필요하다.
using UnityEngine;
using VContainer;
using VContainer.Unity;
public class BaseInitInstaller : LifetimeScope
{
protected override void Configure(IContainerBuilder builder)
{
builder.RegisterEntryPoint<AccoutManager>().AsSelf();
builder.Register<RestAPIManager>(Lifetime.Singleton);
}
private void Start()
{
DontDestroyOnLoad(this);
}
}
내가 가장 많이 사용하는 RegisterEntryPoint와 Register의 차이를 간략히 설명해보자면...
RegisterEntryPoint의 경우 첫씬에 들어왔을 때 반드시 초기화 작업이 이루어져야 할 경우 많이 사용한다.
AccountManager 를 넣은 이유는 씬 시작시 유저정보를 받아오고 초기화 해주어야 하기 때문이다.
이외에도 로드 해야할 작업이 있다던가, 이벤트 등록을 해주어야 한다던가 하는 작업이 모두 여기에 속한다.
Register의 경우 그외에 일반적으로 싱글톤으로 들고 있어도 되는 부분이다.
뭐 InputManager가 될 수도 있고, 게임 레벨을 관리하는 LevelManager.cs 같은 것이 될 수도 있겠다.
RegisterEntryPoint
• 초기화 시점: 애플리케이션이 시작될 때 실행됩니다.
• 주요 역할: 애플리케이션의 초기화 과정에서 중요한 작업을 수행하는 클래스에 적합합니다.
• 예시: 설정 로드, 서비스 초기화, 이벤트 핸들러 등록 등.
Register
• 초기화 시점: 의존성이 주입될 때 실행됩니다.
• 주요 역할: 애플리케이션 실행 중에 필요한 싱글톤 인스턴스에 적합합니다.
• 예시: 레벨 매니저, 게임 매니저, 데이터베이스 매니저 등.
뭐 이런차이가 있다. 사실상 Register의 경우 사용하려는 씬에서 호출한뒤 사용하는 경우가 많지만
블로그이다 보니 그냥 사용하도록 해보겠다.
자 씬 A에서 이렇게 빈오브젝트에 Installer를 넣어준다. 그럼 끝난다.
참고로 첫씬의 BaseInstaller는 전역적으로 사용되는 의존성 주입을 해주어야하기 때문에 싱글톤과 비슷하게
DontDestroyOnLoad를 해줘야 한다.
씬 B로 가보자
일단 여기서도 SceneBInstaller를 하나 만들어주었다.
새로운 주입을 테스트하기 위하여 SceneB.cs 로 클래스를 하나 등록해두자.
using UnityEngine;
using VContainer;
using VContainer.Unity;
public class SceneBInstaller : LifetimeScope
{
protected override void Configure(IContainerBuilder builder)
{
builder.Register<SceneB>(Lifetime.Singleton);
}
}
SceneB.cs
using UnityEngine;
public class SceneB
{
public void TestSceneB()
{
Debug.Log("SceneB Test");
}
}
이건 뭔진몰라도 SceneB에서만 사용하는 일반 클래스일것이다.
사실 이정도는 그냥 사용할 곳에서 생성자를 만들어서 써도 무방해 보인다 내 생각엔..
자 암튼 이제 주입받은 클래스들을 사용하기 위하여 스크립트를 만들어주었다.
using UnityEngine;
using VContainer;
public class TestManager : MonoBehaviour
{
[Inject] private RestAPIManager _restAPIManager;
[Inject] private AccoutManager _accoutManager;
[Inject] private SceneB _sceneB;
public void onClick_Button()
{
Debug.Log("onClick_Button");
_restAPIManager.SayHello();
_accoutManager.SetID("dduR");
_sceneB.TestSceneB();
}
}
onClick_Button 함수를 버튼 하나를 만들어 연결해주었다.
아직 끝이 아니다.
Base의 DI를 받아오기 위하여 Parent에 해당 Installer를 설정해주어야 한다.
그리고 [Inject]를 사용하는 스크립트는 Auto Inject GameObject 안에 오브젝트를 넣어주자.
여기서는 TestManager.cs가 sayhello 오브젝트에 넣어두었다.
그러고나서
SceneA 에서 SceneManagement를 통하여 간단히 씬이동을 구현후 SceneB에서 버튼을 누르면
내가 등록해 주었던 클래스들이 잘 호출되는 것을 볼 수 있다.
자주 사용하는게 아니고 한 번 세팅해두고 안쓰다보니 적어서 남겨놔야할 필요성이 있어서 남겨놓는 글이다.
'프로그래밍 > Unity' 카테고리의 다른 글
[유니티] Unity - AAR로 안드로이드 Toast와 알림메시지 (notification)구현해보기. (4) | 2025.04.08 |
---|---|
[유니티] Unity - ScriptableObject 잘 사용하기 (feat: json Editor) (0) | 2024.12.27 |
[유니티] Unity - Parallel 병렬처리로 반복작업 속도 향상시키기 (0) | 2024.12.18 |
[유니티] Unity - 코루틴 리턴값 받기와 Action에 대하여. (6) | 2024.12.13 |
[유니티] Unity WebGL - React.js와 쌍방향 통신하기 (2) | 2024.12.11 |