unity初识之添加 gameobjectpool 对象池

有的时候,我们需要动态创建某个对象,比如点击就会出现漂浮的文本提示,漂浮的奖励等等,他们可能会创建很多,而且很快就会被销毁,并且创建销毁的操作很频繁,如果太频繁,会很耗性能,好的办法是,当创建出来后,把它存在内存中,需要销毁的时候只是把它隐藏了,放在对象池中,等需要用了,再从对象池中把它拿出来显示。这样省去了频繁创建,销毁的操作。

这里自己写了一个泛型的对象池类

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class GameObjectPool <T>: MonoBehaviour where T : class {

    private T m_resGameObj ;

    private GameObject m_componentParent;

    public delegate void OnCall();

    public delegate void OnCall<T0>(T0 arg0);

    public OnCall OnRecycle = null;

    public OnCall OnNew = null;

    public OnCall OnInitialize = null ;

    private List<T> m_pool = new List<T>() ;

    private List<T> m_usePool = new List<T>();

    public GameObjectPool(T resObj) {

        m_resGameObj = resObj;

    }

    public GameObjectPool(GameObject parent) {

        m_componentParent = parent;

    }

    public int Length() {

        return m_pool.Count;

    }

    public T0 get<T0>() where T0 : class    {

        T0 obj = null ;

        if (m_pool.Count 0) {

            obj = m_pool[m_pool.Count-1] as T0;

            m_usePool.Add(m_pool[m_pool.Count-1]);
            m_pool.RemoveAt(m_pool.Count-1);
        }
        else {

            if (this.OnNew != null) {

                this.OnNew.Invoke();
            }

            Debug.Log("~~~~ type os " + typeof(Component) + " dafdafada " + typeof(T));

            if (m_resGameObj != null && typeof(GameObject) == m_resGameObj.GetType()) {

                obj = Instantiate(m_resGameObj as GameObject) as T0;

                m_usePool.Add(obj as T);

            }
            else if (m_componentParent != null && typeof(Component).IsAssignableFrom(typeof(T) ) ) {

                obj = m_componentParent.AddComponent(typeof(AudioSource)) as T0;

                m_usePool.Add(obj as T);

                Debug.Log("~~~~ new a obj , current used count is " + m_usePool.Count);

            }
            else {

                //TODO: 其他类型的暂不处理
            }
        }

        if (this.OnInitialize != null) {

            this.OnInitialize.Invoke();
        }

        return obj ;

    }

    public void Recycle<T0>(T0 obj) where T0: class {

        if (obj == null) {

            return ;

        }

        for (int i = 0 ; i < m_usePool.Count ; ++i) {

            if (obj == m_usePool[i]) {

                m_usePool.Remove(obj as T);

                Debug.Log("~~~~ remove usepool " + m_usePool.Count );

            }
        }

        m_pool.Add(obj as T);

        if (this.OnRecycle != null) {

            this.OnRecycle.Invoke();
        }

        Debug.Log("~~~~ current pool is " + m_pool.Count );

    }

    public List<T GetAllUseObj() {

        return m_usePool;

    }

    public List<T GetAllUnUsedObj() {

        return m_pool;

    }
}

比如这里我用在声音的控制上,我有一个soundsManager来控制所有音效和背景音乐的播放,而音效是可能同时播放多个的,这时候就需要创建多个audioSource来同时播放不同的音乐。

使用:
private GameObjectPool<AudioSource> m_objPool ;

void Awake(){

        DontDestroyOnLoad(this);

        m_objPool = new GameObjectPool<AudioSource>(this.gameObject);

    }


    public void playSounds(string clipName) {

        StartCoroutine(poolToPlaySounds(clipName));
    }

IEnumerator poolToPlaySounds(string clipName) {

        AudioSource audio = m_objPool.get<AudioSource>();

        audio.loop = false ;

        singlePlaySounds(clipName, audio);

        yield return new WaitForSeconds(audio.clip.length);

        m_objPool.Recycle(audio);
    }

在播放声音的时候,起一个进程,从objectpool中获取一个AudioSource的component, 如果对象池中没有空余的,那么就创建一个新的返回使用,
simgleplaysounds是我自己写的一个方法,里面的逻辑就是普通的将clip赋值给audio ,然后去播放,这时可以获得这个clip的播放时长,然后给这个进程设置一个delay时间,等播放时间完了,后面对象池将这个新创建的AudioSource对象存起来,供下次重复使用.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值