Getting Event Emitter ParamID in Awake

Hello,

We have to use event emitters for our footstep system and I’m just checking there’s a way to get an event emitters parameter ID once instead of getting it every time it’s played, before we were creating instances inside the script and getting the ID once which was fine but with the emitter the cached ID isn’t setting the parameter every time. I can set it by name fine but in the interest of performance I’d like to set by ID.

I’m grabbing the ID’s like this in Awake

m_LeftFootSurfaceParamID = FMODUtility.GetLocalParameterID(m_LeftFootstepEmitter.EventInstance, "SurfaceType");
m_RightFootSurfaceParamID = FMODUtility.GetLocalParameterID(m_RightFootstepEmitter.EventInstance, "SurfaceType");

Here’s the utility function

public static PARAMETER_ID GetLocalParameterID(EventInstance eventInstance, string parameterName) {
    eventInstance.getDescription(out EventDescription description);
    description.getParameterDescriptionByName(parameterName, out PARAMETER_DESCRIPTION parameterDescription);
    return parameterDescription.id;
}

And here we’re trying to set the parameter when a footstep event plays

void PlayFootstepSound(int footIndex) {

    ObjectSurfaceType surfaceType = ObjectSurfaceType.None;
    if (Physics.Raycast(transform.position + m_RaycastOffset, Vector3.down, out RaycastHit hitInfo)) {
        surfaceType = hitInfo.GetSurfaceType();
    }

    switch (footIndex) {
        case 0:
            m_LeftFootstepEmitter.Play();
            m_LeftFootstepEmitter.SetParameter(m_LeftFootSurfaceParamID, (int)surfaceType);
            break;
        case 1:
            m_RightFootstepEmitter.Play();
            m_RightFootstepEmitter.SetParameter(m_RightFootSurfaceParamID, (int)surfaceType);
            break;
    }
}

I should also add we’re adding the event emitters in awake too

m_LeftFootstepEmitter = m_Animator.GetBoneTransform(HumanBodyBones.LeftFoot).gameObject.AddComponent<StudioEventEmitter>();
m_RightFootstepEmitter = m_Animator.GetBoneTransform(HumanBodyBones.RightFoot).gameObject.AddComponent<StudioEventEmitter>();

m_LeftFootstepEmitter.EventReference = RuntimeManager.PathToEventReference("event:/Character/Footstep");
m_RightFootstepEmitter.EventReference = RuntimeManager.PathToEventReference("event:/Character/Footstep");

Is there no way to initialise the instance straight away OnEnable or similar so I can grab any event information?

Also I’d have thought we should set the parameter before playing but in testing by name it was only working afterwards.

Thanks for your time

Hi,

Can I get your exact Unity and FMOD for Unity version numbers?

Also, to clarify, when you say “I can set it by name fine but in the interest of performance I’d like to set by ID”, do you mean that the code snippets you posted work as expected when a parameter name is used instead of an ID? Or is the issue that setting a parameter on an event emitter in the manner you’re trying doesn’t work at all?

Hi Leah,

Unity - 6.0.20f1
FMOD for Unity - 2.02.22

Yes so I can call SetParameter(string name) etc fine without using a parameterID but obviously I want to use IDs as it’s faster.

So at the moment I’m now using a new overload for the GetLocalParameter method which uses the event reference as opposed to the EventInstance which let’s me grab the PARAMETERID in awake.

public static PARAMETER_ID GetLocalParameterID(EventReference eventReference, string parameterName) {
    EventDescription description = RuntimeManager.GetEventDescription(eventReference);
    description.getParameterDescriptionByName(parameterName, out PARAMETER_DESCRIPTION parameterDescription);
    return parameterDescription.id;
}
PARAMETER_ID m_LeftFootSurfaceParamID;
PARAMETER_ID m_RightFootSurfaceParamID;
m_LeftFootSurfaceParamID = FMODUtility.GetLocalParameterID(m_LeftFootstepEmitter.EventReference, "SurfaceType");
m_RightFootSurfaceParamID = FMODUtility.GetLocalParameterID(m_RightFootstepEmitter.EventReference, "SurfaceType");

I assume it’s getting the parameter from the event itself rather than an instance of the event, at the moment it looks like this is the only reliable way of grabbing parameter IDs from an emitter in awake as an emitter instance isn’t created until we play it. I just want to check if this is a sound approach as I can’t see another way other than playing the emitter in awake then caching a parameterID. Also checking that we should be setting the parameter after playing or before? before seems more logical to me but at the moment it doesn’t seem to register unless set afterwards.

Let me know if something isn’t clear

Thanks for your time!

Hello, any update on this?

Thanks so much!

Apologies for the delayed response!

From what you’ve described, the issue you’re running into is a result of how emitters handle their event instances - an instance is only created when StudioEventEmitter.Play() is actually called, so attempting to call API functions on the emitter’s instance before then will return ERR_INVALID_HANDLE since the instance doesn’t exist.

Short of modifying StudioEventEmitter to your needs, the recommended solution would be to do as you’ve already done, and grab the EventDescription from RuntimeManager instead of the non-existent event instance.

In theory, setting a parameter either before or after starting an instance should work fine. However, since the StudioEventEmitter’s instance doesn’t exist until it actually starts playing, you won’t be able to directly set it beforehand.

A workaround for this would be to take advantage of the existing array StudioEventEmitter.Params that is used when you add an initial parameter value to a Studio Event Emitter in the Inspector. Then, when the emitter is played, the instance’s parameter value will be set as if you’d set it via the Unity inspector. If you’re reaching this point, however, it may be worth looking into creating your own script to handle event instances instead of relying on StudioEventEmitter.