Search Unity

Koreographer - Audio Driven Events, Animation, and Gameplay

Discussion in 'Assets and Asset Store' started by SonicBloomEric, Sep 15, 2015.

  1. cosic196

    cosic196

    Joined:
    Mar 15, 2018
    Posts:
    6
    Hi Eric, can you please help me?

    I'm trying to procedurally add Koreography Tracks during runtime.
    Here's the test code I'm using and it seems to work only if the Koreography Editor window is open when I press the play button. Otherwise I'm getting a NullReferenceException.

    Code (CSharp):
    1. [RequireComponent(typeof(Koreographer))]
    2. [RequireComponent(typeof(SimpleMusicPlayer))]
    3. public class LevelManager : MonoBehaviour
    4. {
    5.     private Koreographer _koreographer;
    6.     private SimpleMusicPlayer _simpleMusicPlayer;
    7.  
    8.     private void Awake()
    9.     {
    10.         _koreographer = GetComponent<Koreographer>();
    11.         _simpleMusicPlayer = GetComponent<SimpleMusicPlayer>();
    12.         var koreoTrack = ScriptableObject.CreateInstance<KoreographyTrack>();
    13.         KoreographyEvent koreographyEvent = new KoreographyEvent();
    14.         koreographyEvent.StartSample = 0;
    15.         koreographyEvent.EndSample = 0;
    16.         koreoTrack.EventID = "test";
    17.         koreoTrack.AddEvent(koreographyEvent);
    18.         _koreographer.GetKoreographyAtIndex(0).AddTrack(koreoTrack);
    19.         _koreographer.RegisterForEvents("test", OnTestEvent);
    20.         _simpleMusicPlayer.Play();
    21.     }
    22.  
    23.     private void OnTestEvent(KoreographyEvent koreoEvent)
    24.     {
    25.         Debug.Log("WOW");
    26.     }
    27. }
     
  2. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,085
    When reporting exceptions like this, it is always helpful to provide the full report from the console. That will help anyone who sees it better understand what reference was unexpectedly null. As it stands right now, I have to guess.

    And my guess is that you do not have any Koreography loaded when the Koreography Editor window isn't open. Do you have any Koreography loaded in the "Loaded Koreography" field of the Koreographer component? Do you have a Koreography asset specified in your Simple Music Player component?

    Can you provide a screenshot of the NullReferenceException report in your console or otherwise copy the report contents into a message here?

    Also, what happens if you change "Awake()" to "Start()"?
     
  3. cosic196

    cosic196

    Joined:
    Mar 15, 2018
    Posts:
    6
    upload_2020-12-7_17-53-11.png

    Here's a screenshot. I have loaded a Koreography into the Koreographer and into the Simple Music Player.

    Here's the full report from the console if it's hard to read from the screenshot:

    Code (CSharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    2. SonicBloom.Koreo.Koreography.GetTrackByID (System.String eventID) (at <960e9d4d172b4dcf851c77f9dee55996>:0)
    3. SonicBloom.Koreo.Koreography.DoesTrackWithEventIDExist (System.String eventID) (at <960e9d4d172b4dcf851c77f9dee55996>:0)
    4. SonicBloom.Koreo.Koreography.CanAddTrack (SonicBloom.Koreo.KoreographyTrackBase track) (at <960e9d4d172b4dcf851c77f9dee55996>:0)
    5. SonicBloom.Koreo.Koreography.AddTrack (SonicBloom.Koreo.KoreographyTrackBase track) (at <960e9d4d172b4dcf851c77f9dee55996>:0)
    6. LevelManager.Start () (at Assets/Scripts/Level/LevelManager.cs:24)
    I've tried changing Awake to Start, but still get the same error message.

    Btw. I'm using Unity version 2019.4.15f1 and the Koreographer 1.6.1.
    Another thing to note is that I can't open any Koreographer Editor window to get rid of the error, but the editor window which pops up when I click on the edit button in the Simple Music Player/Koreographer component which has the Koreography I'm trying to use. That's the only way to avoid the exception.
     
    Last edited: Dec 7, 2020
  4. cosic196

    cosic196

    Joined:
    Mar 15, 2018
    Posts:
    6
    Also I've modified the code when sending you the question to remove some unnecessary unused parts, but here's the original file if you're trying to find out what's happening at line 24:

    Code (CSharp):
    1. using GameEventBus;
    2. using SonicBloom.Koreo;
    3. using SonicBloom.Koreo.Players;
    4. using UnityEngine;
    5.  
    6. [RequireComponent(typeof(Koreographer))]
    7. [RequireComponent(typeof(SimpleMusicPlayer))]
    8. public class LevelManager : MonoBehaviour
    9. {
    10.     public static EventBus eventBus;
    11.     private Koreographer _koreographer;
    12.     private SimpleMusicPlayer _simpleMusicPlayer;
    13.  
    14.     private void Start()
    15.     {
    16.         _koreographer = GetComponent<Koreographer>();
    17.         _simpleMusicPlayer = GetComponent<SimpleMusicPlayer>();
    18.         var koreoTrack = ScriptableObject.CreateInstance<KoreographyTrack>();
    19.         KoreographyEvent koreographyEvent = new KoreographyEvent();
    20.         koreographyEvent.StartSample = 0;
    21.         koreographyEvent.EndSample = 0;
    22.         koreoTrack.EventID = "test";
    23.         koreoTrack.AddEvent(koreographyEvent);
    24.         _koreographer.GetKoreographyAtIndex(0).AddTrack(koreoTrack);
    25.         _koreographer.RegisterForEvents("test", OnTestEvent);
    26.         _simpleMusicPlayer.Play();
    27.     }
    28.  
    29.     private void OnTestEvent(KoreographyEvent koreoEvent)
    30.     {
    31.         Debug.Log("WOW");
    32.     }
    33.  
    34.     public void StartTheLevel()
    35.     {
    36.        
    37.     }
    38. }
     
  5. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,085
    Did you see my previous post?

    I see that you changed "Awake()" to "Start()". Did that help things at all?

    What is the exact error that you are receiving in the Console?
     
  6. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,085
    If anyone is reading through this conversation, it seems that @cosic196's post got held up in moderation and didn't arrive. The conversation shifted outside of this forum thread briefly as the post was stuck in limbo for a bit...

    The current theory is that @cosic196 is using a Koreography asset but applying an ephemeral (read: not backed by an asset) instance of a KoreographyTrack. When the Editor leaves PlayMode, the underlying C++ instance is destroyed and the C# instance is set to null. This leaves an empty entry inside the Koreography asset's internal tracks list, which, upon re-entry into PlayMode, breaks during an internal validation step. Loading the Koreography asset in the Koreography Editor and keeping it open ensures that the ephemeral KoreographyTrack doesn't get cleaned up because the Koreography (and all of its references) is "serialized" (though not into an asset stored on disk) between PlayMode phases. Once in this state, calls to "AddTrack" in the provided code will return false. However, the track registration will work as it did before because the track already exists (simply from a previous run).

    There are several workarounds to this, but the main two would be:
    1. Create a new (ephemeral) runtime Koreography asset and copy necessary settings (Tempo Sections, AudioClip, Sample Rate) from a "model" Koreography asset.
    2. Be sure to Remove the ephemeral KoreographyTrack asset from the Koreography asset when leaving PlayMode.
    Either of those should be sufficient.
     
  7. cosic196

    cosic196

    Joined:
    Mar 15, 2018
    Posts:
    6
    Thanks for the help!

    Just wanted to let you know that I've tried your suggestion and it works flawlessly. I went with copying settings from an existing Koreography into a new ephemeral Koreography asset and adding KoreographyTracks to it.
    Here's the code for anyone interested:

    Code (CSharp):
    1. using SonicBloom.Koreo;
    2. using SonicBloom.Koreo.Players;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. [RequireComponent(typeof(SimpleMusicPlayer))]
    7. [RequireComponent(typeof(Koreographer))]
    8. public class KoreographyGeneration : MonoBehaviour
    9. {
    10.     [SerializeField]
    11.     private Koreography _koreographyToCopy;
    12.     private Koreography _koreography;
    13.     private Koreographer _koreographer;
    14.     private SimpleMusicPlayer _simpleMusicPlayer;
    15.  
    16.     void Start()
    17.     {
    18.         _koreographer = GetComponent<Koreographer>();
    19.         _simpleMusicPlayer = GetComponent<SimpleMusicPlayer>();
    20.  
    21.         //Copying from given koreography
    22.         _koreography = ScriptableObject.CreateInstance<Koreography>();
    23.         _koreography.SampleRate = _koreographyToCopy.SampleRate;
    24.         _koreography.SourceClip = _koreographyToCopy.SourceClip;
    25.         List<TempoSectionDef> tempoSectionsToCopy = new List<TempoSectionDef>();
    26.         for (int i = 0; i < _koreographyToCopy.GetNumTempoSections(); i++)
    27.         {
    28.             tempoSectionsToCopy.Add(_koreographyToCopy.GetTempoSectionAtIndex(i));
    29.         }
    30.         _koreography.OverwriteTempoSections(tempoSectionsToCopy);
    31.  
    32.         //Creating and inserting a new koreography track
    33.         var koreoTrack = ScriptableObject.CreateInstance<KoreographyTrack>();
    34.         KoreographyEvent koreographyEvent = new KoreographyEvent();
    35.         koreographyEvent.StartSample = 0;
    36.         koreographyEvent.EndSample = koreographyEvent.StartSample;
    37.         koreoTrack.EventID = "test";
    38.         koreoTrack.AddEvent(koreographyEvent);
    39.         _koreography.AddTrack(koreoTrack);
    40.  
    41.         _koreographer.LoadKoreography(_koreography);
    42.         _koreographer.RegisterForEvents("test", OnTestEvent);
    43.         _simpleMusicPlayer.LoadSong(_koreography, 0, false);
    44.         _simpleMusicPlayer.Play();
    45.     }
    46.  
    47.     private void OnTestEvent(KoreographyEvent koreoEvent)
    48.     {
    49.         Debug.Log("WOW");
    50.     }
    51. }
     
    Last edited: Dec 13, 2020
    SonicBloomEric likes this.
  8. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,085
    We have created a Discord server to host discussions pertaining to Koreographer! To participate, please follow the server invite link here.
     
    Last edited: Jan 19, 2021
  9. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,085
    Good news, everyone! With a little help from some friends we were able to bring FMOD Studio support to Koreographer Professional Edition! The integration package works with FMOD for Unity 2.0 and up. As with the Wwise integration, the FMOD Studio integration is not included in the Koreographer Professional Edition package by default. Instead, it is available upon request. Happy developing!
     
    rrahim and Inspeinre like this.
  10. Seginus

    Seginus

    Joined:
    Feb 1, 2018
    Posts:
    18
    Is it possible to attach Koreography events to music streaming from a server?
     
  11. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,085
    Yes, provided you have playback position information and appropriate Koreography for the streamed track. It is no different from playing locally. This is especially the case if the audio is played through a Unity AudioSource component as then you should be able to use the built-in components to drive Koreography Event triggering.

    If audio playback occurs through some custom audio system (bypassing Unity's AudioSource system or a third party one like FMOD or Wwise) then you would have to provide your own "Audio Visor". There is documentation for how to do this in the code and we are available to help. However, this is generally considered to be a complex undertaking and requires lots of scripting to get right. Not for the faint of heart.
     
  12. Largehare

    Largehare

    Joined:
    Nov 7, 2021
    Posts:
    3
    Hi Eric, There is a problem confusing me a lot.
    upload_2021-11-28_11-46-12.png
    I want to create a tone which can light up gradually and it will be brightest when getting to the endsample of a event. the tone will be destroied when colliding with character's hand.
    upload_2021-11-28_11-25-31.png
    So i instantiate tones in the MainController like this.
    Code (CSharp):
    1. void Start()
    2.     {
    3.         seq = 0;
    4.         isStart = true;
    5.         Koreographer.Instance.RegisterForEventsWithTime(eventID, Generate);
    6.     }
    7.  
    8.     // Update is called once per frame
    9.     void Update()
    10.     {
    11.        
    12.     }
    13.     public void Generate(KoreographyEvent koreographyEvent, int sampleTime, int sampleDelta, DeltaSlice deltaSlice)
    14.     {
    15.         if (isStart)
    16.         {
    17.            
    18.             isStart = false;
    19.             Vector3 pos = RandomPos();
    20.             toneObject = Instantiate(tone, pos, Quaternion.identity);
    21.             AudioSource audioSr = toneObject.GetComponent<AudioSource>();
    22.             audioSr.clip = clips[seq];
    23.             seq += 1;
    24.         }
    25.         if (sampleTime > koreographyEvent.EndSample)
    26.         {
    27.             isStart = true;
    28.         }
    and set its brightness in ToneLighting Script which is in tone object
    upload_2021-11-28_11-34-56.png
    I register another event in the script (both events' ID are same).
    Code (CSharp):
    1. void Start()
    2.     {
    3.         if(gameObject != null){
    4.             Koreographer.Instance.RegisterForEventsWithTime(eventID, SetIntensity);
    5.         }
    6.        
    7.         _renderer = GetComponent<Renderer>();
    8.         _material = _renderer.material;
    9.  
    10.     }
    11.  
    12.     // Update is called once per frame
    13.     void Update()
    14.     {
    15.  
    16.     }
    17.     void SetIntensity(KoreographyEvent koreographyEvent, int sampleTime, int sampleDelta, DeltaSlice deltaSlice)
    18.     {
    19.         if (koreographyEvent.HasCurvePayload())
    20.         {
    21.             if (!isLighted)
    22.             {
    23.                 float intensity = Mathf.Lerp(0, 1.5f, koreographyEvent.GetValueOfCurveAtTime(sampleTime));
    24.                 _material.SetVector("_EmissionColor", new Vector4(0.421f, 0.337f, 0.086f) * intensity);
    25.                 currentEvent = koreographyEvent;
    26.             }
    27.  
    28.         }
    29.  
    30.         if (currentEvent == null || sampleTime > currentEvent.EndSample)
    31.         {
    32.             isLighted = true;
    33.             if (isLightDown)
    34.             {
    35.                 StartCoroutine(LightDown());
    36.                 isLightDown = false;
    37.                
    38.             }
    39.         }
    the first tone works well, but it will occurs MissingReferenceException when following tones are destroied
    upload_2021-11-28_11-43-42.png
    I think it is that two events is registered in different object cause this issue but i don't know how to fix it.
    Thank you for your answers!
     
  13. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,085
    You need to add this to your ToneLighting script:
    Code (CSharp):
    1. void OnDestroy()
    2. {
    3.     Koreographer.Instance.UnregisterForEvents(eventID, SetIntensity);
    4. }
    Because you are destroying the object, you need to tell Koreographer not to trigger the callbacks.

    Additionally, you can get rid of the isStart variable and simply check:
    Code (CSharp):
    1. if (sampleTime - sampleDelta <= koreographyEvent.StartSample)
    2. {
    3.     // Spawn the ToneObject...
    4. }
    Hope this helps!
     
  14. Largehare

    Largehare

    Joined:
    Nov 7, 2021
    Posts:
    3
    it works! thank you very much!
     
    SonicBloomEric likes this.
  15. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,085
    Hey Everyone! We just released version 1.6.2 of Koreographer and Koreographer Professional Edition to the Unity Asset Store! Here's a rundown of changes:
    • [NEW] Koreographer now detects when the sample rate of the audio used during Koreography Event generation differs from the audio's sample rate in a build and accounts for it automatically.
    • [PRO] The Master Audio integration's visors now support setting a target Koreographer component with which to interface.
    • [PRO] The SECTR Audio integration's visor now supports setting a target Koreographer component with which to interface.
    • [PRO] Improve the logic to detect audio looping in the Fabric integration.
    • [PRO] Fix the Master Audio integration's PlaylistControllerSuperVisor component to properly unregister as the Koreographer instance's Music Playback Controller in OnDisable(). This also fixes a console error.
    • [PRO] Fix GradientPayload not updating as expected in the Koreography Editor.
    • [PRO] Fix the MIDI Converter forgetting the "recently used" path to a selected MIDI file.
    • [PRO] Fix deprecated API usage in the FFT Analysis panel on Unity 2021.2+.
    • Improve the operation of the AudioVisor.ResyncTimings() functionality.
    • Fix Undo not working as expected after moving events.
    • Fix Koreography Editor forgetting the "recently used" asset path on Windows.
    • Fix unhandled exception in Koreography Editor when attempting to render the waveform for an AudioClip with incompatible Load Type.
    If you purchased a previous version of Koreographer and Koreographer Professional Edition, then v1.6.1 is a free upgrade! :D
     
  16. kobebryant

    kobebryant

    Joined:
    Feb 20, 2023
    Posts:
    6
    Hello, I use GetLatestSampleTime() or Koreographer.Instance.GetMusicSampleTime() to get current music sampleTime, They work fine in the editor and android, but on webgl, the sampling time acquired is distorted, and the sampling time value decreases as the music plays, It's a big jump, like that , The last time was 397870, The next sample becomes 970 , 45070 , How to accurately obtain the current music playback sampling time?
     

    Attached Files:

  17. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,085
    In the image that you provided, the numbers do indeed jump back to 970 but they continue to increase after that - as though the audio had looped. Is that not happening? What's more, most of the provided numbers are repeated. Are these values the sample positions of target events?

    Regardless, Unity has had broken audio APIs for WebGL builds in the past and it would not surprise me to learn that this has happened again. What version of Unity are you using to produce your builds? What version of Koreographer do you have installed? Which browser and what browser version are you testing your build in?
     
  18. kobebryant

    kobebryant

    Joined:
    Feb 20, 2023
    Posts:
    6
    I get the current sampling time in the Update using GetLatestSampleTime or GetMusicSampleTime
    The music continues as normal,But the sampling time jumps back,The current sampling time taken suddenly gets smaller and jumps around a lot, and I need to make sure that the sampling time is accurate to generate object drops.

    My development environment is
    Koreographer Professional Edition 1.6.0
    Unity 2021.2.18 , WebGL Target platform, WebGL 1
    Export WbGL into small games and use it in wechat,I used a third-party wechat sdk,
    I'm going to verify that this type of problem occurs when exporting webgl directly,
    I also found in the above post that using GetLatestSampleTime will cause the problem of time backtracking, is there a good solution?
     
  19. kobebryant

    kobebryant

    Joined:
    Feb 20, 2023
    Posts:
    6
    After the test, it is normal to obtain the current sampling time value by exporting webgl on Google and Internet Explorer without wechat plug-in. However, the value obtained by adding wechat plug-in to export is correct only in the first few seconds, and later it will be confused. However, I developed a wechat small game, and I have contacted the technical staff of wechat to describe the relevant problems. So how do I solve this problem? Is there any alternative method within koreographer that can get the current sampling time?
     

    Attached Files:

  20. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,085
    @kobebryant We do not have any specific experience with the WeChat so it is difficult for us to say what is going on here. That said, I have a hunch that this may be due to platform sample rate differences. Versions of Koreographer prior to 1.6.2 required that you make certain adjustments to either the audio or the Koreography to ensure that events would trigger correctly. Version 1.6.2 handles this automatically internally.

    We would suggest that you try/do the following:
    • Update your Koreographer installation to v1.6.2. This should be pretty trivial to do by updating the package in the Package Manager and then installing over your current installation. You shouldn't have to change anything to get the enhancement.
    • Update your version of Unity to 2021.3.x. Unity 2021.2 releases are TECH releases and are unsupported by both Unity and us. While there shouldn't be any issues with that version of Unity, we do not guarantee operation as we rely on Unity's ability to fix platform-level issues that may crop up and they have stated that they do not support TECH releases once an LTS is out (in this case, this would be 2021.3).
    Please give those two updates a try and let us know if they resolve the issue for you!
     
  21. kobebryant

    kobebryant

    Joined:
    Feb 20, 2023
    Posts:
    6
    Great, I use Untiy 2021.3.x. Koreographer 1.6.2, it doesn't have the problem of sampling time confusion anymore, thank you very much for your prompt reply.
     
    SonicBloomEric likes this.
  22. kobebryant

    kobebryant

    Joined:
    Feb 20, 2023
    Posts:
    6
    I cut out my game to the background while the music is playing, pause by calling SimpleMusicPlayer.Pause(), pause the game using Time.Timescale, and then cut back to the game, Call Time.timeScale = 1, then simpleMusicPlayer.Play(); I found that the music starts playing again, but the events on the track are not called again, so the rhythm is not matched. It seems that the events on the track go back normally, but the music starts from the beginning. This problem does not appear in the Unity Editor, is there a solution?

    My development environment is
    Koreographer Professional Edition 1.6.2
    Unity 2021.3.15 , WebGL Target platform, WebGL 1
     
  23. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,085
    This sounds like a bug in Unity's WebGL AudioSource implementation. In case you weren't already aware, the WebGL audio interface is different from just about every other platform.

    If I understand you correctly, your code looks something like this:
    Code (CSharp):
    1. player.Pause();
    2.  
    3. // Time passes...
    4.  
    5. player.Play();
    Under the hood the SimpleMusicPlayer is simply forwarding those Pause/Play calls to its internal AudioSource. This means it amounts to:
    Code (CSharp):
    1. audioSource.Pause();
    2.  
    3. // Time passes...
    4.  
    5. audioSource.Play();
    If this simple logic causes the music to start over on the call to Play() then that is a bug in Unity's code - especially given that it sounds as though Koreographer's events continue as normal. From your report, it sounds as though the Koreography picks up right where it left off and doesn't restart. If that's the case then the AudioSource time APIs (see: AudioSource.timeSamples or AudioSource.time) are likely reporting time as though the audio hadn't reset. (If this isn't the case and the Koreography jumps back along with the audio then at least there's internal consistency in Unity's AudioSource implementation...)

    So. The first thing I would suggest is to update your version of Unity. You're currently on 2021.3.15. This item appears in the Release Notes for Unity 2021.3.17:
    Seems pretty promising, no? There are other audio related fixes between your version and the current latest build (at time of writing this is 2021.3.22). There's a good chance that this may have already been resolved by Unity.

    If updating Unity doesn't resolve the issue, then I would highly recommend the following steps:
    1. Verify that this issue occurs across browsers. If you're seeing this in a Chromium-based browser (Chrome/Edge/Brave/etc.), then also check Safari or Firefox (or vice versa).
    2. Try to create a simple test example that removes Koreographer entirely and relies solely on AudioSource Play/Pause APIs. If this doesn't cause the issue, then insert the time control logic for pausing that you used and see if that reproduces the issue.
    3. If you are able to reproduce the issue, file a bug with Unity using the Editor's Bug Reporter and provide the small example project you used to verify the issue.
    While that bug is handled by Unity's QA team, then, you might try to work around it with the following logic:
    Code (CSharp):
    1. player.Pause();
    2. int pausedSample = player.GetSampleTimeForClip(player. GetCurrentClipName());
    3.  
    4. // Time passes...
    5.  
    6. player.SeekToSample(pausedSample);
    7. player.Play();
    That might trigger the AudioSource to properly update its timing position internally before resuming playback.

    Please try updating first, though, and let us all know how it goes!
     
  24. kobebryant

    kobebryant

    Joined:
    Feb 20, 2023
    Posts:
    6
    yes, This is a bug in Unity, This problem still exists in Unity 2021.3.17, If I switch to background while music is playing, I will rule it a failure, Your help was very much appreciated.
     
    SonicBloomEric likes this.
  25. bgdstudios99

    bgdstudios99

    Joined:
    May 2, 2023
    Posts:
    1
    I have a real simple problem. I just want to change speed of an object depending on where the payload curve lands on.
    For example, at this Part of the song, detect the curve payload and then change speed to 5. else, if the curve payload ends then change it back to the default speed.

    My code looks right, but once it goes back to the default speed it doesnt pick up the next curve payload. Any clue why?

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using SonicBloom.Koreo;
    6.  
    7. public class PipeBehavior : MonoBehaviour {
    8.  
    9.     [EventID]
    10.     public string eventID;
    11.     public float pipeSpeed; //Speed declaration
    12.    
    13.     void Awake()
    14.     {
    15.      
    16.     }
    17.  
    18.  
    19.     // Update is called once per frame
    20.     void Update()
    21.     {
    22.         Koreographer.Instance.RegisterForEventsWithTime(eventID, OnMusicalTrigger);
    23.  
    24.         if (!GameData.gameOver)
    25.         {
    26.             transform.Translate(new Vector2(-pipeSpeed * Time.deltaTime, 0)); //Moves the pipe to the left with the speed of 'pipeSpeed' and normalized with Time.deltaTime
    27.         }
    28.     }
    29.  
    30.     void OnMusicalTrigger(KoreographyEvent evt, int sampleTime, int SampleDelta, DeltaSlice deltaSlice)
    31.     {
    32.         if (evt.HasCurvePayload())
    33.         {
    34.             pipeSpeed = 5;
    35.  
    36.         }
    37.  
    38.         else
    39.         {
    40.             pipeSpeed = 2;
    41.         }
    42.     }
    43. }
     
  26. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,085
    Not sure why it wouldn't notice the next event with a Curve Payload... unless all of your events have Curve Payloads on them?

    Regardless, the registration should not be done within the Update() call, but rather Start(). I adjusted the code as follows:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using SonicBloom.Koreo;
    5.  
    6. public class PipeBehavior : MonoBehaviour
    7. {
    8.     [EventID]
    9.     public string eventID;
    10.     public float pipeSpeed; //Speed declaration
    11.  
    12.     void Start()
    13.     {
    14.         Koreographer.Instance.RegisterForEventsWithTime(eventID, OnMusicalTrigger);
    15.     }
    16.  
    17.     void Update()
    18.     {
    19.         if (!GameData.gameOver)
    20.         {
    21.             transform.Translate(new Vector2(-pipeSpeed * Time.deltaTime, 0)); //Moves the pipe to the left with the speed of 'pipeSpeed' and normalized with Time.deltaTime
    22.         }
    23.     }
    24.  
    25.     void OnMusicalTrigger(KoreographyEvent evt, int sampleTime, int SampleDelta, DeltaSlice deltaSlice)
    26.     {
    27.         if (evt.HasCurvePayload())
    28.         {
    29.             pipeSpeed = 5;
    30.         }
    31.         else
    32.         {
    33.             pipeSpeed = 2;
    34.         }
    35.     }
    36. }
     
  27. Dobalina

    Dobalina

    Joined:
    Sep 6, 2013
    Posts:
    105
    Hello. I'm interested in making a beat tapping game using Koreographer + Playmaker, much like a guitar hero. I've gone through my track with events for the beats. Next I'll add a button for the player to tap in timing with the beat. I'm curious of the best way to handle taps that come too early or late. I assume one method could involve checking how much time has elapsed from the last beat and see if your tap was within range of the event, but that would only work on late taps, not early taps. So I don't know the best way to do this in playmaker.
     
  28. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,085
    One way to do this with the PlayMaker integration is to create two separate Koreography Tracks where you effectively move all events by a fixed amount in each direction. This would allow you to define an event "window" where the "earlier'"events would trigger the beginning of a "hit window" and the "later" events would trigger the closing of said window. When input happens you would check if a relevant event window was open or not (you would need to track opened events when the "earlier" trigger happened and then clear them when the "later" trigger happened).

    You might even have a third "source" or "original" or "perfect" Track that has perfectly aligned events. This isn't an issue if your offsets from the original "perfect" event locations are hardcoded values.
     
    Dobalina likes this.
  29. dyguests

    dyguests

    Joined:
    May 4, 2015
    Posts:
    16
    Hello, I have roughly gone through the documentation for Koreographer downloaded from the Unity Asset Store but haven't found the functionality I'm looking for.

    I would like to inquire about how to achieve the following:

    1. While playing in the Koreographer Editor, I can add Events by pressing the 'E' key. However, in OneOff mode with Snap To Beat enabled, it adds Events for every vertical line passed when I press the key. I would like to add the Event only on the first press. How can I achieve this?

    2. I want to add different TextPayloads (or other Payloads) by pressing different keys. Is there a way to do this?
    I am not sure if the complete documentation contains solutions, as I haven't seen the full documentation yet.
     
  30. dyguests

    dyguests

    Joined:
    May 4, 2015
    Posts:
    16
    Currently, there is a temporary workaround for the first issue: using the Span mode and then using a script to set mEndSample to match mStartSample.

    Code (CSharp):
    1.             // snap
    2.             var events = track.GetAllEvents();
    3.             track.RemoveAllEvents();
    4.             events.ForEach(@event =>
    5.             {
    6.                 if (@event.EndSample == @event.StartSample) return;
    7.  
    8.                 changed = true;
    9.                 @event.EndSample = @event.StartSample;
    10.                 track.AddEvent(@event);
    11.             });
     
    Last edited: Jan 24, 2024
  31. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,085
    This is not a supported operation. You would need to modify the source code (available upon request to Professional Edition customers) to achieve the experience that you are looking for directly in the editor. The workaround script that you wrote would be the other. That said, I do not see why you would remove all the events and then re-add them when you could just modify the events by reference directly:
    Code (CSharp):
    1. // snap
    2. var events = track.GetAllEvents();
    3. events.ForEach(@event =>
    4. {
    5.     if (@event.EndSample != @event.StartSample) changed = true;
    6.  
    7.     @event.EndSample = @event.StartSample;
    8. });
    This type of functionality is not provided by the Koreography Editor out of the box. Some Professional Edition customers have made this type of customization by modifying the source code to add custom mappings that are tailored to their specific games' designs.

    I hope this helps!
     
    dyguests likes this.