Problems/Suggestions : Click here and post in the forum or 5argon@exceed7.com

Frequently Asked Questions

(aka. no one actually asked but these explanations doesn't fit anywhere else.)

Q. I need to modify the code. Can you explain the inner workings of Introloop so that I can get started?

The IntroloopPlayer GameObject that appears when you call IntroloopPlayer.Instance.xxxx contains 2 IntroloopTrack.

Each IntroloopTrack represent one IntroloopAudio and we needed 2 because when cross-fading we must hear 2 audio at the same time at some point. Each call to Play method, Introloop will alternate between these two IntroloopTrack.

One IntroloopTrack contains 2 Unity's AudioSource so in total Introloop achieve it's playback function with 4 AudioSource. We need 2 AudioSource because of intro and looping functionality. When approaching loop point, the other AudioSource will be scheduled and waiting to take the baton from previous one, while the previous one is also scheduled to stop at the same time. The scheduling is accurate because it uses AudioSettings.dspTime function in Unity which is independent from game's timescale. Scheduling will happen when one AudioSource is reaching halfway til the switching point.

Each AudioSource actually loads the same audio data (from the same IntroloopAudio) so memory usage is not doubled.

Q. What kind of things can mess up Introloop's scheduling?

Introloop uses AudioSettings.dspTime for scheduling audio pieces, which is independent of normal game's clock. This means if you implement Time.timeScale for pausing the game or for some other reason, it will have no effect on Introloop and it will continue playing. (You can have music still playing while the game pause, for example.)

However there are some situations that can mess up the timing and can produce weird behaviours. For example when creating games in Unity and Introloop is playing, if you make the Unity window inactive everything will stop and resume nicely (The playing audio, AudioSettings.dspTime and Time.time.)

On the other hand if you do things like right-clicking on any GameObject in your Hierarchy and keep the popup menu open, you will notice that your game stopped updating but the music still plays. This will cause Introloop to miss the schedule and I can't fix it because OS-level behaviour is not in my control. This kind of behaviour can only happen in the Editor though, so you should not have to worry about it in real game.

Q. Why Introloop requires Unity 5 and above? Will it works in Unity 4.x with some restrictions?

I am sorry to say that no, it won't work! Read on for detailed reasons that I have been fighting with since 4.x era.

I finished Introloop a long time ago and have been using it in my projects both personal and at work. However the reason I cannot put in on store is because there are much more problems in 4.x about memory that I will explain shortly.

In Unity 4.x if we connect IntroloopAudio to the inspector like we did now in Unity 5, since it contains reference to AudioClip, all the songs will be instantly loaded into memory even if you are not going to play it yet. The same happen when you connect AudioClip to public AudioClip inspector variable. When scene start it checks all inspector slots and load everything. Even if you use Resources.Unload(resource) to quickly free it, the unavoidable memory spike at scene load certainly can crash mobile project with low amount of RAM. (It did really happen to me)

In Unity 5.x if you click any AudioClip you will notice some new checkboxes that is not present in Unity 4.x, Preload Audio Data and Load In Background (Corresponding to the new scripting counterpart AudioClip.preloadAudioData and AudioClip.loadInBackground respectively.) The first one is godsend, since if you uncheck it the audio will not load unless you call the new AudioClip.LoadAudioData() (In Unity 4.x it works like this is set to true all the times.) And so it enables us to use Unity's workflow of connecting the inspector.

How about ditching the connect thing and put the IntroloopAudio in the Resoources folder and load it dynamically in Unity 4.x? Yes, the memory spike is no more but it requires that all your audio is in Resources folder and loaded through Resources.Load(string). This Resources folder restriction feels unnatural and difficult to explain to others and also makes your project messy. (But I have been doing this personally before Unity 5.0) Moreover Resources.Load(string) is designed for run-time execution, it is string based which is not flexible like normal asset-to-inspector preconnecting in Unity. Not to mention that Resources.Unload(resource) is too low-level, sometimes it doesn't unload because something is using the resource and even produce errors. The only error-free way to unload is Resources.UnloadUnusedAssets() but it traverse all GameObject in your scene and it is very bad for performance. (A plugin should never reach out of its own thing also.)

In Unity 5.x to free audio we finally have a dedicated AudioClip.UnloadAudioData() (Counterpart of also new AudioClip.LoadAudioData()) and it is much more reliable than Resource.Unload(resource). The new Load In Background option is not mandatory for Introloop but also useful. In Unity 4.x your code will block when loading audio (Combine that with the must-load-all-connected-audio problem and you get a lag everytime a scene loads!). Checking this to true and your code will continue running while it loads! As an extra, in Unity 5.x the Profiler reports audio data more truthfully. (I have gone through hell being tricked repeatedly in 4.x already...)

For these reasons, if you try Introloop in Unity 4.x it will not compile since it is missing aforementioned 5.x functions.

Q. Now that I use IntroloopAudio to play audio, will Introloop still respect AudioClip import settings?

Yes, because IntroloopAudio is just a link to original audio. Also, it is important to set your import settings correctly. Introloop will work with any combination of load types, (Compressed In Memory, Decompress On Load, Streaming) compression settings (Vorbis, PCM) and options : Load In Background, Preload Audio Data. I recommend unchecking Preload Audio Data for all audio since if not, all IntroloopAudio connected to any GameObject will all be loaded on scene start. Other settings you can set them as you like. As a bonus, if you check Log Information in IntroloopSettings that is attached to the template object and your audio has Load In Background enabled, the log will include a time taken to load that audio too.

Q. I'm sure my boundaries are dead exact but I can still hear a bit of discontinuity in the game!

Actually even the time with 3 decimal places is not enough, since the actual unit for location in audio is sample. The time will be converted to sample by Unity, and this is where an audio might slip off a few samples producing an audible seams.

I use time in seconds since it is easier to get and in most case produce good result. But if your audio is not seamless (and you are sure that your time is exact), you can try adding very small number to both boundaries by the same amount. Since the audio a bit after boundaries should sound the same, doing this should not change the song at all but you will get a new point that a seam might happen. This new seam might work out better than previous point. Try this several times to find out the best spot. (Remember the original point too! You can't go back more than that.)

Q. When will this be usable with WebGL build?

This limitation is actually on Unity's side. As WebGL is currently in preview status, this page lists current limitations. One of them is about audio, which directly affect this plugin. (All "Schedule" method does not work on WebGL)

I have reported the bug, and they responded that it would be resolved in Unity 5.4. So let's wait until then!

When will Introloop support WebGL?

(Ps. Now it's Unity 5.6.0f3 already but after I tested the Schedule methods are still not implemented on WebGL.)