What you’ve described would definitely explain the behavior you’re observing.
The short answer is “no”.
The long answer is that it appears you may be confused about what exactly an EventReference is, what it “triggers”, etc., as well as the scope on which parameters exist. I suspect some of this confusion is caused by the code that actually plays an event being in NarratorController instead of directly in CollectKeys.
An EventInstance is an instance of an event you’ve authored in FMOD Studio that has been created by the FMOD System. it can be played, paused, stopped, have parameter values set on it, etc.
An EventReference, on the other hand, is a convenience class in the Unity plugin that essentially just stores the path and GUID of an event to make it easier for you to create instances of the event. You can view the entirety of the source code for it at ./Assets/Plugins/FMOD/src/EventReference.cs
.
It is not possible to set the parameters of an EventReference, because an EventReference has no parameters. It is possible to set parameters of an EventInstance. However, unless your parameter is “global”, it exists on a per-EventInstance basis, so setting the value of a parameter on one EventInstance will not affect another EventInstance.
No, it’s entirely possible to do both. From what I can tell from the thread you’ve linked, NarratorController would require a couple of tweaks to handle it. The simplest way to do this would be to have a member of NarratorController that represents the desired parameter value, and then make sure to set the parameter to it in NarratorController.PlayNow()
before calling _instance.start()
. For example:
using System.Collections;
using FMOD.Studio;
using FMODUnity;
using UnityEngine;
public enum SFXConcurrencyStrategy
{
Cancel,
Wait,
AbortCurrent,
PlayAnyway
}
public class NarratorController : MonoBehaviour
{
private EventInstance _instance;
private string _parameterLabel;
public bool IsPlaying
{
get
{
if (!_instance.isValid()) return false;
_instance.getPlaybackState(out PLAYBACK_STATE state);
return state == PLAYBACK_STATE.PLAYING || state == PLAYBACK_STATE.STARTING;
}
}
public void Play(EventReference eventReference,
SFXConcurrencyStrategy sfxConcurrencyStrategy = SFXConcurrencyStrategy.Cancel)
{
if (eventReference.IsNull)
{
return;
}
if (!IsPlaying)
{
PlayNow(eventReference);
}
else
{
switch (sfxConcurrencyStrategy)
{
case SFXConcurrencyStrategy.Cancel:
_instance.getDescription(out EventDescription eventDescription);
eventDescription.getPath(out string currentEventPath);
Debug.LogWarning(
$"Will not play narrator comment {eventReference}, because {currentEventPath} is already playing");
break;
case SFXConcurrencyStrategy.Wait:
StartCoroutine(PlayAfterCurrent(eventReference));
break;
case SFXConcurrencyStrategy.AbortCurrent:
_instance.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
PlayNow(eventReference);
break;
case SFXConcurrencyStrategy.PlayAnyway:
PlayNow(eventReference);
break;
}
}
}
private void PlayNow(EventReference eventReference)
{
_instance = RuntimeManager.CreateInstance(eventReference);
_instance.setParameterByNameWithLabel("RandomDialogue", _parameterLabel);
_instance.start();
_instance.release();
}
private IEnumerator PlayAfterCurrent(EventReference eventReference)
{
while (enabled)
{
_instance.getPlaybackState(out PLAYBACK_STATE state);
if (state == PLAYBACK_STATE.PLAYING || state == PLAYBACK_STATE.STARTING) yield return null;
else break;
}
PlayNow(eventReference);
}
public void SetParameter(string label){
_parameterLabel = label;
}
}
You can then call narratorController.SetParameter()
in CollectKeys.CollectedDialogueDelay()
before narratorController.Play(collectedDialogue, SFXConcurrencyStrategy.Wait)
.
This does assume that you’re only playing one specific event and setting one parameter with NarratorController, but it should serve as a good example of what you might want to do.