Kaze's Object Buffer Script - Looking for feedbacks

Hello guys, I was playing with my ArrowHead project and I decided to test some functions thinking in a bullet hell game that I want to create in some far, far away future. The bullet control part worked well until 100-200 bullets in the screen, after this the FPS went under of 60fps. But this topic is about a script that I made to control the bullets’ “existence”.

For example, I have a object that shoot 50 bullets every second, each bullet have 2 seconds of life and this object have 30 seconds of life. So why should I create 1500 bullets when I can create 100 bullets and recycle them. So I did this script and I am looking for feedback, it is working pretty well in my platform game but my game is pretty simple. Maybe I’ll upload it to wiki if it is good ( I want to post something there :stuck_out_tongue: )

#pragma strict
#pragma downcast

public var freeObjects : Array = null;
public var inUseObjects : Array = null;

// Effects objects to creation and destruction, it is optional
public var creationObjectBuffer : ObjectBuffer = null;
public var creationSound : AudioClip = null;
public var creationTimeEffectInterval : float = 0.5;
private var lastCreationEventTime : float = -999;

public var destructionObjectBuffer : ObjectBuffer = null;
public var destructionSound : AudioClip = null;
public var destructionTimeEffectInterval : float = 0.5;
private var lastDestructionEventTime : float = -999;



public var bufferedObject : GameObject = null;

function Start () 
{
	freeObjects = new Array();
	inUseObjects = new Array();
	if( bufferedObject == null )
	{
		Debug.LogError("The object buffer cannot buffer null object.");
	}
}

function fillBuffer( num : int )
{
	if( bufferedObject == null )
	{
		Debug.LogError("The object buffer cannot create a buffer with null object.");
	}
	
	else if( num < 1 )
	{
		Debug.LogError("The object buffer cannot create zero or minus objects.");
	}
	
	else
	{
		var i : int;
		for( i = 0; i < num; i++ )
		{
			freeObjects.Push( GameObject.Instantiate( bufferedObject, Vector3( -10, -10,0 ), Quaternion.identity ) );
		}
	}
}

/* Empty the buffer, but it can't free the elements in use */
function emptyBuffer()
{
	var i : int = 0;
	var object : GameObject;
	for( i = 0; i < freeObjects.length; i++ )
	{
		object = freeObjects[i];
		GameObject.Destroy( object );
	}
	freeObjects = new Array();
	if( creationObjectBuffer != null ) creationObjectBuffer.emptyBuffer();
	if( destructionObjectBuffer != null ) destructionObjectBuffer.emptyBuffer();
	
}

/* Destroy all */
function destroyBuffer()
{
	var i : int = 0;
	var object : GameObject;
	emptyBuffer();
	for( i = 0; i < inUseObjects.length; i++ )
	{
		object = inUseObjects[i];
		GameObject.Destroy( object );
	}
	if( creationObjectBuffer != null ) creationObjectBuffer.destroyBuffer();
	if( destructionObjectBuffer != null ) destructionObjectBuffer.destroyBuffer();
	
	GameObject.Destroy( gameObject );
}

function createObject( pos: Vector3, rotation : Quaternion ) : GameObject
{
	var object : GameObject;
	if( freeObjects.length != 0 )
	{
		object = freeObjects[freeObjects.length - 1];
		setObjectActive( object, true );
		freeObjects.RemoveAt( freeObjects.length - 1 );
		object.transform.position = pos;
		object.transform.rotation = rotation;
	}
	
	else
	{
		object = GameObject.Instantiate( bufferedObject, pos, rotation );
	}

	inUseObjects.Push( object );
	
	if( creationTimeEffectInterval + lastCreationEventTime <= Time.time )
	{
		if( creationObjectBuffer != null )
		{
			creationObjectBuffer.createObject(  pos, rotation );
		}
		if( creationSound != null )
		{
			AudioSource.PlayClipAtPoint( creationSound, pos );
		}
		lastCreationEventTime = Time.time;
	}
	
	
	return object;
}

function destroyObject( object : GameObject )
{
	object.transform.position.x = -10;
	object.transform.position.y = -10;
	setObjectActive( object, false );

	inUseObjects.Remove( object );
	freeObjects.Push( object );
}

function getBufferedObject() : GameObject
{
	return bufferedObject;
}

function setObjectActive( object : GameObject, b : boolean )
{	
	object.SetActive( b ) ;
}

How to use

private var pinBuffer : ObjectBuffer; //Just create a gameObject, put the ObjectBuffer component and fill its variables
...
//Creating a pin, whoever it designed to destroy this object must have access to its buffer
var pin : GameObject = pinBuffer.createObject( Vector3(4,4,0), Quaternion.identity );
...
// Destroying the pin
pinBuffer.destroyObject(pin);

Thanks for the attention :wink:

Push / Pop and Array is slow, you should use List or builtin array if you want to improve it.

Hmm does UnityScript have Lists or only C#? Also I was thinking that maybe to use a binary tree should be a faster solution for this case.

UnityScript has access to the generics as well, though I don’t know the syntax off hand. I wouldn’t go down the binary tree route personally; a generic Queue is already very well optimized for this sort of thing and the impact of enqueue/dequeue compared to the rest of the operations involved in caching and retrieving a game object is trivial (SetActiveRecursively is insanely slow - but I’m not sure how the new 4.0 SetActive method has changed that).