山寨小小军团开发笔记 之 GamePool

很多时候我们对于物体(比如弓箭)大量的生成与销毁,这个时候可以把弓箭放在内存池中进行管理,加快体验。自己Copy了一个简易版的。

一、代码

GameObjectPoolManager.cs

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

// A general pool object for reusable game objects.
//
// It supports spawning and unspawning game objects that are
// instantiated from a common prefab. Can be used preallocate
// objects to avoid calls to Instantiate during gameplay. Can
// also create objects on demand (which it does if no objects
// are available in the pool).
public class GameObjectPoolManager {

   public GameObject parent;

    // The prefab that the game objects will be instantiated from.
   private GameObject prefab;
   // The list of available game objects (initially empty by default).
   private Stack<GameObject> available;

    // The list of all game objects created thus far (used for efficiently
   // unspawning all of them at once, see UnspawnAll).
   private List<GameObject> all;

	// An optional function that will be called whenever a new object is instantiated.
	// The newly instantiated object is passed to it, which allows users of the pool
	// to do custom initialization.
    private Callback<GameObject> initializeFunction;

    private Callback<GameObject> destroyFunction;

    //// Indicates whether the pool‘s game objects should be activated/deactivated
    //// recursively (i.e. the game object and all its children) or non-recursively (just the
    //// game object).
    //private var setActiveRecursively : boolean;

	// Creates a pool.
	// The initialCapacity is used to initialize the .NET collections, and determines
	// how much space they pre-allocate behind the scenes. It does not pre-populate the
	// collection with game objects. For that, see the PrePopulate function.
	// If an initialCapacity that is <= to zero is provided, the pool uses the default
	// initial capacities of its internal .NET collections.
    public GameObjectPoolManager(GameObject prefab, Callback<GameObject> initializeFunction, Callback<GameObject> destroyFunction)
    {
        this.prefab = prefab;

        this.parent = new GameObject(prefab.name + "Pool");

        this.available = new Stack<GameObject>();
        this.all = new List<GameObject>();

        this.initializeFunction = initializeFunction;
        this.destroyFunction = destroyFunction;
    }

	// Spawn a game object with the specified position/rotation.
    public GameObject Spawn(Vector3 position, Quaternion rotation)
    {
        GameObject result = null;

        if (available.Count == 0)
        {
            // Create an object and initialize it.
            result = GameObject.Instantiate(prefab, position, rotation) as GameObject;
            result.transform.parent = parent.transform;

            // Keep track of it.
            all.Add(result);
        }
        else
        {
            result = available.Pop() as GameObject;

            // Get the result‘s transform and reuse for efficiency.
             //Calling gameObject.transform is expensive.
            var resultTrans = result.transform;
            resultTrans.position = position;
            resultTrans.rotation = rotation;

            result.SetActive(true);
        }

        if (initializeFunction != null) initializeFunction(result);

        return result;
	}

	// Unspawn the provided game object.
	// The function is idempotent. Calling it more than once for the same game object is
	// safe, since it first checks to see if the provided object is already unspawned.
	// Returns true if the unspawn succeeded, false if the object was already unspawned.
    public bool Unspawn(GameObject obj)
    {

        if (!available.Contains(obj))
        {
            // Make sure we don‘t insert it twice.
            available.Push(obj);
            obj.SetActive(false);

            if (destroyFunction != null) destroyFunction(obj);

            return true; // Object inserted back in stack.
        }
        return false; // Object already in stack.
	}

       // Pre-populates the pool with the provided number of game objects.
    void PrePopulate(int count){
        GameObject[] array = new GameObject[count];
        for(var i = 0; i < count; i++){
            array[i] = Spawn(Vector3.zero, Quaternion.identity);
            //this.SetActive(array[i], false);
        }
        for(var j = 0; j < count; j++){
            Unspawn(array[j]);
        }
    }
       // Unspawns all the game objects created by the pool.
    void UnspawnAll()
    {
        foreach (var item in available)
        {
            Unspawn(item);
        }
    }
	// Returns the number of active objects.
    int GetActiveCount()
    {
        return all.Count - available.Count;
    }

	// Returns the number of available objects.
    int GetAvailableCount(){
        return available.Count;
    }
}

二、应用

还是用之前的BezierTest.cs的例子

    void Start()
    {
        arrowPool = new GameObjectPoolManager(arrowPrefab, null, null);

        //controlPoints = ControlPoints(transform, right);
    }
    #endregion

    void Test(bool fireRight)
    {
        Transform end = fireRight ? right : left;

        ///在中心点生成弓箭
        GameObject curArrow = arrowPool.Spawn(transform.position, Quaternion.Euler(Vector3.zero));

        ///计算LookTarget的点 与 贝塞尔曲线的第三个控制点
        Vector3[] points = Re_LookTarget_MiddlePerpendicularPoint(curArrow.transform, end);

        ///初始化发射
        ArrowControl arrowControl = curArrow.GetComponent<ArrowControl>();
        arrowControl.Init(
            points[0],
            points[1],
            end.position,
            3.0f,
            delegate()
            {
                arrowPool.Unspawn(curArrow);
            });
    }

  

时间: 2024-11-07 00:22:46

山寨小小军团开发笔记 之 GamePool的相关文章

炉石传说 C# 开发笔记(BS上线尝试)

昨天买了一个月的1G 1核的服务器,由于不是新用户,所以没有享受到阿里的6个月免费的优惠. (阿里脑残,为什么不对于续费或者升级免费呢?) 在服务器的通讯上面已经OK了,完全绕过了ASP.NET,就是单纯的服务器和浏览器在通讯,页面也只是静态的页面,纯HTML5 + JS. 通讯是WebSocket,绘图SVG.不知道为什么,对于固定的文字,UC的文字绘制是OK的,对于JSON反序列化的对象,所有的绘制都是有问题的. 初步怀疑是由于使用了汉字,然后没有设置编码,造成了JS的本地反序列化不对. 服

张高兴的 Windows 10 IoT 开发笔记:RTC 时钟模块 DS3231

原文:张高兴的 Windows 10 IoT 开发笔记:RTC 时钟模块 DS3231 GitHub:https://github.com/ZhangGaoxing/windows-iot-demo/tree/master/DS3231 注意:不包含闹钟设置

Android开发笔记(一百零三)地图与定位SDK

集成地图SDK 国内常用的地图SDK就是百度和高德了,二者的用法大同小异,可按照官网上的开发指南一步步来.下面是我在集成地图SDK时遇到的问题说明: 1.点击基本地图功能选项,不能打开地图,弹出"key验证出错!请在AndroidManifest.xml文件中检查key设置的"的红色字提示.查看日志提示"galaxy lib host missing meta-data,make sure you know the right way to integrate galaxy&

微信订阅号开发笔记(二)

微信开发的流程其实很简单 o(∩_∩)o 哈哈!在微信网站的编辑操作 额,就不说了.虽然有人问过.下面是我的微信开发过程,简单记录下. 成为开发者 材料:1.自己的服务器资源,百度的BAE,新浪的SAE都不错. 2.懂那么点编程语言. 3.注册微信公众号. 上面的都有了之后,就可以自己动手开发了.哇咔咔,好兴奋.有木有. 在登录进去之后,怎么成为开发者?不知道,自己看去. 开始coding吧. 1.验证 if (! empty ( $_GET ['echostr'] ) && ! empt

微信订阅号开发笔记(三)

1.接收语音识别结果 if($msgType=="voice"){ //收到语音消息 //MediaId 语音消息媒体id,可以调用多媒体文件下载接口拉取数据. //Format 语音格式,如amr,speex等 $format = $postObj->Format; $mediaId = $postObj->MediaId; //开通语音识别功能,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,增加一个Recongnition字段. //注:由于客户端缓

微信订阅号开发笔记(四)

1.创建菜单 //创建菜单 public function createMenu(){ $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token="; $url.=$this->getacctoken(); //目前自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单.一级菜单最多4个汉字, //二级菜单最多7个汉字,多出来的部分将会以"..."代替.请注意,创建自定义菜单

Swift开发笔记

Swift开发笔记(一) 刚开始接触XCode时,整个操作逻辑与Android Studio.Visual Studio等是完全不同的,因此本文围绕IOS中控件的设置.事件的注册来简单的了解IOS开发 1.新建一个Xcode项目,项目目录大致如图: 2.在Main.storyboard添加控件 首先要显示右侧的工具栏(Utilities),之后选择显示Object Library,就可以找到常用的一些控件了,然后添加几个控件到界面中 3.将控件和ViewController进行关联 此时要将Ed

张高兴的 Xamarin.Forms 开发笔记:为 Android 与 iOS 引入 UWP 风格的汉堡菜单 ( MasterDetailPage )

所谓 UWP 样式的汉堡菜单,我曾在"张高兴的 UWP 开发笔记:汉堡菜单进阶"里说过,也就是使用 Segoe MDL2 Assets 字体作为左侧 Icon,并且左侧使用填充颜色的矩形用来表示 ListView 的选中.如下图 但怎样通过 Xamarin.Forms ,将这一样式的汉堡菜单带入到 Android 与 iOS 中呢? 一.大纲-细节模式简介 讲代码前首先来说说这种导航模式,官方称"大纲-细节模式"(MasterDetail).左侧的汉堡菜单称为&qu

web前端开发笔记(2)

web前端开发笔记(1) 一.HTML标签书写有哪些规范? 页面编码. 文档声明. 关键字与描述. 行内元素不能包含块级元素. a标签不能嵌套a标签. 标签名和属性必须用小写字母书写,属性必须加引号,标签必须闭合,单标签页必须闭合. 页面中不要用 进行缩进,如需缩进,用css控制. html标签使用必须语义化. 要为img标签填写alt和title属性. 二.HTML静态页面出现中文乱码如何解决? 引入<meta charset="UTF-8"> 三.通常情况下块属性标签和