Unity3D-对象池技术

什么是对象池
对象池定义:对象池就存放需要被反复调用资源的一个空间,当一个对象回大量生成的时候如果每次都销毁创建会很费时间,通过对象池把暂时不用的对象放到一个池中(也就是一个集合),当下次要重新生成这个对象的时候先去池中查找一下是否有可用的对象,如果有的话就直接拿出来使用,不需要再创建,如果池中没有可用的对象,才需要重新创建,利用空间换时间来达到游戏的高速运行效果,在FPS游戏中要常被大量复制的对象包括子弹,敌人,粒子等
废话不多说直接上代码
Icontrol
using UnityEngine;
using System.Collections;
///
/// 挂载对象:不挂载
/// 作用:接口类,方便其他脚本继承此接口
/// 注意:
///
public interface IControl
{
//生成游戏对象的方法
void Spawn();
//销毁游戏对象
void UnSpwan();
}
SubPool
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
///
/// 挂载对象:不挂载
/// 作用:对象池类。
/// 注意:
///
public class SubPool
{
//对象池里面存放场景中需要的游戏物体
List pool = new List ();
//要创建的游戏物体的预设体
GameObject prefab;
//返回预设体的名字,预设体的名字和对象池的名字相同
//在管理对象池的类里面,可以通过预设体的名字找到相对应的对象池
public string Name {
get {
return prefab.name;
}
}
//构造方法
public SubPool (GameObject mPrefab)
{
prefab = mPrefab;//传递预设体参数
}
//从对象池里面拿到一个游戏物体
public GameObject SubPoolSpawn (Transform pos)
{
GameObject obj = null;
//遍历对象池找预设体
foreach (GameObject item in pool) {
//如果该对象未激活,说明该对象没有被使用
if (item.activeSelf == false) {
obj = item;
obj.transform.position = pos.position;
obj.transform.rotation = pos.rotation;
break;//跳出该循环
}
}
//找不到要用的游戏对象
if (obj == null) {
//创建一个新的游戏对象
obj = GameObject.Instantiate (prefab, pos.position, Quaternion.identity)as GameObject;
//把新创建的游戏对象放到集合里面
pool.Add (obj);
}
obj.SetActive (true);//处于激活状态
//通过子类实例化接口对象,子类的脚本组件实现继承
//并实现了接口里面的方法,control里面存的就是该、
//子类所实现的方法

    IControl control = obj.GetComponent<IControl> ();
    if (control != null) {
        //调用游戏对象实现的方法
        control.Spawn ();
    }
    return obj;
}
//回收游戏对象
public void SubPoolUnSpawn (GameObject obj)
{
    //如果对象池集合里面包含了该物体
    if (pool.Contains (obj)) {
        IControl control = obj.GetComponent<IControl> ();
        if (control != null) {
            control.UnSpwan ();
        }
        obj.SetActive (false);
        obj.transform.position = Vector3.zero;
    }
}
//回收所有的游戏对象
public void SubPoolUnsPawnAll ()
{
    //遍历集合中所有的游戏对象
    foreach (GameObject item in pool) {
        if (item.activeSelf) {
            SubPoolUnSpawn (item);
        }
    }
}

/// <summary>
/// 某个对象是否在对象池里面
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public bool Contains (GameObject obj)
{
    //池子里面是否有对象
    return pool.Contains (obj);
}

}
PoolControl
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
///
/// 挂在对象:C#类,不挂载
/// 作用:对象池管理类,减少代码耦合度
/// 注意:不继承MonoBehaviour
///
public class PoolControl
{

private static PoolControl instances;//单例模式

private PoolControl ()
{
}

public static PoolControl Instance {
    get {
        if (instances == null) {
            instances = new PoolControl ();
        }
        return instances;
    }
}
//创建字典,根据预设体名字找到相对应的对象
Dictionary<string, SubPool> poolDic = 
    new Dictionary<string, SubPool> ();

/// <summary>
/// 得到对象池中的游戏对象
/// </summary>
/// <param name="name">预设体的名字</param>
/// <returns></returns>
public GameObject Spawn (string name, Transform pos)
{
    SubPool subpool;
    //如果字典包含该key的值
    if (!poolDic.ContainsKey (name)) {
        //在字典里面添加一个对象池
        RegisterSubPools (name);
    }
    subpool = poolDic [name];
    return subpool.SubPoolSpawn (pos);
}

/// <summary>
///  添加对象池的方法
/// </summary名字
void RegisterSubPools (string name)
{
    //通过名字加载预设体
    GameObject mprefab = Resources.Load (name) as GameObject;
    //根据预设体创建对应的对象池
    SubPool subpool = new SubPool (mprefab);
    //将对象池添加到字典中
    poolDic.Add (name, subpool);
}

///回收对象的方法
public void UnSpwan (GameObject obj)
{
    //遍历所有的对象池看那个对象池包含该游戏物体
    foreach (SubPool item in poolDic.Values) {
        //如果该对象池包含了该物体
        if (item.Contains (obj)) {
            //调用该对象池回收游戏物体的方法
            item.SubPoolUnSpawn (obj);
            break;
        }
    }
}

}
PlayerScript
using UnityEngine;
using System.Collections;
using UnityEngine.WSA;
///
/// 挂载对象:需要产生子弹的游戏物体上
/// 作用:控制游戏物体的旋转移动和子弹的发射
/// 注意:
///
public class PlayerScript : MonoBehaviour
{
public Transform pos;

void Update ()
{
    float v = Input.GetAxis ("Vertical");
    float h = Input.GetAxis ("Horizontal");
    if (v != 0 || h != 0) {
        transform.Translate (transform.forward * v * Time.deltaTime * 10f);
        transform.Rotate (new Vector3 (0, h, 0) * Time.deltaTime * 30f);
    }
    if (Input.GetKeyDown (KeyCode.Space)) {
        PoolControl.Instance.Spawn ("Bullet", pos);
    }
}

}

重点内容
using UnityEngine;
using System.Collections;
using System;
///
/// 挂载对象:子弹
/// 作用:子弹的生成与子弹的运动方向
/// 注意:
///
public class Bullet : MonoBehaviour,IControl
{
// public Transform pos;

public void Spawn ()
{
    Debug.Log ("从对象池里面取出一个游戏物体");
    //三秒钟销毁
    Invoke ("DeleteSelf", 2f);
}

public void UnSpwan ()
{
    Debug.Log ("把游戏物体放入对象池");
}

void DeleteSelf ()
{
    PoolControl.Instance.UnSpwan (gameObject);

}
void Update ()
{
    transform.Translate (transform.right * Time.deltaTime * 4);
}

}
游戏运行效果图如下
运行效果图
子弹发射位置

猜你喜欢

转载自blog.csdn.net/BoBoWang1991/article/details/68961877
今日推荐