BLOG main image
for our next (37)
Dev (32)
Mac (1)
Windows (2)
FreeTalk (1)
Shell (1)
Private (0)
Visitors up to today!
Today hit, Yesterday hit
daisy rss
tistory 티스토리 가입하기!
'2012/01'에 해당되는 글 1건
2012. 1. 25. 15:26

The project I am currently programming audio for targets low end machines. I spent many many hours google and forum searching trying to find definitive answers to how Audio works, especially when related to how it consumes memory and how I can release that memory when the audio is no longer needed. Hopefully the following information will save you loads of time.

Hierarchy and Audio Memory
Any AudioClips that are referenced in the hierarchy of a scene will be loaded in to memory when the scene gets loaded. Keep this in mind if you have a large audio library and are throwing a huge prefab of all your sounds into the scene hierarchy (nom nom memory nom nom). The only way to avoid this is to load audio dynamically with scripts.

Objects and Garbage Collection
Unity keeps track of anything you create that extends from their Object class. That means a couple things. If you do reference one of those objects and set that reference to null, the garbage collector WILL NOT pick it up. The reason for this is that the object still has references in Unity. If you want to release memory for Unity Objects you must call Destroy and pass the object as a parameter. Why is this important? AudioClips extend from Object. Hence setting them to null will not release them from memory.

Resources.Load
Resources.Load creates an object in memory and returns a reference to it. That object is actually the physical asset in your library which is loaded from a .asset file. This file is created when you build.

If you call Destroy on the resource inside the editor you will get a warning that it will delete the actual asset itself. The editor protects you against doing this, but the build will actually delete the asset (but not permanently – more testing required to confirm full behavior). DestroyImmediate will destroy the asset without warning, so be careful when using it. If you are in the editor and that happens you will have to reimport your asset.

The only way to release the memory held by the resource is to call Resources.UnloadUnusedAssets(). This process isn’t the fastest, so doing it during an Update can hurt your performance.

One of the strongest advantages to using Resources.Load is that multiple copies of your AudioClip do not increase your memory size. You can play your clip with 8 different sources and all 8 will play individually and fully layered without adding more AudioClips to memory. The main disadvantage is that if you need to free up memory that an asset occupies, you really can’t be specific and must run the bulky Resources.UnloadUnusedAssets function.

Note that you cannot instantiate an asset object in the build. The editor will allow you to do this however, which is unfortunately very misleading.

Asset Bundles
Asset bundles behave exactly like Resources.Load. Think of them as a way to fragment the .asset file into .unity3d files. This is especially powerful for the web player since you can prioritize which assets get downloaded by the user. Asset bundles need to be loaded with the WWW class. Just like Resources.Load, you will receive an actual asset so destroying them to release memory is not an option. You can however be more specific when unloading them compared to Resources.UnloadUnusedAssets.

WWW
WWW.audioClip does not return a reference to an AudioClip. In fact, it creates an entirely new clip object. The documentation does state that the returned AudioClip is “generated”, but let’s explore the implications of that statement. Note that WWW.GetAudioClip() does the exact same thing except is allows you to specify whether the sound is 3D or 2D.

You can see that new clips are generated by running the following script:


WWW www = new WWW(urltosound);
AudioClip clip;
 
for (int i = 0; i < 20; i++)
{
    clip = www.audioClip;
}
Debug.Log("AudioClips " + FindObjectsOfTypeAll(typeof(AudioClip)).Length);

You will see that 20 AudioClips are created. That creates a huge problem. These clips will reside in memory until they are destroyed. You can do that manually if you have a reference or if you don’t, by calling Resources.UnloadUnusedAssets(). Note that UnloadUnusedAssets will look through the entire game hierarchy and scripts to make sure there are no references to the resources. This IS slow so avoid putting in places where it will be called often (Update for example).

Based on testing 3.3.0f4 and recent forum postings, you can not stream audio in the standalone player with the WWW class using WWW.GetAudioClip() and WWW.audioClip. Both return unplayable sounds until the file has been fully loaded. You can however stream Ogg files using WWW.oggVorbis (which sadly is not documented).

WWW variables DO take up memory space. Since they do not extend from a Unity Object, you can release them from memory by setting them to null.

Unlike Resources.Load, AudioClips you get from WWW do not automatically layer. In other words, if you play the clip with 8 sources, you will only hear one instance of your AudioClip (restarts to the beginning with each call to Play). So for each instance you want, you must create a new clip for it. You can do this with Instantiate(), but with one caveat: PlayOneShot() will return a channel error. That means that you must manually handle the creation and destruction of your AudioSources when using sounds created from WWW. If you do wish to use PlayOneShot(), you can instead create your copies by keeping the WWW in memory and calling WWW.audioClip or WWW.GetAudioClip().

PlayOneShot
PlayOneShot automatically creates an AudioSource for you and destroys it. However, what it does not do is destroy the AudioClip that you pass it. Hence you could get a huge memory leak if you pass it www.audioClip since it will create an un-referenced AudioClip object each time you PlayOneShot.

AudioSource
AudioSource.clip is a reference to an AudioClip. So you can destroy the AudioClip by running Destroy(AudioSource.clip). If you have another reference to the destroyed clip it will become null. Destroying an AudioSource DOES NOT destroy the AudioClip it references. This is significant if you are using AudioSources to store you AudioClips. You must destroy the AudioClip before you destroy the AudioSource if you want all related memory to get released.

Original : http://www.alexander-fisher.com/?p=351


'Dev > Unity3D' 카테고리의 다른 글

Texture, Resource.... and Memory!!  (1) 2012.06.05
GameObject active 여부와 Coroutine / Invoke...  (1) 2012.06.05
unity3d data path!  (0) 2011.12.14
Unity3D Mesh Create Code  (0) 2011.10.20
Unity3D Inspector object 선택후 일괄 처리  (0) 2011.07.02
prev"" #1 next