We are supporting multiple users with playfab in UE4 using C++. For that we store the UPlayFabAuthenticationContext we get from login per user and use it later in all the requests to differentiate between users. It works fine in editor but in a monolithic packaged game we get crashes.
I digged into this and the problem is that the playfab plugin passes UPlayFabAuthenticationContext around as a TSharedPtr. The problematic code is in PlayFab.h:
template<typename T> TSharedPtr<T> MakeSharedUObject() { return TSharedPtr<T>(NewObject<T>((UObject*)GetTransientPackage(), NAME_None, RF_Standalone), [](T* Instance) { // Recommended way of destroying UObjects according to https://udn.unrealengine.com/questions/402414/view.html Instance->ClearFlags(RF_Standalone); }); }
The code tries to keep the created object alive by supplying the RF_Standalone object flag and let it be garbage collected by removing the flag in a custom deleted. This will not work outside of the editor AFAIK.
We work around the problem by storing the UPlayFabAuthenticationContext reference as a TStrongObjectPtr internally once we get it from playfab. This will keep it alive. It looks like this is what the playfab code is actually trying to archive.
Currently internally in playfab code the TSharedptr<UPlayFabAuthenticationContext> is created right before passing it to a delegate for the game to consume. If the TSharedPtr is used directly in that delegate there is no problem. But if the game (or possibly in the playfab plugin?) holds a reference with this TSharedPtr by capturing it in a lambda or something similar this will cause very hard to find crashes. And the natural thing you would expect from a shared pointer would be to be usable for holding a reference to an object (otherwise you could just pass in a raw pointer to the delegate).
As said we can work around this but I think you will want to fix this. If not please put least some warning in the code/documentation.