I use an Actor Component to add a behavior to my actors and pawns.
Now I realized that literally all of my actors and pawns have that component,
thus I created classes AMyActor and AMyPawn and do the setup of the component in there and all my actors and pawn inherit from MyActor and MyPawn.
So far so good.
I still have code duplication, because the setup work happens in both, AMyActor and AMyPawn.
That is some code in the constructor and the OnConstruction script.
Now I wondered: I might as well have APawn directly inherit from MyActor instead of AActor. But how do I go about it?
Just changing code inside “Pawn.h” shouldn’t exactly break stuff, but I don’t know.
Another option is to literally copy “Pawn.h” and “Pawn.cpp” into my project and make the changes there.
Hey, I apologize for not elaborating. As a suggestion meant inherit to create custom parent classes for the actors and pawns accordingly for the scope of the project without editing engines default (unless you dont mind to do so). This is what I would do (and am currently doing in a relatively small project).
Would also like the opinion of other more experienced since this interests me as well.
Pawn inherits from actor so theres also the option to modify that class in your case.
Duplicating a little code in Actor and Pawn (and Character, for that matter) are pretty much going to be staples of working in UE5.
Hacking the engine to save yourself a few lines of cut/paste is not a time efficient choice. Maintaining hacks on the engine long term will take vastly more time and energy than just copying a few lines of code in your actor/pawn/character class.
I tried to copy APawn into my project, but this causes all kinds of problems, too. I don’t even understand all the compiler errors, but the ecosystem is built around the fact that there is exactly one pawn implementation. Renaming to AMyPawn breaks delegates (and other stuff, apparently).
Generally any time you find yourself needing to modify Engine code, that should be a red flag that there is probably an easier way to do something.
There are definitely times when you MUST modify the engine, but in general that’s not something you WANT to do, if it can be avoided.
As for Pawns, Epic does not generally use pawns for anything. They make shooters, and everything they do is a Character.
They provide the Pawn so you can use it instead of a Character, in case you need something with a non-capsule primitive as its root component, but if you go that route, you will have A LOT of code duplication to make the Pawn even close to the level of functionality of the Character.
This is by design and it’s just a necessary evil.
The majority of UE projects, it seems, just uses the Character class and ignores the Pawn. If you decide you want custom pawns with custom movement etc, that’s a perfectly valid choice, but involves a lot of code duplication. 10,000s of lines of code. (Either that, or buy plugins others made where they did that code duplication for you).
The easiest way to work with UE is just to ignore the Pawn, and use the Character as a base instead.
Fortnite has vehicles too though, so how do those work? Anything that requires custom movement, or anything that doesn’t quite fit into the capsule model may actually require Pawn. Think Aerial / Space games / RTS… Custom hybrid vehicles… Complex non-bipedal characters… Implementing the added functionality for online multiplayer and so on, is just part of the added workload of UE sadly. Of course it’d be great if this was all just built-in and included for free like the CMC. There were some interesting threads about this in UE4 (debating the pros / cons of tweaking CMC for non-standard uses). Can’t seem to find them now and don’t remember all the gotchas. But for all the immediate benefits of Character, there’s lots of edge cases too, meaning UE devs are unlikely to escape Pawn.
To clarify, they use pawns in their games. They just don’t provide engine code for replicated pawn movement.
So if you want to use a character, they do all the work for you. If you want to use a custom pawn, you have to do all that work yourself. (Or buy one of the plugins that does it). Anyway, that work is not included in the engine.
This is a well-known problem in object oriented class hierarchies, related to the “fragile base class problem” and “god object” anti-patterns. (And one of the valid criticism of object-oriented design, btw.)
You will have to fork the engine, build it yourself, and update APawn to derive from AYourActor – there’s no way to do this as a “plug-in,” because the inheritance of APawn is baked into the built engine and editor.
If your main concern is just code duplication, and the class duplication is OK for you, then you could break the common setup out into a separate free function, and call that free function from both places. If the function needs some standard class members, you’ll probably want to make that a template function, that takes a pointer to an object of any class that has those members.
You could also use the template-inherits pattern to build the standard setup. You’d make AYourActor and AYourPawn derive from YourTemplate<AActor> and YourTemplate<APawn> respectively. Except I’m not sure UnrealHeaderTool will be very happy with that.
The template-inherits pattern seems more interesting, still. I will try that out.
And yes, this is just about code duplication. But code duplication leads to complexity that is avoidable by some better design (usually). I already shoot myself in the foot on a regular basis when I don’t remember where (or if at all) I implemented some functionality - Unreal doesn’t only provides endless option to implement this or that, often it’s difficult to say with certainty where stuff belongs.
The sum of those ambiguities make up the complexity that will slow me down in the long run, when implementing new features, but also when I try to refactor my code.
Yes a component works well as an interface for different types of actors.
I was working on a plugin for creatures and encountered the similar issue. Initially I created a base class of all creatures, and a player character inheriting it. Issue emerged when bringing them to my project: game animals inherit creature and game players inherit player character, and their hierarchy is not as expected.
Finally I made only one character class and add all additional functions (player controlling, monsters, NPCs,…) in independent components. By browsing specific components in the character instance you can easily identify what class it is. To add new functions, simply define new components and add to your actor.