Conditionally defining UFUNCTIONs

I am developing a plugin that works on both UE4 and UE5. UE5 has the UAudioDeviceNotificationSubsystem which I am using in the following manner:

// in definition of class "Foo"
UFUNCTION()
void OnDefaultAudioRenderDeviceChanged(EAudioDeviceChangedRole AudioDeviceRole, FString DeviceId);

// in Foo.cpp
#if ENGINE_MAJOR_VERSION == 5
UAudioDeviceNotificationSubsystem::Get()->DefaultRenderDeviceChanged.AddDynamic(this, &Foo::OnDefaultAudioRenderDeviceChanged);
#endif

void Foo::OnDefaultAudioRenderDeviceChanged(EAudioDeviceChangedRole AudioDeviceRole, FString DeviceId)
{
#if ENGINE_MAJOR_VERSION == 5
// do stuff
#endif
}

This works fine on UE5 but I cannot get it to compile on UE4 no matter what I try. Obviously EAudioDeviceChangedRole is not defined in UE4 so I am trying to conditionally define it but cannot manage to do so in a way that would work on both UE4 and UE5. UHT either complains about defining stuff within preprocessor statements, about EAudioDeviceChangedRole not being a UCLASS, USTRUCT or ENUM or about duplicate definitions.

Is there any way to make use of UAudioDeviceNotificationSubsystem on UE5 while still having the same code files for UE4 (even if it is a dummy OnDefaultAudioRenderDeviceChanged definition doing nothing). The most relevant topic I found was #define doesn't work with UFUNCTIONS which suggests this is not possible, but here’s hoping something changed or the right person didn’t see that topic. Surely this is a limitation that someone else has encountered/overcome since UE5 was released?

Would it not be easiest to just have two separate versions- one for UE4 and one for UE5?
Seeing as UE4 won’t be getting anything other than crucial devkit upgrades (no new features), it would probably be easier to develop for the versions separately.

2 Likes

Easier depends on the viewpoint :wink: Sure, it is not difficult to have different branches for UE4 and UE5, but up until this issue, it just wasn’t needed as we are using very few UE5-only features and a couple of ifdefs here and there have managed to do the job so far.

I ended up not needing to implement this at all but what I learned in the meanwhile is:

  • For this specific example, I didn’t need to use AddDynamic and UFUNCTION - e.g. AddUObject and normal function worked just as well and circumvented the macro-related problems to work on UE5 and do nothing on UE4.
  • DefaultRenderDeviceChanged was not the delegate I needed - it was DeviceSwitched.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.