博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
天下性能 唯池不破
阅读量:5957 次
发布时间:2019-06-19

本文共 8789 字,大约阅读时间需要 29 分钟。

文章名字是我杜撰的。之前一直在做server开发,上周有机会接触了client,发现非常多资源没有有效管理起来。甚至有资源泄露的发生,我就先针对特效做了pool,结果在一定程度上纠正之前一直非常难解决的位置同步问题。

总结上来client的资源有:模型、特效、音频、动画等。

音频怎么管理起来呢,http://answers.unity3d.com/questions/482218/best-practices-for-playing-a-lot-of-audio.html这个链接的撸主也提出相同问题:大概是项目有大量音频,假设都是执行时载入,开销太大。怎么解决呢?

这个是下周我的一个私人课题,哈哈。毕竟是业余client。首先了解Audio的相关API,假设播放音频,停止播放,暂停。又一次播放等,假设在某个地点或者某个对象上播放;基本上控制好这几个操作就能够写一个简单的AudioPool了。

网上也找到一个简单的AudioMgr:

// ///// Audio Manager.//// This code is release under the MIT licence. It is provided as-is and without any warranty.//// Developed by Daniel Rodríguez (Seth Illgard) in April 2010// http://www.silentkraken.com//// /using UnityEngine;using System.Collections;public class AudioManager : MonoBehaviour{    public AudioSource Play(AudioClip clip, Transform emitter)    {        return Play(clip, emitter, 1f, 1f);    }    public AudioSource Play(AudioClip clip, Transform emitter, float volume)    {        return Play(clip, emitter, volume, 1f);    }    ///     /// Plays a sound by creating an empty game object with an AudioSource    /// and attaching it to the given transform (so it moves with the transform). Destroys it after it finished playing.    ///     ///     ///     ///     ///     /// 
public AudioSource Play(AudioClip clip, Transform emitter, float volume, float pitch) { //Create an empty game object GameObject go = new GameObject ("Audio: " + clip.name); go.transform.position = emitter.position; go.transform.parent = emitter; //Create the source AudioSource source = go.AddComponent
(); source.clip = clip; source.volume = volume; source.pitch = pitch; source.Play (); Destroy (go, clip.length); return source; } public AudioSource Play(AudioClip clip, Vector3 point) { return Play(clip, point, 1f, 1f); } public AudioSource Play(AudioClip clip, Vector3 point, float volume) { return Play(clip, point, volume, 1f); } ///
/// Plays a sound at the given point in space by creating an empty game object with an AudioSource /// in that place and destroys it after it finished playing. /// ///
///
///
///
///
public AudioSource Play(AudioClip clip, Vector3 point, float volume, float pitch) { //Create an empty game object GameObject go = new GameObject("Audio: " + clip.name); go.transform.position = point; //Create the source AudioSource source = go.AddComponent
(); source.clip = clip; source.volume = volume; source.pitch = pitch; source.Play(); Destroy(go, clip.length); return source; }}
就是对AudioClip,正是我须要补的基础知识。

然后这里另一些Pool的知识 http://forum.unity3d.com/threads/simple-reusable-object-pool-help-limit-your-instantiations.76851/:

当中还有代码,针对特效的管理:

using UnityEngine;using System.Collections; public class Effect : MonoBehaviour{    ///     /// The array of emitters to fire when the effect starts.    ///     public ParticleEmitter[] emitters;       ///     /// The length of the effect in seconds.  After which the effect will be reset and pooled if needed.    ///     public float effectLength = 1f;          ///     /// Should the effect be added to the effects pool after completion.    ///     public bool poolAfterComplete = true;           ///     /// Resets the effect.    ///     public virtual void ResetEffect ()    {        if(poolAfterComplete)        {            ObjectPool.instance.PoolObject(gameObject);        } else {            Destroy(gameObject);        }    }       ///     /// Starts the effect.    ///     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();           }         }
比方同一设置特效长度,启动特效后启动所以离子,并启动一个协程。时间一到就ResetEffect,这时候回放到Pool里。

using UnityEngine;using System.Collections; public class SoundEffect : MonoBehaviour{       ///     /// The sound source that will be played when the effect is started.    ///     public AudioSource soundSource;       ///     /// The sound clips that will randomly be played if there is more than 1.    ///     public AudioClip[] soundClips;       ///     /// The length of the effectin seconds.    ///     public float effectLength = 1f;       ///     /// Should the effect be pooled after its completed.    ///     public bool poolAfterComplete = true;             ///     /// Resets the effect.    ///     public virtual void ResetEffect ()    {        if(poolAfterComplete)        {            ObjectPool.instance.PoolObject(gameObject);        } else {            Destroy(gameObject);        }    }       ///     /// Starts the effect.    ///     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();           }      }
音频的管理跟特效管理类似,就是播放的API不一样。操作完毕后一样进行回收。

那这个池子是怎么写的呢?

using UnityEngine;using System.Collections;using System.Collections.Generic; public class ObjectPool : MonoBehaviour{       public static ObjectPool instance;       ///     /// The object prefabs which the pool can handle.    ///     public GameObject[] objectPrefabs;       ///     /// The pooled objects currently available.    ///     public List
[] pooledObjects; ///
/// The amount of objects of each type to buffer. /// public int[] amountToBuffer; public int defaultBufferAmount = 3; ///
/// The container object that we will keep unused pooled objects so we dont clog up the editor with objects. /// 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
[objectPrefabs.Length]; int i = 0; foreach ( GameObject objectPrefab in objectPrefabs ) { pooledObjects[i] = new List
(); int bufferAmount; if(i < amountToBuffer.Length) bufferAmount = amountToBuffer[i]; else bufferAmount = defaultBufferAmount; for ( int n=0; n
/// 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. /// ///
/// The object for type. ///
///
/// Object type. /// ///
/// If true, it will only return an object if there is one currently pooled. /// public GameObject GetObjectForType ( string objectType , bool onlyPooled ) { for(int i=0; i
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; } ///
/// Pools the object specified. Will not be pooled if there is no prefab of that type. /// ///
/// Object to be pooled. /// public void PoolObject ( GameObject obj ) { for ( int i=0; i
事实上这个Pool有多重写法,我在项目里的写法就是写成单例类。以资源的文件位置为Key,比方一个特效名字是“hit/release/bloat”就存进去。

这个帖子的启示点是播放一个时间段的特效用协程来完毕,比现有项目用一个Mgr管理高效多了。

转载地址:http://kiexx.baihongyu.com/

你可能感兴趣的文章
修复群集无法切换磁盘问题
查看>>
expdp 详解及实例
查看>>
洛谷——P1495 曹冲养猪
查看>>
C++中 栈的简单封装
查看>>
我的友情链接
查看>>
Linux常用命令--iconv
查看>>
varnish的了解与常用配置使用
查看>>
Product user profile information 没有导入
查看>>
DELL T410服务器U盘安装Centos7
查看>>
解读最具O2O属性—哈根达斯微信企业号的成功之道
查看>>
Sqlserver2008日志压缩
查看>>
虚拟机usb无线上网同时主机本地上网或无线无线上网
查看>>
View的事件分发机制
查看>>
Android Ndef Message解析
查看>>
mysqldump backup script
查看>>
coding4fun比赛总结
查看>>
Windows Server 2003 系统安装
查看>>
庖丁解牛获取连接状态数的awk数组命令
查看>>
jQueryMobile新版中导航栏按钮消失的解决方法
查看>>
使用触发器记录oracle用户登陆信息
查看>>