Unity3D中对象池的使用
来源:互联网 发布:java插件下载 编辑:程序博客网 时间:2024/05/18 16:56
Unity3D中对象池的使用
原文地址:点击
翻译:claudio
The script is really simple but it has helped the performance in my iOS game tremendously by limiting the number of instantiations that happen at runtime.
这个脚本非常简单,但它可以通过大量减少实例化所带来的开销使我的iOS游戏得到很大的性能提升。
What it does:
The object pool allow you to buffer or pool objects you plan on reusing many time throughout your game, by allowing you to request a new object from it, and tell it whether or not it must give you an object or only give you an object thats available. It also buffers objects at the start to give you a pool to work with initially.
对象池可以缓存你计划在游戏中重复利用的对象,并允许你从中调用,同时它也可以判断是否响应你的调用或者只给你提供可用的对象。它也可以在一开始缓存很多对象来为你提供一个池来进行工作。
How to use:
- Add the ObjectPool.cs behavior to a GameObject.
- In the object prefabs array set the prefabs you want to be pooled and reused throughout the game.
- In the amount to buffer array, specify how many of each object you want to instantiate on the scene start so you have pooled objects to start with. If you don't want to specify each, the default buffer amount will just be used.
- In your game call ObjectPool.instance.GetObjectForType(objectType,onlyPooled). For the object type just give the name of the prefab you want to spawn. Specify true or false for the onlyPooled value, if true it will only return a GameObject if there is already an object pooled, if false it will instantiate a new object if one is not available. (Set true if you want to limit how many objects are pooled, very helpful if you want a limited number of effects to ever happen at one time).
- Make sure your Gameobject you get from the pool knows when to add itself back into the pool if removed.
- 把脚本ObjectPool.cs链接到一个GameObject上。
- 在物体预设数组中设置你想要放到池中并重复利用的预设物体。
- 在缓冲数组中,指定你希望每个物体在游戏开始时被实例化的数量,这样在开始的时候你就有了池对象。
- 在你的游戏中调用ObjectPool.instance.GetObjectForType(objectType,onlyPooled)来使用它。objectType写你想生成的预设的名字、并为onlyPooled指定布尔值,如果返回真,它将返回你已经放到池中的对象;如果返回假,它将实例化一个全新的对象。(如果你想限制被池对象的数量,那么设定为真,这样做非常有用,尤其是在需要限制同时播放特效的数量的时候)。
- 确保你从池中调用的对象知道当它被删除时需要返回到池中。
I have also included the Effect.cs and SoundEffect.cs I use in my game to get anyone started right away. The Effect.cs behavior should be added to a game object, then have any number of ParticleEmitters added to it which will run a single emit each time StartEffect is called. Then after a set amount of time it will reset the effect and pool itself. SoundEffect, does a similar thing but with sound effects.
我同时写了Effect.cs和SoundEffect.cs脚本,并把他们用到了游戏中所有需要的地方。Effect.cs脚本需要链接到一个game object上,之后需要加入一些粒子发射器到脚本,当StartEffect被调用时,每次只运行一次发射。然后在过了设定的时间后,它将重置特效并把自己放回池中。SoundEffect的功能和它差不多,只是利用在音效上。
I hope this can help people out who need to limit the number of instantiate calls made with reusable objects.
我希望这个可以帮到有需要的人。
ObjectPool.cs
**Code (csharp):**
using
UnityEngine;
using
System.Collections;
using
System.Collections.Generic;
public
class
ObjectPool : MonoBehaviour
{
public
static
ObjectPool instance;
/// <summary>
/// The object prefabs which the pool can handle.
/// </summary>
public
GameObject[] objectPrefabs;
/// <summary>
/// The pooled objects currently available.
/// </summary>
public
List<GameObject>[] pooledObjects;
/// <summary>
/// The amount of objects of each type to buffer.
/// </summary>
public
int
[] amountToBuffer;
public
int
defaultBufferAmount = 3;
/// <summary>
/// The container object that we will keep unused pooled objects so we dont clog up the editor with objects.
/// </summary>
protected
GameObject containerObject;
void
Awake ()
{
instance =
this
;
}
// Use this for initialization
void
Start ()
{
containerObject =
new
GameObject(
"ObjectPool"
);
//Loop through the object prefabs and make a new list for each one.
//We do this because the pool can only support prefabs set to it in the editor,
//so we can assume the lists of pooled objects are in the same order as object prefabs in the array
pooledObjects =
new
List<GameObject>[objectPrefabs.Length];
int
i = 0;
foreach
( GameObject objectPrefab
in
objectPrefabs )
{
pooledObjects[i] =
new
List<GameObject>();
int
bufferAmount;
if
(i < amountToBuffer.Length) bufferAmount = amountToBuffer[i];
else
bufferAmount = defaultBufferAmount;
for
(
int
n=0; n<bufferAmount; n++)
{
GameObject newObj = Instantiate(objectPrefab)
as
GameObject;
newObj.name = objectPrefab.name;
PoolObject(newObj);
}
i++;
}
}
/// <summary>
/// Gets a new object for the name type provided. If no object type exists or if onlypooled is true and there is no objects of that type in the pool
/// then null will be returned.
/// </summary>
/// <returns>
/// The object for type.
/// </returns>
/// <param name='objectType'>
/// Object type.
/// </param>
/// <param name='onlyPooled'>
/// If true, it will only return an object if there is one currently pooled.
/// </param>
public
GameObject GetObjectForType (
string
objectType ,
bool
onlyPooled )
{
for
(
int
i=0; i<objectPrefabs.Length; i++)
{
GameObject prefab = objectPrefabs[i];
if
(prefab.name == objectType)
{
if
(pooledObjects[i].Count > 0)
{
GameObject pooledObject = pooledObjects[i][0];
pooledObjects[i].RemoveAt(0);
pooledObject.transform.parent =
null
;
pooledObject.SetActiveRecursively(
true
);
return
pooledObject;
}
else
if
(!onlyPooled) {
return
Instantiate(objectPrefabs[i])
as
GameObject;
}
break
;
}
}
//If we have gotten here either there was no object of the specified type or non were left in the pool with onlyPooled set to true
return
null
;
}
/// <summary>
/// Pools the object specified. Will not be pooled if there is no prefab of that type.
/// </summary>
/// <param name='obj'>
/// Object to be pooled.
/// </param>
public
void
PoolObject ( GameObject obj )
{
for
(
int
i=0; i<objectPrefabs.Length; i++)
{
if
(objectPrefabs[i].name == obj.name)
{
obj.SetActiveRecursively(
false
);
obj.transform.parent = containerObject.transform;
pooledObjects[i].Add(obj);
return
;
}
}
}
}
Effect.cs
**Code (csharp):**
using
UnityEngine;
using
System.Collections;
public
class
Effect : MonoBehaviour
{
/// <summary>
/// The array of emitters to fire when the effect starts.
/// </summary>
public
ParticleEmitter[] emitters;
/// <summary>
/// The length of the effect in seconds. After which the effect will be reset and pooled if needed.
/// </summary>
public
float
effectLength = 1f;
/// <summary>
/// Should the effect be added to the effects pool after completion.
/// </summary>
public
bool
poolAfterComplete =
true
;
/// <summary>
/// Resets the effect.
/// </summary>
public
virtual
void
ResetEffect ()
{
if
(poolAfterComplete)
{
ObjectPool.instance.PoolObject(gameObject);
}
else
{
Destroy(gameObject);
}
}
/// <summary>
/// Starts the effect.
/// </summary>
public
virtual
void
StartEffect ()
{
foreach
( ParticleEmitter emitter
in
emitters )
{
emitter.Emit();
}
StartCoroutine(WaitForCompletion());
}
public
IEnumerator WaitForCompletion ()
{
//Wait for the effect to complete itself
yield
return
new
WaitForSeconds(effectLength);
//Reset the now completed effect
ResetEffect();
}
}
SoundEffect.cs
using
UnityEngine;
using
System.Collections;
public
class
SoundEffect : MonoBehaviour
{
/// <summary>
/// The sound source that will be played when the effect is started.
/// </summary>
public
AudioSource soundSource;
/// <summary>
/// The sound clips that will randomly be played if there is more than 1.
/// </summary>
public
AudioClip[] soundClips;
/// <summary>
/// The length of the effectin seconds.
/// </summary>
public
float
effectLength = 1f;
/// <summary>
/// Should the effect be pooled after its completed.
/// </summary>
public
bool
poolAfterComplete =
true
;
/// <summary>
/// Resets the effect.
/// </summary>
public
virtual
void
ResetEffect ()
{
if
(poolAfterComplete)
{
ObjectPool.instance.PoolObject(gameObject);
}
else
{
Destroy(gameObject);
}
}
/// <summary>
/// Starts the effect.
/// </summary>
public
virtual
void
StartEffect ()
{
soundSource.PlayOneShot(soundClips[Random.Range(0,soundClips.Length)]);
StartCoroutine(WaitForCompletion());
}
public
IEnumerator WaitForCompletion ()
{
//Wait for the effect to complete itself
yield
return
new
WaitForSeconds(effectLength);
//Reset the now completed effect
ResetEffect();
}
}
- Unity3D中对象池的使用
- Unity3D中对象池的使用
- Unity3d中对象池(ObjectPool)的实现
- 对Unity3D中对象池的尝试
- <Unity3D>Unity3D中LineRenderer的使用
- <Unity3D>Unity3D中MeshRenderer的使用
- <Unity3D>Unity3D中MeshRenderer的使用
- <Unity3D>Unity3D中MeshRenderer的使用
- <Unity3D>Unity3D中MeshRenderer的使用
- <Unity3D>Unity3D中LineRenderer的使用
- Unity3d中对象池(ObjectPool)的实现思路
- Unity3d中对象池(ObjectPool)的概念和用法
- 关于Unity3D中对象池的创建与回收
- unity3d中协同的使用
- Unity3d中MicroPhone的使用
- Unity3D中定时器的使用
- Unity3d中lightMap的使用
- Unity3D中Prefab的使用
- USACO6.5.3 Betsy's Tour(betsy)
- 关于ASP.NET用VS2012出现数据库内容汉字乱码(中文乱码)或者汉字变问号(中文变问号)的解决办法,非常简单。
- 黑马程序员----OC核心语法
- CentOS下多节点Openstack安装(四)—— Nova安装
- Codeforces Round #289 (Div. 2, ACM ICPC Rules) -- A. Maximum in Table
- Unity3D中对象池的使用
- 程序员注定孤独
- Codeforces Round #289 (Div. 2, ACM ICPC Rules) -- B. Painting Pebbles (贪心)
- USACO6.5.4 The Clocks(clocks)
- iPhone中使用NSLocalizedString实现国际化
- 协程(coroutine)
- HDU 5099 Comparison of Android versions(坑水题)
- 黑马程序员----OC三大特征
- Android中application的使用-------传递全局参数