【Unity】 손쉽게 객체 풀을 구현할 수 있는 PoolableMonoBehaviour 소개

17963 단어 ObjectPoolUnity

✒ 배경



쉽게 객체 풀을 구현할 수 있는 PoolableMonoBehaviour 를 만들었으므로 소개합니다.

편한 포인트
  • 풀은 모두 ObjectPool , 풀에 세트 하는 것은 모두 PoolableMonoBehaviour 이므로, 선언이 편하다
  • 개체 단독으로 풀로 돌아갈 수 있으므로 관리가 편합니다

  • 📄 코드



    PoolableMonoBehaviour.cs는 추상 클래스입니다. 상속된 클래스를 반복적으로 사용하는 객체에 추가하여 사용합니다.

    PoolableMonoBehaviour.cs
    using UnityEngine;
    
    public abstract class PoolableMonoBehaviour : MonoBehaviour
    {
        public ObjectPool Pool { get; set; }
        public abstract void Init();
        public abstract void Sleep();
    }
    

    ObjectPool.cs는 PoolableMonoBehaviour.cs를 생성하거나 풀링할 수 있는 클래스입니다. SetOriginal, Create, Release만으로도 움직입니다.

    ObjectPool.cs
    using UnityEngine;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    
    public class ObjectPool : MonoBehaviour
    {
        private PoolableMonoBehaviour original;
        private Stack<PoolableMonoBehaviour> pool = new Stack<PoolableMonoBehaviour>();
    
        /// <summary>
        /// オブジェクトプールするものをセット
        /// </summary>
        /// <param name="original">オブジェクトプールするもの</param>
        public void SetOriginal(PoolableMonoBehaviour original)
        {
            this.original = original;
        }
    
        /// <summary>
        /// プールから一つ取り出す
        /// </summary>
        /// <returns></returns>
        public Component Create()
        {
            PoolableMonoBehaviour obj;
            if (pool.Count > 0)
            {
                obj = pool.Pop();
            }
            else
            {
                obj = Instantiate(original).GetComponent<PoolableMonoBehaviour>();
                obj.Pool = this;
            }
            obj.Init();
            return obj;
        }
    
        /// <summary>
        /// プールに戻す
        /// </summary>
        /// <param name="obj">オブジェクト</param>
        public void Release(PoolableMonoBehaviour obj)
        {
            obj.Sleep();
            pool.Push(obj);
        }
    
        /// <summary>
        /// プールの要素数を取得
        /// </summary>
        /// <returns>要素数</returns>
        public int GetPoolCount()
        {
            return pool.Count;
        }
    
        /// <summary>
        /// プールの要素を破壊
        /// </summary>
        /// <param name="count">破壊数</param>
        public void Destroy(int count)
        {
            for (int i = Mathf.Min(pool.Count, count) - 1; i >= 0; i--)
            {
                Destroy(pool.Pop().gameObject);
            }
        }
        /// <summary>
        /// 全てのプールの要素を破壊
        /// </summary>
        public void DestroyAll()
        {
            foreach (PoolableMonoBehaviour item in pool)
            {
                if (item == null) continue;
                Destroy(item.gameObject);
            }
            pool.Clear();
        }
    
        /// <summary>
        /// あらかじめ生成
        /// </summary>
        /// <param name="count">生成数</param>
        /// <param name="duration">生成時間</param>
        public async void Preload(int count, float duration)
        {
            if (!Mathf.Approximately(duration, 0f))
            {
                int interval = (int)(duration / count * 1000);
                PreloadOnce();
    
                for (int i = count - 2; i >= 0; i--)
                {
                    await Task.Delay(interval);
                    PreloadOnce();
                }
            }
            else
            {
                for (int i = count - 1; i >= 0; i--) PreloadOnce();
            }
    
            void PreloadOnce()
            {
                PoolableMonoBehaviour obj = Instantiate(original).GetComponent<PoolableMonoBehaviour>();
                obj.Pool = this;
                Release(obj);
            }
        }
    }
    

    📖 함수 설명




    함수 이름
    설명


    void SetOriginal (PoolableMonoBehaviour original)
    객체 풀 하는 것을 세트 합니다. original : 객체 풀하는 것

    Component Create()
    수영장에서 하나 꺼냅니다. 반환값 : PoolableMonoBehaviour를 상속한 클래스

    void Release (PoolableMonoBehaviour obj)
    풀로 돌아갑니다. obj : 돌려주는 객체

    int GetPoolCount()
    풀의 요소 수를 가져옵니다. 반환값 : 요소수

    void Destroy (int count)
    풀의 요소를 파기합니다. count : 파기 수

    void DestroyAll()
    모든 풀의 요소를 파기합니다.

    void Preload (int count, float duration)
    풀 하는 오브젝트를 미리 생성합니다. count : 요소 수duration : 생성 시간


    💡사용법의 예



    총알을 발사하는 예를 만들었습니다.

    1. Shooter 컴포넌트를 장면의 객체에 추가합니다.
    2. 탄하고 싶은 객체를 조립식으로 만들어 Bullet 구성 요소를 추가합니다.
    3. Shooter 구성 요소에 조립식을 전달합니다.
    4. 장면을 재생하고 스페이스 키를 누르면 탄이 발사됩니다.

    Shooter.cs
    using UnityEngine;
    
    public class Shooter : MonoBehaviour
    {
        [SerializeField] PoolableMonoBehaviour original;
        ObjectPool pool = new ObjectPool();
    
        void Start()
        {
            pool.SetOriginal(original);
        }
    
        void Update()
        {
            if (Input.GetKeyDown(KeyCode.Space))
            {
                var bullet = pool.Create() as Bullet;
                bullet.transform.position = transform.position;
                bullet.transform.rotation = transform.rotation;
            }
        }
    }
    

    Bullet.cs
    using UnityEngine;
    
    public class Bullet : PoolableMonoBehaviour
    {
        float aliveCount;
    
        public override void Init()
        {
            aliveCount = 1f;
            gameObject.SetActive(true);
        }
    
        public override void Sleep()
        {
            gameObject.SetActive(false);
        }
    
        void Update()
        {
            transform.position += transform.forward * 10f * Time.deltaTime;
    
            aliveCount -= Time.deltaTime;
            if (aliveCount < 0f) Pool.Release(this);
        }
    }
    

    좋은 웹페이지 즐겨찾기