Help with multi-platform plugin development

Hey everybody,

I am currently developing a plugin that is used to quickly setup a project with basic replicated pawns. There a different classes of pawns for different platforms and needs. Right now I have a pawn that uses motion controller for windows VR, and a pawn that is meant to be used with a touch screen. I want to be able to switch between the different pawns automatically, the developers settings up the scene shouldn’t have to manually change the default pawn depending on the build.

The problem I am facing right now is that I can package the plugin for Windows fine, but not, for example Android, because the VR code doesn’t compile for that platform. I have changed my .Build.cs file to only include the VR code like so:

if(Target.Platform == UnrealTargetPlatform.Win32 || Target.Platform == UnrealTargetPlatform.Win64)
            {

                PrivateDependencyModuleNames.AddRange(
                new string[]
                {
                    "HeadMountedDisplay",
                    "SteamVR"
					// ... add private dependencies that you statically link with here ...
				}
                );

                PublicIncludePaths.AddRange(
                new string[] {
                    "Runtime/HeadMountedDisplay/Public"
					// ... add public include paths required here ...
				}
                );
            }

And in my classes I ignore the code that uses those dependencies like so:

	LeftMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Left Mesh"));
	LeftMesh->SetIsReplicated(false);
	LeftMesh->SetStaticMesh(ControllerObj.Object);
	LeftMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);

	RightMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Right Mesh"));
	RightMesh->SetIsReplicated(false);
	RightMesh->SetStaticMesh(ControllerObj.Object);
	RightMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);

#if PLATFORM_WINDOWS
	LeftController = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("Left Controller"));
	LeftController->SetupAttachment(Root);
	LeftController->Hand = EControllerHand::Left;
	LeftController->PlayerIndex = -1;
	LeftController->bDisableLowLatencyUpdate = true;
	LeftController->SetCollisionEnabled(ECollisionEnabled::NoCollision);

	RightController = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("Right Controller"));
	RightController->SetupAttachment(Root);
	RightController->Hand = EControllerHand::Right;
	RightController->PlayerIndex = -1;
	RightController->bDisableLowLatencyUpdate = true;
	RightController->SetCollisionEnabled(ECollisionEnabled::NoCollision);

	RightMesh->SetupAttachment(RightController);
	LeftMesh->SetupAttachment(LeftController);
#endif

and in the header file:

#if PLATFORM_WINDOWS
#include "MotionControllerComponent.h"
#endif

The problem with this method is that it doesn’t work with the UPROPERTY macro. It will give an error, I think since 4.13, if I try to do this in the header file:

	UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite, Category = "Vive Pawn")
	UStaticMeshComponent* LeftMesh;

	UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite, Category = "Vive Pawn")
	UStaticMeshComponent* RightMesh;

#if PLATFORM_WINDOWS

	UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite, Category = "Vive Pawn")
	UMotionControllerComponent* LeftController;

	UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite, Category = "Vive Pawn")
	UMotionControllerComponent* RightController;

#endif

It will output the error:

Error: UPROPERTY inside this preprocessor block will be skipped

To work around this problem, I write this instead:

#if WITH_EDITOR || PLATFORM_WINDOWS

So, I am not super familiar with how UE4 compile process works, but I think UAT doesn’t know the macros PLATFORM_WINDOWS and throws an error when it encounters it, but with writing a known macro in a or operation first, it will accept it without looking at the other condition. I think that later in the compiling process, the macro WITH_EDITOR doesn’t mean anything to visual studio but PLATFORM_WINDOWS does, and is able to remove that section of code from the build. But that’s where I’m not sure.

With this trick, I am able to compile the code and package for windows. But when I try to package for Android, it gives me the following error:

UATHelper: Packaging (Android (ETC2)): UnrealBuildTool: D:/Unreal Projects/TheiaPluginDev/Plugins/TheiaPlugin/Intermediate/Build/Android/UE4/Inc/TheiaPlugin/TheiaPlugin.generated.cpp(237,2) :  error: unknown type name 'HEADMOUNTEDDISPLAY_API'
UATHelper: Packaging (Android (ETC2)): UnrealBuildTool:         HEADMOUNTEDDISPLAY_API class UClass* Z_Construct_UClass_UMotionControllerComponent_NoRegister();

So it would seem that the motion controller code is still being included in the build. There is only one class where the motion controller component class is used and I am sure I removed every references to it with the #if macro.
I am new to cross-platform development, is this the correct way to approach this problem? It seems like a pain to segment the code with pre-processor directives, is there a better way to do this? Am I missing something?

Thank you for the help!