对象池的设计与实现

3 篇文章 0 订阅

VR射击子弹


管理场景中大量的频繁使用的物体: 子弹的生成与销毁,改为激活和隐藏

1.子弹挂载脚本
public class Pool1Item : MonoBehaviour
 {

	public string PoolName;   //对象池的名称
	public bool IsInPool;      //是否再池中

	void OnTriggerEnter(Collider c)  //碰撞到墙上,入池隐藏
	{
		Pool1Manager.GetInstance().GetPoolByName (PoolName).Enqueue (this);
	}
	void OnDisable()
	{
		Rigidbody r = GetComponent<Rigidbody> ();
		if (r != null)
			r.velocity = Vector3.zero;
	}
}
2.对象池类:队列存储所有子对象
public class Pool1 : MonoBehaviour 
{

    //池的名称
    private string poolName;
    //队列
    private Queue<Pool1Item> pools;
    //池中的对象
    private GameObject prefab;    //预制体,子弹或者怪物
    //上限                         
    private int maxCount;   
    //初始化
    public void Init(string _name, GameObject _prefab, int _maxCount, int initCount)
    {
        pools = new Queue<Pool1Item>();
        poolName = _name;
        prefab = _prefab;
        maxCount = _maxCount;
        for (int i = 0; i < initCount; i++)    //提前添加一些对象
        {
            Enqueue(CreateNewItem());

        }
    }

    //出池
    public Pool1Item Dequeue()    //得到池中一个子弹对象
    {

        if (pools == null)
            pools = new Queue<Pool1Item>();     //安全操作
        if (pools.Count <= 0)                   //对象池中没有对象
            pools.Enqueue(CreateNewItem());     //创建新对象添加到池中,调用本类中的方法

        Pool1Item item = pools.Dequeue();       //有对象后可以出池了
        item.IsInPool = false;
        item.gameObject.SetActive(true);
        Debug.Log(item.name);
        return (item);

    }

    //入池
    public void  Enqueue(Pool1Item item)
    {
        if (pools == null)
        { pools = new Queue<Pool1Item>(); }
        if (pools.Count >= maxCount)
        {
            Destroy(item.gameObject);
            return;
        }
        item.IsInPool = true;
        item.gameObject.SetActive(false);
        pools.Enqueue(item);
        
    }

    //创建新的池对象
    private Pool1Item CreateNewItem()
    {

        GameObject go = Instantiate(prefab);                               //生成实例对象
        go.transform.SetParent(transform);                                  //设置父物体(当前池)
        go.SetActive(false);              //隐藏
        Pool1Item item = go.AddComponent<Pool1Item>();
        item.PoolName = poolName;
        item.IsInPool = true;
        return item;
    }
}

3.对象池管理类
public class Pool1Manager : SingleTon<Pool1Manager>
 {
	private Dictionary <string ,Pool1> poolDic = new Dictionary<string, Pool1>();
	//创建新的对象池
	public Pool1 CreateNewPool(string poolName,GameObject prefab)
	{
		if (poolDic.ContainsKey (poolName))
        {
			Debug.LogFormat ("对象池创建失败:{0}已存在", poolName);
			return null;
		}
		GameObject go = new GameObject ();      ..//创建新对象池
		go.name = poolName;
		Pool1 pool = go.AddComponent<Pool1> (); 
		pool.Init (poolName, prefab, 10, 3);
		poolDic.Add (poolName, pool);              //将池存储起来
		return pool;
	}

	//获取对象池,根据名称
	public Pool1 GetPoolByName(string poolName)
	{
		if (!poolDic.ContainsKey (poolName))
	    {
			Debug.LogFormat ("对象池获取失败:{0}不存在", poolName);
			return null;
		}
		return poolDic [poolName];
	}

	//销毁对象池
	public void DestoryPool(string poolName)
	{
		Pool1 pool = GetPoolByName (poolName);
		if (pool == null)
			return;
		poolDic.Remove (poolName);
		Destroy (pool.gameObject);
	}
}
4.调用
 public class Weapon1Ctrl : MonoBehaviour 
 {

    //获取VR组件
    SteamVR_TrackedObject trackedObj;

    private GameObject bullet;
    private const string poolName = "NormalBullet1";
    public Transform gunpos;
    private Pool1 pool;
    private AudioSource audio;

    void Start()
    {
        bullet = Resources.Load("Bullet1") as GameObject;
        
        pool = Pool1Manager.GetInstance().CreateNewItem(poolName, bullet);
        //获取vr手柄上的组件
        trackedObj = this.GetComponentInParent<SteamVR_TrackedObject>();
        //trackedObj = this.transform.parent.GetComponent<SteamVR_TrackedObject>();

        audio = GameObject.Find("Sound").GetComponent<AudioSource>();
    }
    void Update()
    {
        //获取vr手柄输入
        var dev = SteamVR_Controller.Input((int)trackedObj.index);
        //按下扳机键
        if (dev.GetPress(SteamVR_Controller.ButtonMask.Trigger))
        {  
            Fire();
            audio.Play();
        }
    }

    void Fire()
    {
        Pool1Item item = pool.Dequeue();  //出池
        //注意谁发射子弹,就将子弹的层级设置为一样
        item.gameObject.layer = gameObject.layer;
        item.transform.position = gunpos.position;
        item.transform.rotation = gunpos.rotation;
        item.gameObject.GetComponent<Rigidbody>().AddForce(gunpos.transform.forward * 50, ForceMode.Impulse);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值