Hello, this may be a silly question, as it flips the point of FMOD, but here goes.
Let’s say I have some music with two loops, loop A and loop B, and a unity event X toggles the parameter which makes loop A keep looping, meaning that once loop A is finished, loop B is started.
How can I make a unity event happen when loop B starts? As the X trigger event can happen anytime, timing the second event based on X won’t work. FMOD has to be the second event caller.
If there is no direct way for FMOD to trigger a unity event on loop start, is there some way to check the playback position of the music in unity?
Put the marker at the start of loop B and then invoke a UnityEvent from the callback.
Another simpler way could be to use a global FMOD parameter that is changed from 0 to 1 using an FMOD Command instrument when loop B starts, and at the Unity end you have a coroutine running something like this:
private bool TryGetGlobalParam(string paramName, out float value)
{
var result = FMODUnity.RuntimeManager.StudioSystem.getParameterByName(paramName, out value);
if (result != FMOD.RESULT.OK)
Debug.LogWarning($"Failed to get parameter {paramName}, result: {result}");
return result == FMOD.RESULT.OK;
}
private IEnumerator WaitUntilParamChange()
{
wwhile (TryGetGlobalParam("Parameter", out float value) && value == 0) yield return null;
LoopBStartedEvent.Invoke();
}
Yep: eventInstance.getTimelinePosition(out int currentPositionMs);
I have went for the second option (only slightly tweaking) and everything is working fine code wise. Unfortunately I cannot for the life of me get the global parameter to be changed. The instrument changes its value to 1 in FMOD (the yellow dot goes to the top right corner), but it does not do so in unity.
I’ll continue trying to solve this when I get the time, until then I am pretty lost.
And for any future readers, if the code doesn’t work, turn the “wwhile” at line 11 to “while”, and if the Invoke() method at line 12 is causing issues like it did for me, you can just call LoopBStartedEvent() directly instead.
Glad it was helpful. Thanks for spotting the errors in my sloppy code! The below code works (at least for me) if you need a UnityEvent specifically to fire on a param change:
using System.Collections;
using UnityEngine;
using UnityEngine.Events;
public class Test :MonoBehaviour
{
public UnityEvent LoopBStartedEvent;
void Start()
{
StartCoroutine(WaitUntilParamChange());
}
private bool TryGetGlobalParam(string paramName, out float value)
{
var result = FMODUnity.RuntimeManager.StudioSystem.getParameterByName(paramName, out float _,out value);
if (result != FMOD.RESULT.OK)
Debug.LogWarning($"Failed to get parameter {paramName}, result: {result}");
return result == FMOD.RESULT.OK;
}
private IEnumerator WaitUntilParamChange()
{
while (TryGetGlobalParam("Parameter", out float value) && value == 0) yield return null;
LoopBStartedEvent.Invoke();
}
}