Prefab 하나로 Data에 따라 Sprite나 Animation 등을 바꿔주며 다른 Object가 되도록 설정할 수 있도록 구현하기 위해 Data와 Resource를 구분하였다. 프로젝트에서 내가 맡은 부분은 Resource로 리소스를 불러오고 외부에서 리소스를 사용하라 수 있도록 했다.

 

구현 방법

소규모 프로젝트에서는 Resources.Load 방식으로 구현하는 것이 더 간단하기 때문에 모든 리소스를 Resources 폴더에 넣고 Resources.Load 또는 Resources.LoadAll 함수를 통해 리소스를 불러오는 방식을 택하였다. 

 

구현 기능

게임 시작 시 게임에 Resource 경로에서 필요한 리소스(Sprite, Prefab, JsonData, Animation)를 불러온다.

Initialize( ): 리소스를 불러올 경로를 지정하여 Dictionary에 추가한다. 현재 Sprites의 경로가 지정되어 있지 않기 때문에 후에 수정해야 한다.

Load~( ): Dictionary의 key값으로 리소스가 있는지 확인 후, 리턴한다.

Instantiate( ): 오브젝트가 풀 안에 있는지 확인 후, parent 하위에 prefab을 생성하거나 내보낸다.

Destroy( ): 필요 없는 오브젝트를 파괴한다.

public class ResourceManager : MonoBehaviour
{
    private Dictionary<string, Sprite> _sprites = new();
    private Dictionary<string, GameObject> _prefabs = new();
    private Dictionary<string, TextAsset> _jsonData = new();
    private Dictionary<string, RuntimeAnimatorController> _animControllers = new();

    public void Initialize()
    {
        Sprite[] sprites = Resources.LoadAll<Sprite>("Sprites/"); // TODO: 경로 지정.
        foreach (Sprite sprite in sprites)
        {
            _sprites.Add(sprite.name, sprite);
        }

        GameObject[] objs = Resources.LoadAll<GameObject>("Prefabs");
        foreach (GameObject obj in objs)
        {
            _prefabs.Add(obj.name, obj);
        }

        TextAsset[] texts = Resources.LoadAll<TextAsset>("JsonData");
        foreach (TextAsset t in texts)
        {
            _jsonData.Add(t.name, t);
        }

        RuntimeAnimatorController[] controllers = Resources.LoadAll<RuntimeAnimatorController>("Animations");
        foreach (RuntimeAnimatorController controller in controllers)
        {
            _animControllers.Add(controller.name, controller);
        }
    }

    // 리소스가 있는지 확인.
    public GameObject LoadPrefab(string key)
    {
        if (!_prefabs.TryGetValue(key, out GameObject prefab))
        {
            Debug.LogError($"[ResourceManager] LoadPrefab({key}): Failed to load prefab.");
            return null;
        }
        return prefab;
    }
    public Sprite LoadSprite(string key)
    {
        if (!_sprites.TryGetValue(key, out Sprite sprite))
        {
            Debug.LogError($"[ResourceManager] LoadSprite({key}): Failed to load sprite.");
            return null;
        }
        return sprite;
    }
    public TextAsset LoadJsonData(string key)
    {
        if (!_jsonData.TryGetValue(key, out TextAsset data))
        {
            Debug.LogError($"[ResourceManager] LoadJsonData({key}): Failed to load jsonData.");
            return null;
        }
        return data;
    }
    public RuntimeAnimatorController LoadAnimController(string key)
    {
        if (!_animControllers.TryGetValue(key, out RuntimeAnimatorController controller))
        {
            Debug.LogError($"[ResourceManager] LoadJsonData({key}): Failed to load animController.");
            return null;
        }
        return controller;
    }

    // 오브젝트가 풀 안에 있는지 없는지 확인 후 생성.
    public GameObject Instantiate(string key, Transform parent = null, bool pooling = false)
    {
        GameObject prefab = LoadPrefab(key);
        if (prefab == null)
        {
            Debug.LogError($"[ResourceManager] Instantiate({key}): Failed to load prefab.");
            return null;
        }

        if (pooling) return Main.Pool.Pop(prefab);

        GameObject obj = GameObject.Instantiate(prefab, parent);
        obj.name = prefab.name;
        return obj;
    }

    // 필요없는 오브젝트 파괴.
    public void Destroy(GameObject obj)
    {
        if (obj == null) return;

        if (Main.Pool.Push(obj)) return;

        Object.Destroy(obj);
    }
}

 

 

+ Recent posts