odyssey

#10 odyssey 개발일지 : 오브젝트 풀링 분리

san10 2023. 5. 7. 01:23

저번 글에 이어서

오브젝트 풀링을 하는 부분은 떼어서 따로 분리하려고 한다.

 

기존 TerrainManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Pool;

public class TerrainManager : MonoBehaviour
{
    public ObstacleGenerator obstacleGenerator;

    public List<Terrain> terrainPrefabs = new List<Terrain>();
    public List<TerrainData> terrainDatas = new List<TerrainData>();
    public TerrainPool terrainPool = new TerrainPool();

    private Dictionary<TerrainType, ObjectPool<Terrain>> terrainPoolDictionary;

    public Vector3 previousTerrainEndPoint=Vector3.zero; // endPoint알아내기용

    private float time;

    void Start()
    {
        
        terrainPoolDictionary = new Dictionary<TerrainType, ObjectPool<Terrain>>();
        int i = 0;
        foreach (Terrain terrain in terrainPrefabs)
        {
            TerrainType terrainType = (TerrainType)i;
            ObjectPool<Terrain> objectPool = new ObjectPool<Terrain>(
                () => CreateTerrain(terrain, terrainType),
                OnGet,
                OnRelease,
                OnDestroy,
                maxSize: 10
                );
                                                            
            terrainPoolDictionary.Add(terrainType, objectPool);
            i++;
            
        }
        TerrainGenerator();
    }

    private Terrain CreateTerrain(Terrain terrain,TerrainType type)
    {
        Terrain t = Instantiate(terrain);
        t.SetPool(terrainPoolDictionary[type]);
        return t;
    }

    private void OnGet(Terrain terrain)
    {
        terrain.gameObject.SetActive(true);
    }

    private void OnRelease(Terrain terrain)
    {
        terrain.time = 0;
        terrain.gameObject.SetActive(false);
    }

    private void OnDestroy(Terrain terrain)
    {
        Destroy(terrain);
    }

    public void TerrainGenerator()
    {
        TerrainType selectedTerrain = (TerrainType)UnityEngine.Random.Range(0, System.Enum.GetValues(typeof(TerrainType)).Length);


        switch (selectedTerrain)
        {
            case TerrainType.Plane1:
                {
                    Vector3 terrainPoint = previousTerrainEndPoint - terrainDatas[0].terrainStartLocalPoint;
                    Terrain Plane1 = terrainPoolDictionary[selectedTerrain].Get();
                    Plane1.transform.position = terrainPoint;
                    previousTerrainEndPoint = Plane1.transform.TransformPoint(terrainDatas[0].terrainEndLocalPoint);
                }
                break;

            case TerrainType.Plane2:
                {
                    Vector3 terrainPoint = previousTerrainEndPoint - terrainDatas[1].terrainStartLocalPoint;
                    Terrain Plane2 = terrainPoolDictionary[selectedTerrain].Get();
                    Plane2.transform.position = terrainPoint;
                    previousTerrainEndPoint = Plane2.transform.TransformPoint(terrainDatas[1].terrainEndLocalPoint);
                }
                break;

            case TerrainType.Steep1:
                {
                    Vector3 terrainPoint = previousTerrainEndPoint - terrainDatas[2].terrainStartLocalPoint;
                    Terrain Steep1 = terrainPoolDictionary[selectedTerrain].Get();
                    Steep1.transform.position = terrainPoint;
                    previousTerrainEndPoint = Steep1.transform.TransformPoint(terrainDatas[2].terrainEndLocalPoint);
                }
                break;
        }
        
    }

    void FixedUpdate()
    {
        time += Time.deltaTime;
        if (time >=5f)
        {
            TerrainGenerator();
            time = 0;
        }
    }
  
}

 

여기서 오브젝트 풀링하는 부분은 TerrainPool이라는 클래스로 분리할 것이다!

 

TerrainPool

using UnityEngine.Pool;
using System.Collections.Generic;
using UnityEngine;

public class TerrainPool : MonoBehaviour
{
    public Dictionary<TerrainType, ObjectPool<Terrain>> terrainPoolDictionary;
    public List<Terrain> terrainPrefabs = new List<Terrain>();

    void Start()
    {
        terrainPoolDictionary = new Dictionary<TerrainType, ObjectPool<Terrain>>();
        int i = 0;
        foreach (Terrain terrain in terrainPrefabs)
        {
            TerrainType terrainType = (TerrainType)i;
            ObjectPool<Terrain> objectPool = new ObjectPool<Terrain>(
                () => CreateTerrain(terrain, terrainType),
                OnGet,
                OnRelease,
                OnDestroy,
                maxSize: 10
                );

            terrainPoolDictionary.Add(terrainType, objectPool);
            i++;

        }
    }

    private Terrain CreateTerrain(Terrain terrain, TerrainType type)
    {
        Terrain t = Instantiate(terrain);
        t.SetPool(terrainPoolDictionary[type]);
        return t;
    }

    private void OnGet(Terrain terrain)
    {
        terrain.gameObject.SetActive(true);
    }

    private void OnRelease(Terrain terrain)
    {
        terrain.time = 0;
        terrain.gameObject.SetActive(false);
    }

    private void OnDestroy(Terrain terrain)
    {
        Destroy(terrain);
    }

    public Terrain GetTerrain(TerrainType key)
    {
        return terrainPoolDictionary[key].Get();
    }

}

기존 코드에서 풀링하는 부분만 떼어서 만들었다!

 

TerrainManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TerrainManager : MonoBehaviour
{
    public ObstacleGenerator obstacleGenerator;
    public TerrainPool terrainPool;

    public List<TerrainData> terrainDatas = new List<TerrainData>();
    public Vector3 previousTerrainEndPoint=Vector3.zero; // endPoint알아내기용
    private float time;

    void Start()
    {
        TerrainGenerator();
    }

    public void TerrainGenerator()
    {
        TerrainType selectedTerrain = (TerrainType)UnityEngine.Random.Range(0, System.Enum.GetValues(typeof(TerrainType)).Length);


        switch (selectedTerrain)
        {
            case TerrainType.Plane1:
                {
                    Vector3 terrainPoint = previousTerrainEndPoint - terrainDatas[0].terrainStartLocalPoint;
                    Terrain Plane1 = terrainPool.GetTerrain(selectedTerrain);
                    Plane1.transform.position = terrainPoint;
                    previousTerrainEndPoint = Plane1.transform.TransformPoint(terrainDatas[0].terrainEndLocalPoint);
                }
                break;

            case TerrainType.Plane2:
                {
                    Vector3 terrainPoint = previousTerrainEndPoint - terrainDatas[1].terrainStartLocalPoint;
                    Terrain Plane2 = terrainPool.GetTerrain(selectedTerrain);
                    Plane2.transform.position = terrainPoint;
                    previousTerrainEndPoint = Plane2.transform.TransformPoint(terrainDatas[1].terrainEndLocalPoint);
                }
                break;

            case TerrainType.Steep1:
                {
                    Vector3 terrainPoint = previousTerrainEndPoint - terrainDatas[2].terrainStartLocalPoint;
                    Terrain Steep1 = terrainPool.GetTerrain(selectedTerrain);
                    Steep1.transform.position = terrainPoint;
                    previousTerrainEndPoint = Steep1.transform.TransformPoint(terrainDatas[2].terrainEndLocalPoint);
                }
                break;
        }
        
    }

    void FixedUpdate()
    {
        time += Time.deltaTime;
        if (time >=5f)
        {
            TerrainGenerator();
            time = 0;
        }
    }

}

 

이제 TerrainManager에서 오브젝트 풀링으로 지형을 생성할 일이 있으면

TerrainPool의 GetTerrain()을 호출한다..