Hello, I’ve not run into this issue in the past because I’ve never had the need to inherit from multiple classes without writing my own.
I am using the AdvancedSessions plugin to streamline access to Steam for my packaged builds. I am using this on top of Lyra.
I want to be able to create a GameInstance class that inherits functionality from both AdvancedSession’s UAdvancedFriendsGameInstance AND Lyra’s ULyraGameInstance in order to be able to make updates to future builds without much fuss in case the underlying architecture changes a bit.
I am aware of how to handle the diamond problem using virtual when I have two parent classes with common ancestors (UGameInstance in this case)…however…this is not standard C++, I am being forbidden by UE to be able to do this because:
1>C:\Users\Nephera\Documents\Unreal Projects--StarterGame\Source\LyraGame\Public\MyGame\Game\MyGameInstance.h(13): error : Class ‘ULyraGameInstance’ is not an interface; Can only inherit from non-UObjects or UInterface derived interfaces
So it’s not quite as simple as inheriting from both classes like this:
#pragma once
#include "CoreMinimal.h"
#include "AdvancedFriendsGameInstance.h"
#include "System/LyraGameInstance.h"
#include "MyGameInstance.generated.h"
/**
*
*/
UCLASS()
class LYRAGAME_API UMyGameInstance : public UAdvancedFriendsGameInstance, public ULyraGameInstance
{
GENERATED_BODY()
// Header functions and variables here
};
I am not sure what the best practice is for approaching this, as it seems like the best course of action at this point is to derive my class from only one of them (probably AdvancedSessions’ UAdvancedFriendsGameInstance) and take all of the code from the other and implement it manually. This adds a little bit of overhead in case there are updates to the files that I am pulling the code from (which will probably be Lyra’s ULyraGameInstance). I’d like to avoid that overhead if at all possible.
Any ideas on how I could approach a resolution? I need the functionality from BOTH UAdvancedFriendsGameInstance AND ULyraGameInstance.
Yeah, you’re basically in a bind here because there’s no good solution. As you found, the Engine is pretty adamant about only having one non-interface base class.
The Game Instance is probably one of worst cases for extending in plugins because it doesn’t have a good way to combine things from multiple plugins.
In addition to the option you already suggested of manually incorporating Lyra into your game instance derived from AdvancedSessions, you might be able to leverage game instance subsystems.
The way that would probably work is that you’d branch the lyra game instance into your code and tweak it to be a Game Instance Subsystem instead. You’d have to do the same with the Common Game Instance that Lyra derives from. But once you do that, it would be easier to incorporate changes to the Lyra source into your version since you’d just merge and you’d have minimal changes.
Unfortunately I’m not entirely sure how effective this would be. At least the Common Game Instance uses a couple overrides that you can’t directly implement from a subsystem.
You might be able to split the difference and leverage the fact that you don’t have to match 1:1 headers and cpp files. So you’d have to manually merge the header requirements for both systems, but you could branch (just like the subsystem solution) the LyraGameInstance cpp into your own code to provide those function implementations while leaving your own cpp for your own overrides. Then you could still get the easier merges, but still a complicated source setup.
Thank you for the reply. This is kind of what I was afraid of. Been wrangling this for a few days now and I’m leaning toward making my own game instance class and copying the functionality from either of the two would-be parents manually (probably Lyra since we’re doing a total conversion anyway) and using the AdvancedSessions’ UAdvancedFriendsGameInstance as its official parent.
My concern now is that there code elsewhere in the Lyra codebase, like in B_MusicManagerComponent for example which takes the game instance and casts it to B_LyraGameInstance. That would now fail. So all of those classes would require a rewrite.
This seems like it’s going to get real messy real quick.
Well, Lyra is meant as a sample not a library. So any of that other code you would want to modify anyway as part of incorporating into your project from Lyra. Maybe even rewrite them better so they don’t need a game instance (which feels a little suspect to me without having looked at any of the code).
I suspect they’re using the GameInstance because it’s one of the few things that isn’t torn down in between server travels, so they put the music manager in there along with some other stuff for encryption and the like.