对象池使用

对象池:
  
  
对象池就存放需要被反复调用资源的一个空间,当一个对象回大量生成的时候如果每次都销毁创建会很费时间,通过对象池把暂时不用的对象放到一个池中 (也就是一个集合),当下次要重新生成这个对象的时候先去池中查找一下是否有可用的对象,如果有的话就直接拿出来使用,不需要再创建,如果池中没 有可用的对象,才需要重新创建,利用空间换时间来达到游戏的高速运行效果,在FPS游戏中要常被大量复制的对象包括子弹,敌人,粒子等
把脚本分别拖入场景中,不需要做任何操作 using System.Collections; using System.Collections.Generic; using UnityEngine; //创建接口,用于传递对象的生成和销毁 public interface IControl{ //生成时调用 void Spawn (); //销毁对象 void UnSpawn (); } /// <summary> /// 对象池类,用于存放相同类型的对象 /// 1.从对象池中拿出一个游戏对象 /// 2.回收某一个游戏对象 /// 3.回收所有的游戏对象 /// 4.检查某个游戏对象是否在对象池里 /// </summary> /// //对象池类 public class SubPool { //对象池里存放的所有需要频繁创建销毁的游戏对象 List <GameObject> pool = new List<GameObject>(); //要创建的游戏对象的预设体 GameObject prefab; //返回预制体的名字,预制体的名字和对象池的名字一致,在管理对象池的时候 //可以通过预制体的名字找到相应的对象池 public string name{ get{ return prefab.name; } } //自定义一个构造函数 public SubPool(GameObject obj){ prefab = obj; } //从对象池里面拿出一个游戏对象 public GameObject SubPoolSpawn(){ GameObject obj = null; //遍历集合,如果有对象就拿来用,没有的话,直接创建,放进池子 foreach (GameObject item in pool) { //如果没有用(场景中没有显示) if (item.activeSelf == false) { //取出 obj = item; break; } } //说明当前游戏对象没有可复用的游戏对象(有两种情况,一个没有,一个全部再用) if (obj == null) { //创建游戏对象,放在池子里 obj = GameObject.Instantiate (prefab) as GameObject; pool.Add (obj); } // 将游戏对象设置为激活状态 obj.SetActive (true); IControl control = obj.GetComponent<IControl> (); if (control != null) { control.Spawn (); } return obj; } //回收某一个游戏对象 public void SubPoolUnSpawn(GameObject obj){ //如果包含该游戏对象 if (pool.Contains(obj)) { obj.SetActive (false); IControl control = obj.GetComponent<IControl> (); if (control != null) { control.UnSpawn (); } } } //回收所有的游戏对象 public void SubPoolUnSpanwAll(){ //遍历所有未激活的游戏对象,进行回收 foreach (GameObject item in pool) { if (item.activeSelf) { SubPoolUnSpawn (item); } } } //检查某个对象是否在对象池里 public bool SubPoolContains(GameObject obj){ return pool.Contains (obj); } }
把脚本分别拖入场景中,不需要做任何操作



using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//管理类
public class PoolControl {

	#region单利
	private static PoolControl instance;
	private PoolControl (){
		
	}
	public static PoolControl Instance{
		get{
			if (instance == null ) {
				instance = new PoolControl ();
			}
			return instance;
		}
	}
	#endregion
	//创建字典,根据预设体的名字,找到对应的对象池
	Dictionary<string, SubPool> PoolDir = 
		new Dictionary<string, SubPool> ();

	//添加对象池的方法
	private void Register(string name){
		//通过名字加载预制体
		GameObject obj = Resources.Load (name) as GameObject;
		//根据预制体创建相应的对象池对象
		SubPool subPool = new SubPool(obj);
		//将obj对象池对象添加到对象池管理类字典里
		PoolDir.Add (name, subPool);
	}
	//根据预制体的名字找到对象池的对象,调用对象池中返回游戏对象的方法
	public GameObject Spawn (string name){
		SubPool subPool;
		//如果字典中不包含对应的key为name的键值对
		if (!PoolDir.ContainsKey(name)) {
			//此时需要在字典中创建对应的对象池
			Register (name);
		}
		subPool = PoolDir [name];
		return subPool.SubPoolSpawn ();
	}

	//回收一个游戏对象的方法
	public void UnSpwan(GameObject obj){
		//找对游戏对象所在的池子

		foreach (SubPool item in PoolDir.Values) {
			if (item.SubPoolContains(obj)) {
				//让该对象池回收它
				item.SubPoolUnSpawn (obj);
				break;
			}
		}
	}


}

创建一个Sphere球,把bittle脚本挂在Sphere身上,并把Sphere重命名为Butttle,
并把Buttle拖成预设体,放在Resources文件中
 
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class bittle : MonoBehaviour,IControl {
	//实现接口里面的方法
	public void Spawn ()
	{
		Debug.Log("表示从对象池中生成");
		//从游戏对象创建开始执行,延迟3秒销毁
		Invoke ("DeleteSelf", 3);

	}
	public void UnSpawn ()
	{
		Debug.Log("表示从对象池中销毁");
	}

	void Start () {
		
	}
	
	void Update () {
		transform.position += Time.deltaTime * Vector3.forward * 20;
	}
	//子弹销毁
	void DeleteSelf(){
		//回收游戏对象
		PoolControl.Instance.UnSpwan (gameObject);     
		//重置一下位置
		transform.position = Vector3.zero;
	}
}


创建一个胶囊体,并把player脚本挂在身上,运行的时候,按下空格的时候发射子弹

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

public class Player : MonoBehaviour {

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		if (Input.GetKeyDown(KeyCode.Space)) {
			//创建子弹
			GameObject obj = PoolControl.Instance.Spawn ("Bullet");
			obj.transform.position = transform.position;
		}
	}
}





Unity中,可以通过编写脚本来手动实现对象池,也可以使用Unity提供的对象池类来创建对象池。 以下是手动实现对象池的示例代码: ```csharp using UnityEngine; using System.Collections.Generic; public class ObjectPool : MonoBehaviour { public GameObject prefab; // 要缓存的对象的预制件 public int poolSize; // 缓存池的大小 private List<GameObject> objectPool = new List<GameObject>(); void Start () { // 创建缓存池中的对象 for (int i = 0; i < poolSize; i++) { GameObject obj = Instantiate(prefab); obj.SetActive(false); objectPool.Add(obj); } } // 从对象池中获取空闲对象 public GameObject GetObject() { foreach (GameObject obj in objectPool) { if (!obj.activeInHierarchy) { obj.SetActive(true); return obj; } } // 如果没有空闲对象,则创建一个新对象 GameObject newObj = Instantiate(prefab); objectPool.Add(newObj); return newObj; } // 将对象放回对象池 public void ReturnObject(GameObject obj) { obj.SetActive(false); } } ``` 以上代码演示了如何手动实现一个简单的对象池。首先在Start方法中创建一定数量的对象,然后在GetObject方法中遍历对象池,找到一个未激活的对象返回。如果没有空闲对象,则创建一个新对象并添加到对象池中。最后,在ReturnObject方法中将不再需要的对象放回对象池,将其激活状态设为false。 使用以上代码时,需要将希望缓存的对象的预制件赋值给prefab变量,并指定缓存池的大小。 Unity也提供了可重用对象池的类ObjectPool,可以在需要使用时直接调用。以下是Unity官方文档中的示例代码: ```csharp using UnityEngine; using UnityEngine.Pool; public class ObjectPoolExample : MonoBehaviour { public GameObject prefab; public int poolSize; private ObjectPool<GameObject> objectPool; void Start() { objectPool = new ObjectPool<GameObject>(() => Instantiate(prefab), poolSize, item => item.SetActive(true), item => item.SetActive(false)); } void Update() { // 从池中获取对象 GameObject obj = objectPool.Get(); // 将对象放回池中 objectPool.Release(obj); } } ``` 以上代码演示了如何使用Unity提供的ObjectPool类创建可重用对象池。首先,在Start方法中创建一个ObjectPool对象,并指定预制件创建方法、池大小、对象取出和放回时的回调函数等。然后,在Update方法中可以通过Get方法取出对象,通过Release方法将对象放回对象池中。 无论是手动实现对象池还是使用Unity提供的ObjectPool类,都可以有效地减少对象创建和销毁的次数,提高性能并减少内存占用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值