Search Unity

  1. Unity 2018.3 is now released.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Want more efficiency in your development work? Sign up to receive weekly tech and creative know-how from Unity experts.
    Dismiss Notice
  4. Build games and experiences that can load instantly and without install. Explore the Project Tiny Preview today!
    Dismiss Notice
  5. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  6. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

Introloop - Easily play looping music with intro section [V2.0 RELEASED]

Discussion in 'Assets and Asset Store' started by 5argon, Jan 8, 2016.

  1. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790


    Introloop - Easily play looping music with intro section
    Requirement : Unity 5.5.6 or above. Constant pitch only. WebGL not supported yet as of 5.6.0f3.
    Demo, Installations, Scripting Ref., FAQ : http://www.exceed7.com/introloop/
    Asset Store Link : http://u3d.as/mxD
    Contact : Post on this thread or mail to 5argon@exceed7.com

    Less than 1 minute explanation of what it is :

    Release Note (View all versions at http://exceed7.com/introloop/)
    • (05/05/2018) Version 3.0
      • Multiple Introloop singleton playing at the same time by subclassing
        You could have MyBGMPlayer.Get.PlayBattleTheme() + MyAmbientPlayer.Get.PlayWindy() instead of IntroloopPlayer.Instance.Play(battleTheme) without the wind. Each subclass could use its own template prefab so you can pre-connect things or route mixers before runtime.
      • Local Introloop
        GetComponent<IntroloopAudio>() that you have attached somewhere in the scene and everything works. You can also .AddComponent<IntroloopAudio>() and the next frame it will be ready to play. Local Introloop does not automatically get DontDestroyOnLoad unlike the static-singleton IntroloopPlayer.Instance or the new Subclass.Get.
      • Positional Introloop
        The point of having local Introloop is you could have it positioned meaningfully. Imagine you have 10 bushes with its own seamlessly looping leaf sound. You can have Introloop in each bush and as you approach it will get louder. There are many additional methods to help you setup audio source spatial curve to an IntroloopPlayer.
    Get that charm of a polished game. Adds huge value to music. Directs player's feel with an intro. Gives every song a memorable and immersive feeling which can't be put in an OST.

    Let's recall memorable moment from favorite games you have played. A destined fight with arch rival? Roaming overworld map for the first time? An opening stage that really hooks you that you can't put down the joystick?

    Wondered why they stuck so well in your memory? The answer is music intro and I am going to make you realize that it is important. I think I am not the only one who noticed this so I made Introloop for the person who cares about his own game soundtrack :D

    Many commercial game music has certain charm when you are listening to it in game because they're programmed to have a nice intro that sets the mood of that particular scene, before transitioning seamlessly to a music loop, never having to play the intro again. This is the source of immersive feeling you never get when you listen to the song again in an OST.

    In Unity if you select "Loop" in an AudioSource, the song will loop to beginning when it reaches the very end.


    With Introloop, you can specify 2 time point "Intro Boundary" and "Looping Boundary" in your audio. Playing with this plugin, it will now loop back to Intro Boundary when it reaches Looping Boundary, effectively make the section before Intro Boundary an intro section that plays only once and the rest will be looping.


    Advantages :
    No need to cut the actual file into 2 parts.
    ► And because of this you can use any compression (like OGG) without fear of messing the precision at the head and tail of audio file. Feel free to utilize the Unity's compression quality slider - and any other audio settings built-in.
    ► By not physically cutting the audio, it is easy to experiment and adjust the loop point right in Unity. In 2 split clips solution you will have to cut the music over and over again until it is seamless enough.
    ► Updating music from your composer is easy, as long as the song structure is the same you can just replace the whole music and use the old boundaries.
    ► Automatic audio memory releasing at appropriate time, which is perfect for mobile project. This is the reason of Unity 5 requirement. Any other solutions that claims to works with Unity 4.x cannot manually free audio data, as this function came with Unity 5.
    ► Supports pause, resume, fade in, fade out and even cross fading between intro-included audio. Built in pop/clicks reduction when stopping the music suddenly. You can also set the default volume per-audio.
    ► Route the entire plugin to your game's Unity 5 audio mixer for your own higher level control. Casting epic spell and wanted to duck the BGM down? No problem, route to your mixer and use Unity 5's great ducking feature on it.
    ► Modular. Easily integrates. Came with no other assortment of audio features.
    ► The license purchase came with full source code.

    It is a common practice used in many commercial games. Intro adds huge value to music, turning into a powerful tool for directing player's feel and blends more into gameplay.

    It's not just about random battles, any feeling you would like your player to feel, use music intro to direct him/her to that direction right from the start then keep it going with your gameplay.

    See real examples from commercial games and try out the demo in the website below.
    http://www.exceed7.com/introloop/

    The demo contains several songs I prepared for you to play with. It is available to try on both desktop and mobile devices, so you can see that it works cross-platform.


    Feel free to ask me any question about Introloop. Criticisms, suggestions are all welcomed as I wanted to know what you guys want. Thank you!

    (As for why WebGL is not supported, on that platform the Scheduled audio functions are not implemented.)

    If you want to use a variable pitch, I suggest trying Master Audio's playlist function (in the Asset Store) for the time being. You have to physically cut your audio, but it supports changing pitch as if your audio goes faster it simply just go to "the next one" in the playlist unlike tight scheduling I use in Introloop.
     
    Last edited: May 5, 2018
  2. Cascho01

    Cascho01

    Joined:
    Mar 19, 2010
    Posts:
    1,046
    Cool.
    Can we expect a smooth loop without any noticable "cracks" when it jumps from end to startpoint?
    In my experience this is the hardest point to solve.
     
  3. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    Yes! You can expect it as long as your 2 time point is precise enough. The timing is achieved by not the normal game time nor coroutine but by
    Code (CSharp):
    1. AudioSettings.dspTime, AudioSource.PlayScheduled, AudioSource.SetScheduledStartTime and AudioSource.SetScheduledEndTime
    internally to ensure this.

    I have provided the demo in this page so you can test the seamless-ness. Or alternatively if you don't have the PC now, download this game to your mobile phone and hear if you notice any cracks or not. (The title screen already is using Introloop)
     
    Last edited: Jan 8, 2016
  4. hima

    hima

    Joined:
    Oct 1, 2010
    Posts:
    183
    Is there a way to change a track's volume in real time? In my game, the player can change global background music volume in the option screen. It'd be nice if they can hear the change in real time.
     
  5. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    Yes. For global volume/sfx that you will adjust in option screen, the current best practice in Unity 5 is using the Audio Mixer. You can route Introloop's audio to your mixer by following this tutorial : http://www.exceed7.com/introloop/getting-started.html

    After this, the level of that track you routed to can be controlled from script. Mainly via SetFloat/GetFloat which you can then link to your slider UI.
    https://unity3d.com/learn/tutorials/modules/beginner/5-pre-order-beta/exposed-audiomixer-parameters
     
    hima likes this.
  6. hima

    hima

    Joined:
    Oct 1, 2010
    Posts:
    183
    Thank you! I totally forgot about the new Audio features in Unity5. This mean I have to rewrite how I handle audio in the game again but it should be much easier to deal with.
     
    5argon likes this.
  7. Fallenleader

    Fallenleader

    Joined:
    Jan 26, 2015
    Posts:
    7
    The only flaw I have seen with this, is for systems like the N3DS.
    Ultimately, this solution is exactly what I need, but I cannot guarantee it will work for specific devices, which is why I am holding off on a purchase.
    How would using your solution work for all devices, and not just a specific set for normal everyday user devices?
     
  8. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    Hello, thank you for interested in Introloop. It's true that I could not confirm either that if it is working on 3DS or not because I don't have their dev kits. At first I assume it is Unity's job to make the code cross-compile successfully but then there is the case like WebGL where all audio "Schedule" functions are still not implemented. (they told me it is ready in 5.4, but haven't tested since then.)

    I am not sure that it also happen in 3DS or not but I could not verify it. (I will update the website with a list of untested systems along with the next update)
     
  9. Douvantzis

    Douvantzis

    Joined:
    Mar 21, 2016
    Posts:
    73
    Is the track decoded or is it streamed form the source?
     
  10. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    Hello, sorry for the late reply. You can choose whatever import settings you like and they will be in effect like it normally did. (Encoding quality, playback mode, etc.)

    Introloop uses original audio without cutting or altering anything. Internally basically it is 4 audio sources which cooperate with each others and each one have your music file loaded, so in turn, audio sources will respect all import settings.
     
  11. oliran

    oliran

    Joined:
    Sep 29, 2015
    Posts:
    35
    IntroloopPlayer randomly doesn't play the music at all (Unity 5.5). I don't know how to reproduce it as it seems random.

    In case you need it, the settings for the audioclip is:
    Load in background disabled
    Decompress On Load
    Preload Audio Data enabled
    Vorbis

    Any ideas? Has anyone else experienced this?
     
  12. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    Thank you for the report. I will look into this immediately.
    My active project that also uses Introloop is also on 5.5, so I will try to reproduce it. (If I have fixed the issue, I will come back to report again.)

    If the audio file is not sensitive, you can send the audio file, the audio's .meta file, and the corresponding Introloop asset file (that contains the 2 loop points) to me via DM. It will help me find the problem!
     
  13. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    I am pleased to inform you that version 2.0 of Introloop has finally been released. (It is also on sale 30% as a part of Unity open sale until the end of this April 2017.)

    https://www.assetstore.unity3d.com/en/#!/content/51095

    Release Note
    • (14/04/2017) Version 2.0 - New functions includes :
      • Pitch - You can now specify pitch in an IntroloopAudio asset file. If you would like to use multiple pitches of the same audio, you can just copy the asset file and have different pitches. It can reference to the same actual audio file. Works fine with pause, resume, automatic memory management.
      • Preload - A feature where critical precision of starting an Introloop Audio is needed. Load the audio by calling IntroloopAudio.Instance.Preload(yourIntroloopAudio) beforehand to pre-consume memory, and then call Play as usual afterwards.
      • Ogg Streaming as Introloop on iOS/Android - In Unity 5.5.2 they added support for choosing "Streaming" with OGG on iOS/Android. I am happy to inform that this option works with Introloop. Everthing will be the same except it will not cost you as much memory of an entire audio on Play as before in an exchange for some CPU workload.
    The website (http://exceed7.com/introloop/) also has already been updated with demo of version 2.0, which you can try the song with altered pitch. As always, if you found any problems I am ready to help you here or in the e-mail. Thank you!
     
  14. arkogelul

    arkogelul

    Joined:
    Nov 14, 2016
    Posts:
    35
    Hi,

    That looks great ! i'm trying to achieve that but couldn't get my head around how dspTime and playSchedule functions works.
    Is it possible to loop the intro and the outro instead of looping the middle part ?
     
  15. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    Hello. By definition of intro and outro I think it should not be seamlessly loopable? That's why we need Introloop, to loop the middle loopable part, and you would not have an outro since by definition of "loop" the music should never ends, thus no need for an outro.

    But if you do want to loop the intro over and over, you could set up the intro boundary as 0 and outro boundary as the "supposed to be" intro boundary.

    With the same idea you could set the intro boundary as the "supposed to be" looping boundary and outro boundary as the song's length, it should loop the outro over and over once it arrives there.

    Please do clarify if I misunderstand something. Thank you.
     
  16. arkogelul

    arkogelul

    Joined:
    Nov 14, 2016
    Posts:
    35
    I actually would like to loop the intro until a certain event, then play the middle part once and then play the "outro" over and over until another event ends the music (fade out).

    EDIT: Nevermind, I actually managed to do what I wanted :)
     
    Last edited: Sep 20, 2017
    5argon likes this.
  17. Fallenleader

    Fallenleader

    Joined:
    Jan 26, 2015
    Posts:
    7
    The ONLY reason I bought this already is because I am making my game for other systems than this specific embedded one. It seems one could achieve the same effect by fully grasping dspTime, SetScheduledStartTime, SetScheduledEndTime, and PlayScheduled, but be it lack of time, laziness, or both, I just decided to use your tool as it will save me time in the end.
    This all being said, I really need to know what kind of memory footprint I will have to expect compared to toher means of looping music. I actually have 2 other usable options available that approach this solution in a less than ideal manor without much memory overhead.
    Can you please share in both Megabytes and Megabits (MB and MiB receptively) the typical memory overhead for a 3.5MB song at 32 bit Wav (on import)?
    I am targeting the Nintendo 3DS, which already has limited memory, and I am trying to land it onto an Old 3DS variant which is even more crippled memory wise( try ~16MB memory to work with).
    If you cannot specify something this precise, can you at least explain how much additional memory overhead it would have in general compared to a solution like 5000 samples of silence for a buffer, as my other method uses?
     
  18. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    Hello. Yes this project is basically manipulating dspTime, SetScheduledStartTime, SetScheduledEndTime, and PlayScheduled to achieve the effect while multiple AudioSources coordinate with each other.

    The memory overhead will be the same as Unity's normal audio loading and playing, as it is basically just 4 AudioSources that loads the same audio. This means the memory depends on your import settings of the said audio. (Thus "Streaming" would use the least memory as it loads just around the playhead.) You can determine the memory overhead by dragging your 3.5MB 32-bit song to the AudioSource (with your desired loading type) and look at the Profiler. (Beware that just clicking the file might cause a false memory overhead as the Profiler profiles memories used for previewing in the editor)

    Other than that, the additional memory overhead is from storing the GameObjects and variables that manages the looping mechanism. I don't think that is significant compared to the audio data itself.

    However Introloop does something more that are different from just issuing .Play() .Stop() directly to the AudioSource :

    1. When you stop the audio (and the audio finished fading out completely, if you choose to stop with a fade out), it is automatically unloaded from memory. This is not the case when you just call "Stop" to the AudioSource. This is in effect if you choose "Decompress on load" or "Compressed in memory" type.

    2. If you cross fade the audio, there will be a moment when both audio are in memory. This means if both audio file has "Decompress On Load" you will have the whole size of 2 audios in the memory in that cross fading moment. However, when it finished cross fading the faded out ones will be automatically unloaded. If your memory allowance is very critical you might want to avoid the cross fading by fading out the first song then begin playing the second song later.

    Also please note that I haven't test on the 3DS as I don't have the dev kit. I once test on the WebGL build and there is a problem that web platform does not support any _Scheduled_ methods at all, I don't think that is the case with 3DS but there might be a similar problem of unsupported method that Unity team have not yet implement. In the case that it really does not work please inform me (and you can also issue a refund). Thank you.
     
    Last edited: Oct 27, 2017
    Fallenleader likes this.
  19. Fallenleader

    Fallenleader

    Joined:
    Jan 26, 2015
    Posts:
    7
    Please don't get me wrong. I bought this for more platforms than the 3DS ;)
    I eventually plan to learn how dspTime, SetScheduledStartTime, SetScheduledEndTime, and PlayScheduled works for the sake of being thorough, but this tool is still quite useful.
    This is why I said that the only reason I went ahead and bought it despite not being sure about 3DS support is I will definitely utilize it on other platforms. I am quite sure you have extensively tested it on PC and Android if nothing else, and as many users as you have, I am sure all Unity free platforms are tested, if not other systems that require devnet access (e.g. Playstation, Xbox, Nintendo, etc).
    I have seen enough to be impressed. I can easily make a quick test as soon as possible to find out for you.

    On another note, does this have pause and resume support? How does oneshot SFX sounds work?
     
  20. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    Introloop can pause and resume! You can try the free demo in the website http://exceed7.com/introloop/ the last 3 colored button can demonstrate the function.

    The limitation is that if you issued Stop, currently there is no way to start at any other point besides the beginning. I planned to make it so that you can specify a time to start the song, that also take account of the looping function. (For example a song with 1s intro and 4s looping part, if you call PlayFrom(5) you would begin at the intro boundary because 5s means it have already looped 1 time.)

    For oneshot SFX, Introloop is not designed to play SFX. You can instead use a normal PlayOneShot(). (I am not sure if I misunderstood something, as "SFX" is not supposed to be looping or has an intro?) Introloop is not a complete audio management as opposed solutions like Master Audio, SoundManagerPro etc. that aims to be all-in-one. Introloop is just a tool that you can use just for the BGM part of your game.
     
    Last edited: Nov 8, 2017
  21. castor76

    castor76

    Joined:
    Dec 5, 2011
    Posts:
    1,282
    Hello.

    I am enjoying IntroLoop. But I recently came to some question about how it is able to accurately loop the music.

    As I understand Unity Update API will respond only as quickly as the next frame update. So if the looping time falls in between each frame draw call (aka in between update call) how do you handle such looping case smoothly? Do you internally split the music clip asset into 2 different parts?
     
  22. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    Hello, thank you for using Introloop.

    Introloop does not split the music clip or buffer data at any point. You are correct about Unity's Update API, but Unity has an another timing mechanism specifically for audio, dspTime (https://docs.unity3d.com/ScriptReference/AudioSettings-dspTime.html).

    There are 3 methods that utilize this, AudioSource.PlayScheduled, SetScheduledStartTime, and SetScheduledEndTime. After you call them, when dspTime comes to that point you specify an audio will play regardless of if it is in-between Update frame or not. Therefore I can set it up to loop to itself without cutting the asset. (Actually it is not looping to itself but a duplicate of itself that is waiting at the seam. When dspTime arrives one will stop and the other one will begin.)

    The difficulties of using this is it is like setting a trap. You have to plan things ahead of time to also allows it to loads up the audio. Introloop's strategy is to schedule when there is halfway to go approaching the loop point. The schedule cannot be cancelled, if user decides to stop, pause or change music in the period after it already scheduled we also have to reschedule to override the old ones. The schedule can even be met while an AudioSource is stopping or pausing but luckily will not take effect until it is playing again, so we can reschedule before resuming to prevent it jumping to a wrong place.
     
  23. MetaMythril

    MetaMythril

    Joined:
    May 5, 2010
    Posts:
    149
    @5argon Hi! I just wanted to share an issue I had that I was able to fix.

    In IntroloopPlayer.FadeUpdate() you use Time.deltaTime to fade volumes but this causes functions like Pause() to stop working for me when my game did something that caused Time.timeScale to be set to 0 (effectively pausing the game).

    Changing the use of Time.deltaTime to Time.unscaledDeltaTime fixed my issue and now I'm able to pause and resume music even if the timeScale is at 0.

    My justification for this is for things like when a player acquires a new weapon or item and a jingle melody plays (like in Super Metroid). I needed to pause the currently playing track so I could play the jingle on a separate AudioSource (not connected to IntroloopPlayer) since it's just a one-off sound. I needed to "pause" the game when the notification window and jingle is displayed, then promptly resume once window was dismissed.

    Would you consider making this fix permanent?
     
  24. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    Sorry for the long absent,

    Yes I have overlooked this case, this is definitely a problem. Audio should not be related to game's time scale by definition in most case. Thank you for reporting.

    I will include this fix in the next update along with a new feature, that is allowing you to subclass IntroloopPlayer and thus able to make a specialized Play method tailored for your game, (e.g. EventMusicPlayer.Get.PlayRelaxed()) or having multiple instances running at the same time. (e.g. BGMPlayer.Get.PlayField(); AmbientPlayer.Get.PlayWindy(); )
     
    MetaMythril likes this.
  25. Marrt

    Marrt

    Joined:
    Feb 7, 2012
    Posts:
    517
    Hi, i can't believe this is still not part of vanilla Unity.

    Is this plugin suitable for:
    - short sounds? like machine-gun-loops with a fadeout-echo after the last shot is fired
    - mobile? I plan to have at least two of such machine-gun-audiosources active at the same time plus a seamlessly looping background track. Would this compromise performance compared to the normal AudioSource?

    Thanks!
     
  26. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    Hello Marrt, (I can't believe it too)

    1. Introloop was not designed for sound effects but it should work with short sound. However the situation you described cannot be achieved by Introloop. Introloop adds intro but you wants to add a unique outro. What Introloop can do for you is have a machine gun with startup sound (as an intro) then enters a loop part. When you stop firing, you could tell Introloop to stop then play an additional fade out sound you have. (This part is not related to Introloop and you can use a regular AudioSource, or also Introloop)

    For that kind of behavioral sound I think things like WWISE or fmod is the correct tool for this job. You can set your entire project's sound effect to have various behavior. You can even have just one shot sound (not a loop) one rev up sound and one wind down sound and program fmod to play rev up -> one shot repeatedly (+with variations) -> wind down when asked to. Plus all the settings are separated from the project, so you could have someone else design the sound without touching Unity. Beware of a latency problem, in fmod I have tested and the latency seems to be about Unity's "Default" or "Good Latency". There might be a setting that enable fmod to match Unity's "Best Latency" but I stopped using fmod since long time ago.

    Ps. I am actually making a WWISE/fmod-like tool that works in Unity and manage your sound effects + program it's behavior like what I described and directly solve your problem. But it will be very long way to go until it finishes that you should not wait for it. (I won't release it until I see it working fine in my new game, which is also far from finish)

    2. Introloop was made originally for mobile use but it works in a standalone also. (It does not work on WebGL) Theoretically Introloop is 4 AudioSources working together. (There is a detailed explanation in http://exceed7.com/introloop/faq.html) So strictly speaking the compromise is +3 AudioSource. However from my experience from my own game (iOS/Android game) 3 more AudioSources does not cause any noticable performance loss. There is no additional cost of memory usage since all 4 AudioSources uses the same audio in the memory. The only point is that when you crossfade songs you will have 2 audio in memory for a short time before the old one automatically unload itself when completely faded out.
     
    Last edited: Mar 30, 2018
    Marrt likes this.
  27. Fallenleader

    Fallenleader

    Joined:
    Jan 26, 2015
    Posts:
    7
    I would like to report back on using Introloop on the 3DS.
    Sadly, I haven't had much luck. This isn't so much due to introloop itself failing, as DSP issues from what I can gather (though this side of development is honestly not my strength). The scheduled audio when played together for the looping part will heavily desync, making this tool not an option for that platform unfortunately.

    I would appreciate further correspondence, maybe even a more idiot friendly solution using a single script, as I can easily split my audio, but currently cannot avoid that glitch of silence when swapping an intro to a looping song. This also adds the additional headache of multiple files, and probably more overhead I am not thinking about right off hand.

    For other platforms, this tool has been invaluable, and despite my initial skepticism, I am extremely content. Cheap but effective. This tool could easily sell for way more than you list, but you chose not to price gouge consumers, and unlike many other assets I have seen, provide active feedback!
     
    5argon likes this.
  28. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    Thank you!

    If all the __Schedule method is not working precisely then we don't have much option because it is the most precise one. But if the problem is only with `dspTime` then it might be possible to schedule with a normal coroutine. (yield return new WaitForSeconds(___)) But still the time will not be precise because it is frame-dependent. It will resume at the first frame after that wait time and I think it won't be seamless enough. I guess it is the same with `MonoBehavior.Invoke`. If you can put up with frame-level seams (That would be around 1/30s ~ 1/60s depending on your frame rate) it might be enough.

    Or you could employ a cross-fade trick and try to blend between 2 clips. I have done it with ambient sounds before because it would blend easier (around Unity 4 era) but it caused many bugs when the game pause, entering cutscenes, time slowdown, etc. (It actually leads to me creating Introloop to based on Scheduled method more than a year later, when I saw Unity 5 can defer loading audio and manually unloads audio.)

    I would like a 3DS to test, but honestly I am heavily interested in Nintendo Switch for my next game!
     
  29. Fallenleader

    Fallenleader

    Joined:
    Jan 26, 2015
    Posts:
    7
    3DS is relatively easy to work with, assuming you have a spare one you can mod, and a bit of patience.
    Granted, you are confined to 2 rules of thumb:
    1: Developing outside of a dev/testkit means final products would involve purchasing an actual testkit before considering submission (that should be clearly evident), and it technically breaks ToS, so speak no evil, get no ban hammer. Development rules apply regardless if you convert the output or not. if you run into an issue, the tools to dump debug logs work all the same. A CFW unit for developing is basically a slightly limited testkit that can play retail games.
    2: Builds require you to manually convert them to work on the retail unit. This can present the possibility of bugs that normally wouldn't exist (I have had no issues so far). It is straightforward to do, but becomes a tedious chore if you say forget a single line of code, as you have to compile, convert, and reinstall each time, rather than do a signle compile and install for the testkit.

    Testkits are easily obtainable for only a margin more than an actual NEW retail unit, though you can also get a used retail Old 2DS (unadvised due to memory limitations) or even a used New 2DS for fairly cheap, and modding it is actually easy enough if you know how to read directions. Only thing you lack is 3D, and you sacrifice the ability to immediately submit your game, as well as gain the minor headaches I mentioned before. It boils down to cost vs usage.

    Also, Nintendo is doing Switch units/access on a case by case basis. While I have a game fairly well along in development, I was rejected on my request. YMMV. I am honestly eager to get my hands on my own switch testkit to start porting to, so I have been putting my retail 3DS to use in the meantime while I save up for when I am able to get my switch unit. If I complete my game if/before Switch becomes openly available, I will get myself a 3DS testkit to make sure everything is ready, and release a 3DS version for more leverage for a Switch.
     
    5argon likes this.
  30. KOemxe

    KOemxe

    Joined:
    May 1, 2018
    Posts:
    22
    Hi @5argon !

    Thanks very much for writing what you have with this. I have enjoyed your InterLoop audio library so far.

    One issue. I've been playing with this to figure out how to loop music consistently between levels until you reach the end menu in the build list of scenes. I've been trying to use a counter as a static instance outside of my Game Manager that plays the tracks, but it seems that the Awake method spawns a new instance of InterLoop each level? In this case, it seems more copies of my audio track try to play at the same time, causing some sound conflicts.

    Would you have some insight in how to handle this issue?

    Code (CSharp):
    1. public class GameManagement : MonoBehaviour {
    2.  
    3.     bool gameHasEnded = false;
    4.  
    5.     public float restartDelay = 1f;
    6.  
    7.     public GameObject completeLevelUI;
    8.  
    9.     public IntroloopAudio IntroloopAudio;
    10.  
    11.     void Awake()
    12.     {
    13.         Debug.Log("There are ");
    14.         Debug.Log("Count is " + LoadCounter.GameLoadedCounter);
    15.         //Debug.Log("StartCount is " + PlayerPrefs.GetInt("StartCount"));
    16.         if (LoadCounter.GameLoadedCounter == 0)
    17.         {
    18.             //IntroloopPlayer.FindObjectsOfType(this.IntroloopPlayer.Instance);
    19.             Debug.Log("Playing music, should be first time");
    20.             play(0);
    21.             //LoadCounter.GameLoadedCounter++;
    22.         }
    23.         LoadCounter.GameLoadedCounter++;
    24.         //PlayerPrefs.SetInt("StartCount", startCount);
    25.         Debug.Log("Counted up to " + LoadCounter.GameLoadedCounter);
    26.         //Destroy(this);
    27.     }
    28.  
    29.     public void play(int var)
    30.     {
    31.         IntroloopPlayer.Instance.Play(IntroloopAudio);
    32.     }
    33.  
    34.     public void CompleteLevel ()
    35.     {
    36.         Debug.Log(SceneManager.GetActiveScene().buildIndex);
    37.         Debug.Log("Out of: " + SceneManager.sceneCountInBuildSettings);
    38.         if ((SceneManager.GetActiveScene().buildIndex + 1) == SceneManager.sceneCountInBuildSettings -1)
    39.         {
    40.             //IntroloopPlayer.Instance.StopFade();
    41.             // play(1);
    42.             completeLevelUI.SetActive(true);
    43.         }
    44.         else
    45.         {
    46.             completeLevelUI.SetActive(true);
    47.         }
    48.     }
    49.  
    50.     public void EndGame()
    51.     {
    52.         if (gameHasEnded == false)
    53.         {
    54.             gameHasEnded = true;
    55.             Debug.Log("Game Over");
    56.             Invoke("Restart", restartDelay);
    57.         }
    58.  
    59.     }
    60.  
    61.     void Restart()
    62.     {
    63.         IntroloopPlayer.Instance.Pause();
    64.             SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    65.         IntroloopPlayer.Instance.Resume();
    66.     }
    67.  
    68. }
    Let me know your thoughts! I think this has been a good exercise in trying to flex on instantiation and perhaps encapsulation, but I figured you might see something that was under my nose.
     
  31. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    Hello @KOemxe,

    This is strange, because `IntroloopPlayer` gets `DontDestroyOnLoad` on its `Awake` (See IntroloopPlayer.cs). When the sound plays for the first time in your Hierarchy view did IntroloopPlayer game object resides in "DontDestroyOnLoad" Unity generated scene like this?

    Screenshot 2018-05-01 11.19.48.png

    Because everything in this scene won't be destroyed even with LoadSceneMode.Single, and then the next time you play sound it should be able to find this instance. (See IntroloopPlayer.cs > public static IntroloopPlayer Instance {... )

    Can you try going to the provided IntroloopDemo scene, then modify the code at `Awake()` adding :

    Code (CSharp):
    1. playButtons[0].onClick.Invoke();
    And then at `Update()` adds :

    Code (CSharp):
    1.         if(Input.GetKeyDown(KeyCode.P))
    2.         {
    3.             UnityEngine.SceneManagement.SceneManager.LoadScene("IntroloopDemo");
    4.         }
    So that the song plays immediately on scene load, then you can press P repeatedly to reload the same scene. Did `IntroloopPlayer` game object multiplies itself? In my case it doesn't, so from here you might be able to track down the problem by comparing the difference of this demo scene from your game.

    I will try to think of other ways that cause this problem.
     
    Last edited: May 1, 2018
  32. KOemxe

    KOemxe

    Joined:
    May 1, 2018
    Posts:
    22
    Hi @5argon , maybe I didn't look hard enough but... link to the demo project so I can test this?

    It DOES seem that the "DontDestroyOnLoad" only occurs after the first restart...
     
    Last edited: May 2, 2018
  33. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    The demo project is a scene in a `Demo` folder. It is provided along with other plugin's script. It is at "Introloop/Demo/IntroloopDemo"

    If you double click that scene file and enter play mode, did the "DontDestroyOnLoad" occur immediately? (No restart)
     
  34. KOemxe

    KOemxe

    Joined:
    May 1, 2018
    Posts:
    22
    Hi 5argon,

    I can't find the Awake() method in any of your scripts in the demo scene. Is it Start() in this case?
     
  35. KOemxe

    KOemxe

    Joined:
    May 1, 2018
    Posts:
    22
    Is the problem that I'm calling the IntroLoop player from a destroyable object like my GameManagement class? I wouldn't mind zipping up the project so that you can look if you're interested.
     
  36. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    Sorry my bad, there is no Awake method. What I meant is you can try to define Awake and put some audio playing in there. When you enter the scene you should hear the song immediately, then try to press P to reload the scene. In my case `IntroloopPlayer` get DontDestroyOnLoad from the first time the scene was loaded.

    That would be the best way for me to help you! I can look at it as soon as you send me the project. (Please remove any sensitive information if you have)
     
  37. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    790
    Great news, after a long time finally Introloop v3.0 is coming soon, now in the testing phase against my own game.

    Screenshot 2018-05-03 16.32.07.png

    Highlight includes :

    - Multiple Introloop singleton playing at the same time by subclassing : You could have MyBGMPlayer.Get.PlayBattleTheme() + MyAmbientPlayer.Get.PlayWindy() instead of IntroloopPlayer.Instance.Play(battleTheme) without the wind. Each subclass could use its own template prefab so you can pre-connect things or route mixers before runtime.

    There is a new demo scene demonstrating this function. You can play 2 IntroloopAudio, one using `IntroloopPlayer.Instance` and an another using your subclass. Each one use its own template prefab in the Resources folder. (Match by class name)

    Screenshot 2018-05-03 17.04.59.png

    - Local Introloop : GetComponent<IntroloopAudio>() that you have attached somewhere in the scene and everything works. You can also .AddComponent<IntroloopAudio>() and the next frame it will be ready to play. Local Introloop does not automatically get `DontDestroyOnLoad` unlike the static-singleton `IntroloopPlayer.Instance` or the new `Subclass.Get`

    - Positional Introloop : The point of having local Introloop is you could have it positioned meaningfully. Imagine you have 10 bushes with its own seamlessly looping leaf sound. You can have Introloop in each bush and as you approach it will get louder. There are many additional methods to help you setup audio source spatial curve to an IntroloopPlayer.

    (Positional Introloop was inspired by an e-mail from one of my user. If you have any other use case which is not covered yet by Introloop please do not hesitate to e-mail me or post here!)

    A new demo scene demonstrating the positional function is also available.

    Screenshot 2018-05-03 16.37.43.png

    On a related note, Introloop is on sale right now as a part of Unity's annual May Madness Sale. (I highly recommend getting I2Localization and Odin Inspector too while you have the chance. They are so good I want to advertise it for free. Haha)
     
    Last edited: May 3, 2018