Unity 单例类模板+对象池的简单使用(记录方便拷贝使用)

一.单例类模板

using UnityEngine;
/// <summary>
/// 通用Mono单例模板
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>
{
    private static T ms_instance;

    public static T Instance
    {
        get
        {
            if (ms_instance == null)
            {
                ms_instance = Instantiate();
            }

            return ms_instance;
        }
    }

    protected static T Instantiate()
    {
        if (ms_instance != null) return ms_instance;

        // 在场景中查找T类型的Mono类
        ms_instance = (T)FindObjectOfType(typeof(T));
        if (FindObjectsOfType(typeof(T)).Length > 1)
        {
            return ms_instance;
        }

        if (ms_instance != null) return ms_instance;

        // 创建GameObject实例
        var singleton = new GameObject("[Singleton]" + typeof(T).Name);
        DontDestroyOnLoad(singleton); // 设置GameObject不被销毁
        if (singleton == null) return ms_instance;

        // 添加Mono单例脚本
        ms_instance = singleton.AddComponent<T>();
        // 初始化单例
        ms_instance.InitSingleton();

        return ms_instance;
    }

    protected virtual void InitSingleton()
    {
    }

    /// <summary>
    /// 使用预制体实例化时创建单例
    /// </summary>
    protected virtual void Awake()
    {
        if (ms_instance == null)
        {
            ms_instance = this as T;

            // 初始化单例
            InitSingleton();
        }
        else
        {
            // 如果已经存在实例,则需要销毁当前的GameObject
            GameObject.Destroy(this.gameObject);
        }
    }

    protected virtual void OnApplicationQuit()
    {
        ms_instance = null;
        // 销毁GameObject
        GameObject.Destroy(this.gameObject);
    }
}

MonoSingletonExample:

public class UITWQChoiceQuestion : MonoSingleton<UITWQChoiceQuestion>
{

  protected  override  void Awake()//重写Awake
    {
        base.Awake();//被重写的Awake 也执行,不添加base 则只执行重写的Awake
        BtnCommit.onClick.AddListener(() => { OnBtnCommit(); });
    }

}

二.对象池的简单使用:

对象池的管理:

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

public class PoolManage : MonoSingleton<PoolManage>
{
    //开辟一块 对象池
    List<GameObject> objectPools = new List<GameObject>();

   protected override  void Awake()
    {
        base.Awake();
    }
    /// <summary>
    /// 从对象池中获取
    /// </summary>
    /// <param name="obj"></param>
    public void GetObj(GameObject obj)
    {
        //判断池中是否有可用资源
        if (objectPools.Count == 0)  //没有则重新生成
        {
            GameObject go = Instantiate(obj, Vector3.zero, Quaternion.identity) as GameObject;
            //并添加到池中
            objectPools.Add(go);
        }
        else
        {
            //从对象池中取
            GameObject go = objectPools[0];
            go.SetActive(true);
            objectPools.Remove(go);
        }
    }

    /// <summary>
    /// 放到对象池中
    /// </summary>
    /// <param name="obj"></param>
    public void SetObj(GameObject obj)
    {
        objectPools.Add(obj);
        obj.SetActive(false);
    }

}

//在想要用到的地方直接调用:

 PoolManage.Instance.GetObj(GameObject);//从对象池中拿取,没有则创建并存取对象池

Example :
   

public GameObject BullerPre;
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            PoolManage.Instance.GetObj(BullerPre);

        }
    }

Example :

挂载在子弹预制的类 用来回收子弹

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

public class Bullet : MonoBehaviour
{

    //在创建一个脚本挂在子弹预设物上,用来回收子弹
    public float Speed = 7f;
    void Update()
    {
        //让子弹向前移动
        transform.Translate(Vector3.forward * Time.deltaTime * Speed);
        StartCoroutine(DesBullet(3f));
    }

    //回收子弹,用完 放回对象池
    private IEnumerator DesBullet(float v)
    {
        yield return new WaitForSeconds(v);
        PoolManage.Instance.SetObj(gameObject);
        this.transform.position = Vector3.zero; 
    }

}

猜你喜欢

转载自blog.csdn.net/qq_37524903/article/details/122599378
今日推荐