There are better ways to reuse code without increasing dependency, reducing cohesion, namespace bloat, and violating of the principle of encapsulation. For example, if the character class requires the functionality of the pawn class it should include a member of type pawn. To preserve the conceptual relationship between character and pawn, there should be a rule that classes of type character can include members of type pawn but classes of type pawn cannot include members of type character.
The gameplay framework is the result of 20 years of legacy code and bodges for backwards compatibility. It’s quite terrible. And with Fortnite being a live service game, Epic cannot make any large scale breaking changes.
Many had hoped for UE5 to bring new light to this tunnel, but then it ended up being UE4.28 with a Nanite and Lumen plugin. Oh well…
Make your own Interfaces and you don’t have to worry too much about their class hierarchy.
I too had hoped UE5 would move away from so much inheritance. Stuff like spectators can’t be a character because the spectator class already inherits from pawn. Problems like this go through the whole gameplay framework.
Interfaces are also very clunky to use and full of longstanding bugs (whether an interface is pure c++, blueprint extended from c++, or pure blueprint all interacts in broken ways and sometimes fails to interoperate https://answers.unrealengine.com/questions/567469/interface-as-paramter-on-call-from-blueprint-to-c.html).
On top of that, every static mesh actor is bloated with stuff like an input component pointer and damage delegates it will never use and even networking related stuff, but at least they have fairly recently added sparse delegates to help with some of that (sizeof(AActor) used to be I think close to or over 1KB).
I haven’t looked at any of the new modular game features plugin stuff in UE5 yet, does it keep its data outside of the actor similar to an ECS or have they had to add in more delegates all over the place to support it?
Once C++ finishes standardizing reflection it would be worthwhile to revisit a lot of stuff, like UHT. It could also allow for a move to more aggregation over inheritance while enforcing compile time constraints on it to still provide structure, but without the limitations and tendency towards AActor god-object (God object - Wikipedia) caused largely by single inheritance.