Unity 简单的预制体管理方式带对象池功能

游戏开发过程中遇到需要频繁创建和销毁的对象为了方便创建通常会使用预制体的方式进行生成,而为了避免对垃圾回收造成压力通常会使用对象池来对这些预制体进行管理。但是加载,实例化预制体需要额外的代码控制。这里提供了一种简单的管理方案。

首先创建一个基类,这个类用于自动获取预制体并将其放入对象池进行管理

基类代码:

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

public abstract class PrefabBehavior : MonoBehaviour where T : MonoBehaviour
{
    private static Queue objectPool = new Queue();        //对象池
    private static T template;      //预制体


    /// 
    /// 获取对象
    /// 
    /// 
    public static T Get()
    {
        //读取Resources/Prefabs路径下所有带有继承PrefabBehavior脚本的物体,必须有且只能有一个,否则报错
        if (template == null)
        {
            T[] all = Resources.LoadAll("Prefabs");
            if (all.Length == 0) { throw new Exception(string.Format("{0} has no prefab in path: Resources/Prefabs", typeof(T))); }
            if (all.Length > 1) { throw new Exception(string.Format("{0} in path: Resources/Prefabs has morethan one", typeof(T))); }
            template = all[0];
        }

        if (objectPool.Count > 0)
        {
            T obj = objectPool.Dequeue();
            obj.gameObject.SetActive(true);
            return obj;
        }
        else
        {
            return Instantiate(template);
        }
    }

    /// 
    /// 回收对象
    /// 
    public void Retrieve()
    {
        DontDestroyOnLoad(gameObject);
        gameObject.SetActive(false);
        objectPool.Enqueue(this as T);
    }

    /// 
    /// 清空对象池
    /// 
    public static void ClearObjectPool()
    {
        for (int i = objectPool.Count; i > 0; --i)
        {
            Destroy(objectPool.Dequeue().gameObject);
        }
    }
}

 

 预制体制作:

这里举个简单的例子,制作一颗子弹。

1.创建脚本,脚本继承上面的基类,代码如下:

using UnityEngine;
using System.Collections;

public class Bullet : PrefabBehavior
{
    void OnEnable()
    {
        StartCoroutine("IAutoRetrieve");        //激活时开始自动回收
    }

    //3秒后回收自己
    IEnumerator IAutoRetrieve()
    {
        yield return new WaitForSeconds(3);
        Retrieve();
    }

    void Update()
    {
        transform.Translate(Vector3.forward * Time.deltaTime * 100);        //向前飞
    }
}

2.创建一个球体,把子弹脚本挂上去,然后作为预制体放到Resources/Prefabs目录下就大功告成了。是不是很简单?

Unity 简单的预制体管理方式带对象池功能_第1张图片

 

如何使用:

我们先写一个简单的发射脚本,代码如下:

using UnityEngine;

public class OnCamera : MonoBehaviour
{
    float eulerX;
    float eulerY;
    
    void Update()
    {
        //鼠标控制旋转
        eulerX += Input.GetAxis("Mouse Y");
        eulerY -= Input.GetAxis("Mouse X");
        eulerX = Mathf.Clamp(eulerX, -90, 90);
        if (eulerY > 360) { eulerY -= 360; }
        if (eulerY < 0) { eulerY += 360; }
        transform.eulerAngles = new Vector3(eulerX, eulerY, 0);

        //按住左键每帧发射一颗子弹
        if (Input.GetMouseButton(0))
        {
            Bullet sample = Bullet.Get();       //通过Bullet.Get()获取预制体
            sample.transform.position = transform.position + transform.forward * 3;     //设置发射位置
            sample.transform.rotation = transform.rotation;     //设置发射方向
        }
    }
}

 将代码挂到摄像机上

Unity 简单的预制体管理方式带对象池功能_第2张图片

开始运行

Unity 简单的预制体管理方式带对象池功能_第3张图片是不是SoEasy? 

你可能感兴趣的:(Unity)