在网上看见了对象池的一些应用,一直很好奇,所以来研究一下
对象池主要的用途就是在那些需要重复被创建和销毁的物体上可以不进行重复的创建和销毁,例如子弹,在射击时被创建,一般在打到物体或者飞行一段距离(时间)后被销毁,然后再射击一次,再重复此操作,但要知道,多次的创建和销毁很耗性能,而对象池可以这样去处理子弹——在射击时先查询对象池里有没有没被激活的子弹,没有就创建一个新的,并把新的子弹加入到对象池,再把它射击出去;有就激活旧子弹,然后重置其参数,再把它射击出去,打到物体或者飞行一段距离(时间)后不进行销毁而是直接隐藏,这样就可以做到重复利用已创建出来的子弹,只进行激活和隐藏操作,大大节省了性能
那么具体就见代码吧,就以子弹为例
现在写了三个脚本,一个是子弹的,主要有子弹的速度,飞行距离,初始位置,移动,销毁,碰撞
一个是武器的,主要有子弹,子弹射击出的位置,创建对应类型的子弹的克隆体并加入到对象池中
一个是对象池的,有一个存放所有克隆体的字典,以Tag为key,有加入字典的方法,又找到某种类型的克隆体的方法,还有一个重置物体的方法
这样构成了一个最简单的子弹对象池
首先是子弹代码:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace tomo
{
public class bullet : MonoBehaviour
{
// Use this for initialization
public float speed;
public float distance;
private Vector3 start_pos;
void Awake()
{
start_pos = transform.position;
}
void Start()
{
}
// Update is called once per frame
void Update()
{
Move();
}
private void Move()
{
transform.GetComponent<Rigidbody>().velocity = Vector3.forward * speed * Time.deltaTime;
destroy(distance);
}
private void destroy(float dis)
{
float D = Vector3.Distance(start_pos, transform.position);
if (D >= dis)
{
transform.gameObject.SetActive(false);
}
}
void OnTriggerEnter(Collider collider)
{
if (collider.transform.name == "Cylinder")
{
transform.gameObject.SetActive(false);
}
}
}
}
武器代码:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace tomo
{
public class weapon : MonoBehaviour
{
public GameObject Bullet;
public Transform shootPostion;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Create_Bullet(shootPostion.position);
}
}
public void Create_Bullet(Vector3 sp)
{
List<GameObject> list = pool.getObj(Bullet);
if (list.Count > 0)
{
pool.reset(list[0], sp, transform.rotation);
list[0].SetActive(true);
//return list[0];
}
else
{
GameObject obj = GameObject.Instantiate(Bullet, sp, transform.rotation) as GameObject;
pool.inputObj(obj);
//return obj;
}
}
}
}
对象池代码:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace tomo {
public class pool : MonoBehaviour {
// Use this for initialization
//public static List<GameObject> pooledObj = new List<GameObject>();
public static Dictionary<string, List<GameObject>> dictionary = new Dictionary<string, List<GameObject>>();
void Start() {
}
// Update is called once per frame
void Update() {
}
//将新建子弹加入对象池列表
public static void inputObj(GameObject obj)
{
//Debug.Log("......"+obj);
//pooledObj.Add(obj);
var tagString = obj.tag;
if (dictionary.ContainsKey(tagString))
{
dictionary[tagString].Add(obj);
}
else
{
List<GameObject> list = new List<GameObject>();
list.Add(obj);
dictionary.Add(tagString, list);
}
}
public void OnClickShowDictionary()
{
foreach (var item in dictionary.Keys)
{
var list = dictionary[item];
foreach (var it in list)
{
Debug.LogError("tag " + it.tag + " name " + it.name);
}
}
}
//在对象池列表中找到隐藏的对象
public static List<GameObject> getObj(GameObject obj)
{
List<GameObject> list = new List<GameObject>();
foreach (var tag in dictionary.Keys)
{
if (tag == obj.tag)
{
List<GameObject> dic_list = dictionary[tag];
for (int i = 0; i < dic_list.Count; i++)
{
if (dic_list[i].activeSelf == false)
{
list.Add(dic_list[i]);
}
}
}
}
return list;
}
public static void reset(GameObject obj, Vector3 position, Quaternion rotation)
{
obj.transform.position = position;
obj.transform.rotation = rotation;
}
}
}